You are on page 1of 78

A Simplified Linear Refreshable Braille Display

by Christopher W. Tullar

A Thesis Submitted to the Graduate Faculty of

APPALACHIAN STATE UNIVERSITY

in Partial Fulfillment of the Requirements

for the degree of

MASTER OF SCIENCE

in Applied Physics

December, 2001
A Simplified Linear Refreshable Braille Display

A Thesis by Christopher W. Tullar

December, 2001

Approved By:

__________________________________________
Thomas L. Rokoske, Ph.D.
Chairperson, Thesis Committee

__________________________________________
J. Sid Clements, Ph.D.
Member, Thesis Committee

__________________________________________
Brian W. Raichle, Ph.D.
Member, Thesis Committee

__________________________________________
Anthony G. Calamai, Ph.D.
Chairperson, Department of Physics and Astronomy

__________________________________________
Judith E. Domer, Ph.D.
Dean of Graduate Studies and Research
Copyright by Christopher W. Tullar, 2001
All Rights Reserved
A Simplified Linear Refreshable Braille Display

Christopher W. Tullar

Abstract

A linear braille display has been developed which is simple in design so that it

may be of low cost. The display is activated by movement of the hand and automated by

the use of an 8051 microcontroller. The braille display uses a 40-cell line composed of

standard-sized braille cells on a magnetic display actuated by three solenoids, a unique

design developed at ASU. These cells are the same size as used in braille books, so they

are easy to read. Text to be read is first converted to an ASCII document, and then

downloaded to the braille display for reading. The instrument uses sound to guide the

user through the process of reading and is designed to be simple to use.

iv
Acknowledgments

I would like to thank my thesis advisor, Dr. Tom Rokoske, for starting the

refreshable braille display projects at ASU, giving me something neat to do for a year,

and for his willingness to help on every occasion I asked for it. Mr. Robert Miller

deserves a great deal of thanks for his constant help in the mechanical design process, his

excellent machining skills, and his dedication to make room for my schedule. I would

also like to thank Dr. Sid Clements, who helped at troubleshooting software, gave ideas

for electronic hardware, and let me all but live in his computer lab. I wish to thank

Graduate Studies and Research at ASU for the grant that partially funded my project.

Thanks to Guardian Electric, who donated the solenoids used in this project. Thanks also

to Mr. Josh Hastings who seems to always save the day. Thanks to Mr. Mike Abaray

who did some footwork and sent me a huge history on braille displays. And I would

finally like to thank my wife Raeleen, who helped me with the thought process, helped

build the testing apparatus, and who is my personal presentation wizard.

v
Table of Contents

Page

List of Figures……………………………………………………………….……...viii

Chapter 1: Introduction……………………………………………………………. 1

1.1 Braille……………………………………………………………….……….. 1

1.2 Grades of Braille……………………………………………………………... 1

1.3 Ways to Reproduce Braille…………………………………………………... 3

1.4 Refreshable Braille Displays………………………………………………….3

1.5 Previous ASU Braille Displays……………………………………………….5

1.6 The Proposed Machine………………………………………………………. 7

Chapter 2: Mechanical Hardware…………………………………………………. 12

2.1 Pinboard……………………………………………………………………… 12

2.2 Solenoids……………………………………………………………………...13

2.3 Solenoid Carriage……………………………………………………………..14

2.4 Solenoid Carriage Mounting………………………………………………….16

2.5 Mounting Plate and Rails……………………………………………………..17

2.6 Optcouplers and Encoder Strips………………………………………………18

2.7 Shuttle………………………………….…………………………………….. 19

2.8 Eraser………………………………………………………………………… 20

Chapter 3: Electronic Hardware……………………………………………………21

3.1 SBC-51………………………………………………………………………..21

vi
3.2 Optocouplers………………………………………………………….……… 22

3.3 Solenoid Signals……………………………………………………………... 22

3.4 Shuttle Switches……………………………………………………………....23

3.5 Speaker………………………………………………………………………..23

3.6 Handshaking…………………………………………………………………. 23

Chapter 4: Software…………………………………………………….…………. 24

4.1 Getting Started………………………………………………………………...24

4.2 Overall System Objective……………………………………………………. 24

4.3 External Buffer………………………………………………………….…….

25

4.4 Internal Buffer………………………………………………………..……….25

4.5 External Interrupts…………………………………………………………… 28

4.6 Polling Interrupts…………………………………………………………….. 30

4.7 Sound………………………………………………………………………… 30

4.8 Monitor Display……………………………………………………………… 31

4.9 Testing………………………………………………………………………...32

Chapter 5: Discussion……………………………………………………………... 34

5.1 Review of Accomplishments………………………………………………… 34

5.2 Problems……………………………………………………………………... 36

5.3 Possible Future Endeavors……………………………………………………36

References…………………………………………………………………………..38

vii
Appendix A: Mechanical and Electronic Schematics……………………………...39

Appendix B: System Software……………………………………………………..50

Vita…………………………………………………………………………………..66

List of Figures

1-1 Refreshable Braille Displays………………………………………………….. 4

1-2 Xiong Lu’s Rotating-disk Display……………………………………………..5

1-3 Bruce Stansell’s Rotating-disk Display ……………………………………….6

2-1 Pinboard Cross-section………………………………………………………...13

2-2 Conceptual Drawing of the Solenoid Carriage………………………………...15

2-3 Close-up of the Solenoid Carriage……………………………………………..16

2-4 View From Below the Mounting Plate………………………………………...17

2-5 Conceptual Drawing of the Solenoid Carriage,

Mounting Plate, and the Teflon Sliders……………………………………..… 18

2-6 Optocouplers and Encoder Strips……………………………………………... 18

2-7 Shuttle and Eraser Mechanism………………………………………………... 20

3-1 System Electronics……………………………………………………………..21

4-1 Braille Cell Encoding Byte Translation………………………………………..27

4-2 Filling the Internal Buffer………………………………………………………28

4-3 Cell Direction/Counting Method……………………………………………… 29

4-4 Apparatus for Testing Software………………………………………………..33

viii
5-1 The Finished Refreshable Braille Display……………………………………. 34

A-1 SBC-51 Circuit Diagram…………………………………………………...… 40

A-2 Circuit Diagram for Optocouplers….………………………………………… 43

A-3 Output Control Circuitry……………………………………………………... 44

A-4 Circuit/wiring Diagram for Shuttle Switches………………………………… 45

A-5 Placement of Interior Components…………………………………………… 46

A-6 Specifications for Solenoid Carriage Parts…………………………………… 47

A-7 Specifications for the Adjustable Mounting………………………………….. 48

A-8 Specifications for the Mounting Plate………………………………………... 49

ix
Chapter 1: Introduction

1.1 Braille

Perhaps the most significant invention bestowed upon the blind has been braille.

This international system of reading for the blind has endured for over 175 years without

significant rivalry from any other form of written communication. Braille is found at

automatic teller machines, elevators, hospitals, on public signs and menus, and many

other, often unnoticed, places.

Before the advent of braille, the blind read ordinary letters in relief. This method

was cumbersome and difficult to read quickly. However, around 1824 in Paris, France, a

fifteen-year-old boy by the name of Louis Braille completed a full sixty-three-character

code that used cells made of six easily producible dots. He was directly influenced by a

new code shown to him by a French artillery captain Charles Barbier. The captain had

developed what he called “night writing” for messages delivered in the dark within the

army. He almost immediately tried to make it accessible to the blind under the name of

“sonography” and in doing so met Louis Braille, who developed the idea into what is

today’s most common reading method for the blind.1

1.2 Grades of Braille

Despite the ease of creating braille cells with the proper tools, it soon became

apparent that transliterating every letter (English or otherwise) into braille was going to

be a problematic practice. The characters could not be the same size as written text

because of the resolutional capability of the average human fingers. So they were made

1
2

larger and their size became standardized for the most part (the Japanese have slightly

smaller characters).2 This meant that a page of braille was immensely larger than a page

of standard written text. Also, braille could only be written on one side of a page because

the dots were punched from the reverse side. So, to contain the same information, a

braille page would have to be four times as long and three times as wide as a printed

page. Naturally, a page that size would be hard to handle, very tedious to transcribe, slow

to read, and would make impractical book sizes.

As a result, many braille contractions were created. Groups of two or more

letters, as well as many words, were assigned their own characters, or groups of

characters. Every contraction had to be methodically chosen to ensure it would be

efficient to read. This new contracted braille was dubbed Grade II braille and is the type

most widely used today. Thus, the uncontracted form of braille became Grade I.3

Some criticize Grade II of being arcane and difficult to use. There are many

nested rules regarding when contractions should be used and several common symbols

are not represented. Early on, many of the contractions were created in direct relation to

Christianity, because a main focus was enabling the blind to read the bible, and many

today feel that too many contractions were used for this practice. There are many other

codes in existence and people are constantly working on new ones. Most of the current

projects involve eight-dot cells and include characters to enable the blind to read

mathematical and other non-Latin symbols. It should be noted that even with contracted

braille, a book that could fit in a pocket in printed text form would be several large

volumes in Grade II braille. Nevertheless, Grade II documents are considerably smaller

than uncontracted braille documents.


3

1.3 Ways to produce/reproduce Braille

Braille can be produced in several ways. The simplest form is with a slate and

stylus. In this method, the braille is manually embossed into paper with a stylus. Using

guide depressions, the stylus presses the paper into depressions on the slate.

Unfortunately, this method requires writing backwards because the braille is embossed

from the under-side. Similarly, a braille typewriter embosses a page mechanically. A

more modern and rapid way to produce braille is with a braille printer. In this case a

computer sends the printer information and the printer embosses the braille on a page.

This is usually done with a lot of pressure, sometimes up to ten tons per braille cell!4

Many braille printers, called interpoint printers, can emboss braille on both sides of a

page by adjusting spacing on each side. The main disadvantage to braille printers is that

they are very noisy. They routinely produce noise at levels of 70dba or more.4 Many

models on the market today have sound-attenuating hoods to reduce noise. Finally, there

is the refreshable braille display, which is a device that produces braille electronically by

raising and lowering pins which correspond to cell dots. Since this is the main concern of

this thesis, it will be discussed in detail.

1.4 Refreshable Braille Displays

Refreshable Braille displays were first introduced in the mid-1970’s and were

electromechanical displays that used tiny solenoids to move the pins. By the late 1970’s,

piezoelectric displays, first introduced by Oleg Tretiakoff, were on the market. The

piezoelectric cell consists of a small ceramic substrate which, when around 200 volts is

applied, bends and activates a pin. These actuators are small, which is preferred, but they

are expensive. The first mass produced display, the VersaBraille, was based on his
4

design and manufactured by TeleSensory in the early 1980’s, and by the end of the

1980’s everything on the market was piezoelectric.5

Figure 1-1: Refreshable Braille Displays – 20, 40, and 80 Cell Models6

Manufacturers of refreshable braille displays have been motivated all along to

find a cheaper alternative to piezoelectric technology. One idea was a moving braille

cell, tried by IBM, which slid along a track and merely punched braille into the finger.

This was deemed unacceptable because the movement of the finger over the braille is

important. In another prototype, dots were pressed into a moving belt of Mylar and then

pressed flat again after being read. This was tried more than once by separate companies,

but was rejected because the Mylar wore out too quickly, was noisy, and felt unnatural.

The pneumatic display was also a promising technology which was abandoned. One

attempt at cost efficiency called the BrailleMate (TeleSensory) eliminated all but one

cell.5 In the early 1990’s, more experimental methods were being tried, mainly fluids

technology and with materials which change their integrity when a voltage is applied.

And then there are the rotating display ideas. In this technique, the fingers remain

stationary and the braille, constantly being refreshed, moves underneath. Only three

prototypes were accounted for in the research for this paper. Two rotating disk displays
5

were created at Appalachian State University which will be discussed in detail. A

prototype built at NIST (National Institute of Standards and Technology) in Gaithersburg,

Maryland, uses a rotating drum with the braille cells on the perimeter of the drum. This

machine uses stationary solenoids to punch specially designed pins into one of two states,

up or down.7

Of the braille displays that exist on the market, the most important and

competitive features are those that involve navigation through a screen of text. Some of

the newer models use two-dimensional navigational control, where horizontal and

vertical screen positions can be changed. Other competitive features include

compatibility with Windows environments and speech synthesis. Speech software,

though not replacing the reading of braille, is becoming a standard in technology for the

blind. In the refreshable braille display, however, speech synthesis is usually confined to

simple messages giving information about text attributes or graphics located at the cursor

position. 8

1.5 Previous ASU Braille displays

Figure 1-2: Xiong Lu’s Rotating-Disk Braille Display (1993)


6

Xiong Lu’s prototype was built at Appalachian State University and completed in

1993. This showed that a display was feasible in which the actuators remain stationary

and the pins move above them by means of a rotating disk. This display has only two

refreshable cells which are larger than standard braille cell size, and its operation is

relatively slow. The cells are held in place by means of a spring mechanism. One

optocoupler sensor informs the computer that the six solenoids are in line with the pins

and a character was formed on the display. This machine is an external apparatus driven

by an IBM PC.9

Figure 1-3: Bruce Stansell’s Rotating-Disk Display (1997)

Bruce Stansell’s prototype was completed in 1997. The machine’s display

consists of 36 braille cells lining the perimeter of a rotating disk. The pins, which

correspond to the individual dots, are held by magnetic attraction in a rotating disk.

Holes were drilled through a piece of flexible magnetic material sandwiched between two

pieces of plastic. The pins were inserted into the holes and were kept from falling by

means of being attracted to the wall of the hole. This is by no means a bistable

mechanism, which would be ideal, but greatly simplified the machining of the pin and
7

proved to be effective. This method had two drawbacks however, both related to the

instability of the material. First, the flexible material is difficult to machine, making the

holes very tedious to drill and leaving the end result less than accurate. Second, it

absorbs moisture and swells. When the machine was examined three years after its

completion, nearly all of the pins had to be worked into moving condition again.

In Bruce Stansell’s prototype, six optocoupler sensors determine when one of the

six solenoids is in line with a pin. Text is translated on the PC by ASCII-to-Grade II

software available through the American Federation of the Blind. The encoded dot file is

then transmitted to the braille display. The user can scroll 50 or 150 cells at a time, and

there are also the options of scrolling by word or sentence. The display can insert

bookmarks to save the reader’s place in the file. This prototype includes a keypad

interface, LCD display, both serial and parallel ports for PC interface, and adjustable disk

speed control. Software is contained both on-board the display and on the IBM PC.

Maximum reading rate is one hundred fifty cells per minute, or, using an average word

length of five characters, around 30 words per minute.10

1.6 The Proposed Machine

As sophisticated technology makes braille easier to produce, the blind are faced

with the unavoidable problem of high cost. Currently braille printers cost from $1,700 to

$80,000 and refreshable braille displays cost from $3,500 to $15,000 (usually around

$5,000 per 40 cells).11 Unfortunately, most visually impaired people can’t afford these

prices and the available machines are limited mainly to business and educational uses.

The current project and many others are dedicated to making affordable braille displays

using innovative technology.


8

The goal for this thesis was to create a greatly simplified in-line refreshable

braille display which is reliable and easy to use, using the fewest, most cost-efficient

parts. The following are the desired features for the proposed display:

Standard Cell Size

Due to the size limitations of the actuators used in most braille displays, the cells

are larger than standard size. Since the blind prefer to read standard cell size and spacing,

this machine should ideally have these characteristics. This has been shown possible by

Stansell’s prototype.

Dependable Pinboard

An innovative concept in Stansell’s display was to use a magnetic material to hold the

braille pins in place. Holes were drilled through a flat vinyl magnet and the pins were

inserted through the holes.10 Unfortunately, the material which was chosen was rather

unstable and subsequently became brittle and left residue on the pins. When the machine

was examined after several years of not being used, it was found that many braille pins

were locked fast and required considerable pressure to free them. It should also be noted

that machining the holes was difficult and at the end of the project no suitable lubrication

had been found to improve the stability of the pinboard. So without question this method

of holding the pins must be improved to ensure reliability of the display.

Shuttle

An innovative technique to be implemented during the present research is the use

of a shuttle which will move the solenoid carriage underneath the braille pins with the

movement of the hand. The shuttle is to be similar in size and function to a computer
9

mouse, and its linear position will be slightly offset from the solenoid carriage so that

each cell will be formed in advance of the hand's position.

There are several benefits to the use of a shuttle. Besides reducing cost, noise

(mechanical and electrical), and software, it would also ease navigation and spacial

orientation within a document. This could be done by adding several buttons to the

shuttle, similar to those on a mouse. Two buttons will be used for scrolling back and

forth through the document, and in a more advanced version, a third button could be

added to act as a left mouse click, for example. This feature would eliminate the need for

“touch dots” which are sensors situated above each braille cell in many commercially

available models to position the cursor.

If the proposed braille display system is to be thought of in analogy with a dot matrix

printer, with solenoids making up the “print head”, several disadvantages come into view.

In order to provide a maximum reading rate of 100 - 200 words per minute, a fast motor

would be needed to ensure that the user would not have to wait to read a line. This would

require more software, more hardware, and therefore more complexity and cost. It would

be desirable for the reader to control the reading speed.

Three actuators

There will be a carriage on which the solenoids travel beneath the pins. The

solenoids will strike the pins at designated times determined by the exact position of the

solenoid carriage. However, horizontal travel only requires three actuators, as there are

three rows of dots. So the solenoid carriage need only house three solenoids. Compared

to commercial displays, this saves 237 parts! Compared to Stansell’s prototype, this

eliminates the need for three solenoids at a total saving of $60.00.


10

Speed

Average braille reading rates are under 100 words per minute in Grade II braille,

and most common rates are from 50 - 70 words per minute. However, some can read

over 300 words per minute, which if read aloud would be very fast speech.12 Since an

ASCII to Grade I translator will be used, producing one hundred words (around 500

characters) per minute would be a conservative upper limit. Grade I is approximately

20% longer than Grade II, so it would take 20% longer to read.13 The maximum speed

of this machine in Grade I is expected to be at least one hundred fifty words per minute.

A software “governor” will be added to protect the hardware in the event that the

maximum speed is exceeded.

On-board translator

The device will have an on-board translator which will translate ASCII into Grade

I braille. This feature will maintain the machine’s independence and make the system

easier to operate. In text-editing modes, many braille displays switch from Grade II to

the Nemeth Code, which is a character-to-character translation of ASCII to braille. This

is used so the user can read each character on the screen when editing text. However, this

is not comfortable to read. Translating ASCII to Grade I avoids the contractions and

exceptions of Grade II, but comes with its own set of exceptions, which will have to be

taken into consideration. These will be discussed in further detail in the software

implementation. Admittedly, Grade I is also not completely comfortable to read, but will

be used for this prototype due to the massive amount of software required for a Grade II

translation and small amount of available code memory.


11

• Ease of use

Finally, the machine should be as easy to use as possible. It should connect to a

PC and start up without need for a technical tutorial. Whenever possible, messages such

as “too fast”, “buffer full”, etc. will be conveyed by a sound. It should require as little

setup on the PC as possible. There should be one simple connection to the serial port of

the computer and when the power is turned on the braille display will await information

from the PC.


Chapter 2: Mechanical Hardware

The mechanical hardware was built from the pinboard outward so each part could

be built referencing the previous part, the most important reference being the fixed

location of the pins. When possible, lightweight materials such as aluminum and PVC

were used. This is especially important for the moving carriage assembly which should

be as lightweight as possible to reduce friction, and therefore minimize fatigue to the

reader.

2.1 Pinboard

Improving the stability of the pinboard was a major goal of this project. The

pinboard is the mechanism which holds the braille pins in place. Several non-magnetic

methods were attempted, but the final solution involved ceramic magnets. Holes of .0625

inch diameter were drilled through two thin plates of low carbon steel, chosen for its

ferromagnetic properties, and the pins were fitted through the two layers. The pins were

turned from steel welding wire, which also has optimal ferromagnetic properties.

Ceramic magnets were placed between the two layers, on either side of the pins. Since

the ceramic magnets have higher magnetic strength than the flexible magnetic material,

their close proximity to the pins is enough to pull the pins to the sides of their holes and

hold them in place. The magnets are kept from touching the pins by means of recessed

shoulders which were milled into the top steel layer (shown in Figure 2-1). Before the

final pinboard was assembled, the steel plates were treated chemically to prevent

potential rust damage. The final pinboard of 40 braille cells contains 240 pins and is

highly stable.

12
13

Figure 2-1: Pinboard Cross-section. The ceramic magnets (dark areas) are sandwiched
between the two layers of low-carbon steel, and the pins fit through the center.

2.2 Solenoids

Solenoids were chosen for the highest impulse and speed. It was calculated that a

maximum reading rate of 200 words per minute, which is in excess of the original goal,

would allow a maximum total stroke time of around 24 ms. The solenoids were therefore

tested using a 10 ms pulse, assuming that the downward stroke of the plunger would take

longer than the upward stroke. In addition, a translational mechanism would be needed

to raise the pins, which are separated by only 0.10 inch, while the centers of the

solenoids are 0.50 inch apart. The energy absorbed from the solenoid stroke by the

translational mechanism had to be taken into consideration when choosing the proper

solenoid.

The Guardian T-3.5X9 DC 24V solenoid was chosen for high speed, strength, and

small dimensions. Modifications were made to prevent the plunger from sticking to the

solenoid cavity at the top of its stroke and to keep it from dropping from the solenoid at

the bottom of its stroke. Small aluminum collars were machined and fitted to the bottoms

of the plungers to prevent the plunger cone from striking the interior of the solenoid. A

small plastic plate was used to position the bottom of the solenoid stroke (see Figure 2-4).
14

The strength of the solenoid depends partially on the distance of its stroke, so the plate

was positioned to maximize strength.

2.3 Solenoid Carriage

The solenoid carriage is responsible for holding the solenoids in place and

translating the centers of the solenoid strokes to the centers of the pins. The mechanical

drawings for the solenoid carriage parts are shown in the Appendix as Figures A-5 (page

46) and A-6 (page 47). The problem with translating this force is overcoming the lateral

torque that will be created about the centers of the solenoids. Merely bending a plunger

tip will not solve the problem because the plungers are free to rotate about their

longitudinal axis. Thus, hitting the pins would be very unlikely. Stabilizing the bent

plunger tip would create unwanted friction.

The translational mechanism is shown in Figure 2-2. It uses two paddles that are

free to rotate about an axis that is 1.5 inches from the centers of the plunger tips. The tips

of the outer solenoid plungers are hinged to the outer edges of the paddles with small

pins, so that the plunger and the paddle will function as a unit. A plunger pushes the

outer edge of a paddle and forces it to rotate upward until the inner edge of the paddle,

equipped with a small striking pin, contacts the cell pin. In this way the torque is

absorbed by the rigid aluminum paddle’s axis, and the energy of the stroke is minimally

affected. The horizontal component of the rotation of the paddle, which is a few

thousands of an inch, is negligible.


15

Figure 2-2: Conceptual Drawing of the Solenoid Carriage. The threaded bushings,
which hold the solenoids into the carriage base plate, are not shown. The solenoid
plunger tips are hinged at the outer edges of the paddles, while the middle plunger tip is
extended.

The middle plunger, being lined up with the center pin already, was merely

lengthened to reach the pin. All striking pins are chamfered to allow the striking pins to

be forced back down in the event of a collision with a cell pin. Without the chamfer, the

entire carriage would lock in position due to one collision.

The plungers are also fitted with small springs (see Figure 2-3) which apply a

constant downward pressure. These springs greatly increase the speed of the downward

stroke as well as reduce bouncing of the plungers off the plastic stop plate.

The solenoids are threaded into brass bushings that fit into 0.5 inch diameter holes

in the base plate of the solenoid carriage. The bushings are held in place with setscrews

so the solenoid position may be adjusted. The height of the pins is ultimately controlled

by vertically adjusting the solenoids.


16

Figure 2-3: Close-up of the Solenoid Carriage. The restraining springs lie just
below the paddles.

2.4 Solenoid Carriage Mounting

The solenoid carriage is fixed by means of an adjustable mounting to a plate

which slides on a pair of parallel rails as the user slides the shuttle. To allow for vertical

adjustment of the carriage, the mounting was made in two pieces that are dovetailed

together to minimize movement in other directions (shown in Figures A-7 and A-8). The

mounting is adjusted vertically by turning two screws whose ends rotate freely in the

bottom surface of the upper part of the mounting. The screws are threaded through the

mounting plate and are thus able to pull or push the upper portion of the mounting. When

the desired vertical position is achieved, a set screw, which is threaded through the back

of the lower piece, pushes the dovetailed pieces in opposite directions, thereby locking

them in place. These adjustment screws are shown in Figure 2-4.

The carriage mounting is also laterally adjustable. A key on the lower part of the

mounting fits into a slot in the mounting plate. The whole fixture may be moved in the

slot by means of another adjusting screw. Two screws fasten the mounting to the
17

mounting plate in the desired lateral position from underneath. The carriage adjustments

serve to more precisely place it in alignment with the pins.

Figure 2-4: View from Below the Mounting Plate. Shown above is the plastic
stop plate. In the middle are the adjusting screws for the adjustable mounting. To the
right is one of the Teflon sliders and at the left are the aluminum encoder strips and
optocoupler circuit.

2.5 Mounting Plate and Rails

The aluminum mounting plate supports the solenoid carriage rigidly in place with

respect to the rails. It is attached directly to Teflon sliders which move along the rails.

The plate was designed so the shuttle would push it approximately from the center of

mass of the solenoid carriage assembly, thereby reducing torque and friction on the

sliders.
18

Figure 2-5: Conceptual Drawing of the Solenoid Carriage, the Mounting Plate, and the
Teflon Sliders

2.6 Optocouplers and Encoder Strips

Optical sensors are used to locate the position of the shuttle. Two are used, one

for each of the two vertical columns of dots in a braille cell. The U-shaped optocouplers

straddle aluminum encoder strips which run the length of the encasing and have slits

corresponding to cell locations. This arrangement is shown in Figure 2-6.

Figure 2-6: Optocouplers and Encoder Strips. Seen above the mounting plate is the
horizontal adjustment screw for the adjustable mounting. At left are the wires that power
the shuttle switches.

The sensors are mounted to the underside of the mounting plate and the strips are

attached at the ends to the case, so the optocouplers move and the strips remain
19

stationary. The strips may be adjusted to align properly with the cell placement. The

offset distance between slits is also adjustable using screws that set the strips in place.

2.7 Shuttle

The shuttle consists of a shell made from Sculpey, a modeling material that sets

when baked, and an aluminum frame which is equipped with the two shuttle switches.

The shell was made by making a sculpture of the desired shuttle shape with modeling

clay that was 0.25 inch smaller on every surface than the predetermined shuttle

dimensions. Then a 0.25 inch sheet of Sculpey was laid over the clay model and worked

into shape. Next, the model was baked, hardening the outer layer so the clay could be

removed from the inside. Once fully hardened, the inside of the shell was reinforced with

epoxy.

The shell encloses a small aluminum frame which holds the switches and mounts

the shuttle to the shuttle plate. The switch buttons are elongated with aluminum

extension rods to reach the outer surface of the shuttle. On the inner surface of the shuttle

there is a plate to which the erasing mechanism is fastened. The entire shuttle assembly,

complete with erasing mechanism, is screwed through a spacer to the carriage mounting

plate below. The finished shuttle and eraser assembly is shown in Figure 2-7.
20

Figure 2-7: Shuttle and Eraser Mechanism

2.8 Eraser

The erasing mechanism must move the raised pins back to their recessed position.

There are two options to do this: push or pull. Pulling requires a strong electromagnet,

which requires an inefficient consumption of current and would create unwanted

electrical noise. To push the pins down, an arm which is fixed to a plate on the shuttle

reaches to the top of the pinboard and applies downward pressure. To reduce the bulk of

the materials required to achieve this operation, a two-inch-long cylindrical Alnico

magnet was chosen to provide the necessary downward force to erase the cells. The

magnet is held in place by a cradle made from PVC. This cradle is attached to the shuttle

and moves along with the reader’s hand.


Chapter 3: Electronic Hardware

The electronics include the single-board computer, output-control circuitry, and

the shuttle switches and optocouplers. An 8032 microcontoller controls the

entire machine. All electronics were made as compact and discrete as

possible with removable wiring connections for easy servicing. A modular

5V, 24V DC power supply supplies the voltage for both the electronic

circuits and the solenoids.

3.1 SBC-51

The URDA SBC-51 single-board computer was chosen for ease in development

of the system. The circuit diagram is shown in Figure A-1. It has a serial port, parallel

port, and 16KB of user external memory. It also has three jacks that allow access to the

8155 pins (parallel interface chip) and to the available 8032 port pins. The Timec

12MHz 8032 microcontroller was chosen because it has a third timer, which was used for

the polling interrupt.

21
Figure 3-1: System Electronics

22
23

3.2 Optocouplers

The position of a dot column in a cell is sensed by one of two optocoupler circuits

attached to the solenoid carriage. When an optocoupler passes over a slit in the encoder

strip, light can pass through the slit, thereby exciting a photo-detector which produces an

analog voltage proportional to the amount of light received.

The circuitry necessary to power the optocouplers was soldered to a circuit board

and attached to the carriage mounting plate. The LED emitter of the circuit, shown in

Figure A-2, uses a 470 Ω current-limiting resistor and the detector uses a 1.5 kΩ load

resistor. When no light is detected by the optocoupler, the detector voltage goes low.

This signal controls a one-shot (74LS123, 74LS122) which produces a 10 ms high pulse

on the 8032’s corresponding external interrupt line. The one-shot, or monostable

multivibrator, is a circuit which uses an RC circuit to produce an output pulse of a desired

duration. Here a 33 kΩ resistor and 1 µ F capacitor are used as shown in Figure A-3.

3.3 Solenoid Signals

When the optocoupler-initiated interrupt has been processed, the braille output for

that cell column is sent out to the 8155 parallel port. Each of these three lines is sent to a

one-shot which outputs a 10 ms pulse (if the input signal was high) to enable a 754410

driver chip, as shown in Figure A-3 (page 44). This chip is triggered by a 5V pulse and

outputs a 24V pulse directly to each solenoid. If two highs were sent in succession to this

circuit, there would only be one 10 ms output from the monostable multivibrator because

it must be first reset with a low. This problem is solved in software by pulsing each

output line low before data transfer, thereby resetting the one-shots.
24

3.4 Shuttle Switches

The shuttle switches require debouncing so they may be accurately monitored by the

microcontroller. The simple nand gate latch is shown in Figure A-4 (page 45). As with

the rest of the electronic hardware, the circuitry is localized, so the shuttle requires

power, ground, and signal wires.

3.5 Speaker

System sound is sent directly from port 1 on the 8032 through a 7404 inverter

gate (see Figure A-3) because the inverter has more drive-current capability than the

8032 port pin.

3.6 Handshaking

The SBC51 is equipped with a MAXIM232 converter chip to achieve proper

RS232 signal voltages. The system uses the chip for transmitting and receiving data, so

there are three lines for RS232 communication, which are transmit, receive, and ground.

However, since a handshaking signal is necessary to control the data flow from the

sending device, an extra line is needed. P1.0 on the 8032 controls the CTS line, which

was hard-wired through the MAXIM’s extra inverter and to pin 5 on jack 1 (RS232

interface).
Chapter 4: Software

4.1 Getting Started

The entire program for the display is written in 8051 assembly language. To

make the machine more independent and easy to use, all of the software, including the

translator, is executed solely by the 8032 microcontroller. The memory of the system has

four components: 1) internal 8032 user RAM (128 bytes), 2) external ROM (8K bytes),

which contains only I. Scott McKenzie’s MON51 monitor program, 3) external user

ROM (8K bytes), which contains the custom software for the machine, and 4) external

user RAM (8K bytes), which is used as the input text buffer.

4.2 Overall System Objective

The main objective of the controller software is to input a text file (composed of

ASCII characters), translate it into Grade I Braille, and send the braille output to the

electronic hardware. This is achieved by first storing the ASCII file in external RAM.

The program extracts these stored data one character at a time and translates each byte

into Grade I braille. After a byte is translated, it is stored as encoded braille in a buffer

inside the 8032’s on-board RAM. Finally, the program waits for signals from the cell

position sensors on the solenoid carriage and, when activated, transmits the braille

characters via the 8155 parallel port to the electronic hardware.

The program is mostly interrupt driven. When no interrupts are being executed,

the system waits for the reset switch to be pressed or empties the character output buffer,

which will be discussed in the section on the internal buffer. The reset switch is

responsible for initiating the program and subsequently for resetting the shuttle position

as a method of cell position correction. The switch, which is active low, is directly

25
26

connected to a port pin on the 8032 and is depressed when the shuttle is moved to the

extreme left, or the home position, where the cell count is -1.

4.3 External Buffer

There are two buffers designated to handle the information in the input file. The

largest buffer, the external buffer, stores raw data from a text file. Its task is to store as

much information as possible, because its size limits how far back the reader can scroll

when scanning backwards by line or by page. This buffer is isolated in an 8K byte

external RAM chip and is defined in code space.

The external buffer fill executes using the 8032’s serial port interrupt. In this way

a character is stored when it arrives but the system does not exclusively wait for it. This

prevents the system from hanging up when the external buffer is not completely full and

allows the braille display to operate while the external buffer is being filled.

If not hindered, the serial port interrupt subroutine will refill the external buffer,

writing over the stored data, as long as there are incoming data on the receive line. A

handshaking signal must be used to start and stop the data transmission. When the

external buffer is full, the clear-to-send line (CTS) is disabled, forcing the computer to

cease transmission. If an incoming word is incomplete at the end of the buffer, the buffer

will take in more characters until the word is finished or until the end of memory. This is

done to prevent word cutoff at the end of a line. If the file ends before the external buffer

is full, the CTS signal remains high and the system is capable of receiving more data.

4.4 Internal Buffer

The method of filling the internal buffer is shown in Figure 4-2. Characters are

extracted from the external buffer by the “fill” subroutine. Since there is only one
27

external data pointer in the 8032, and all variables are global in 8051 assembly language,

special care must be taken not to destroy the data pointer. For this reason, both the

external buffer and internal buffer store the current value of the 16-bit data pointer in

separate 8-bit memory locations.

The fill routine first points to the current external character to be read and sends it

to the ASCII to Grade I braille translator subroutine. This translator is mostly a

character-to-character translation. However, there are several exceptions, such as when

to add one or more number signs, letter signs, or capital signs. For example, if the

number 74LS123 is to be translated, the translation would be: number sign-G-D-cap

sign-cap sign-L-S-number sign-A-B-C. In this case two capital signs indicate that there

is more than one capital letter following, and the numbers are represented with the

number sign followed by corresponding letters. There are several characters which must

be spelled out in grade I such as plus, greater than, etc. In this case, the data pointer is

incremented to the next character as normal and the spelled out translation takes up more

characters in the internal buffer. In fact, one of the reasons two buffers are used in this

program is because Grade I braille takes up more characters than ASCII, and having a

small translated buffer saves more space for the text file in the external buffer.

There is a more concise computer braille code than Grade I or Grade II called the

Nemeth code. This code is often used by braille displays in text-editing modes, but is not

preferable for reading purposes. Most braille displays use Grade II braille, but since a

Grade II translator was not a practical task for this prototype, Grade I was chosen as a

middle ground to show that on-board translation is a viable option.


28

The translated character is stored in the internal buffer as an encoded byte where

the most significant hexadecimal digit represents the information for the left side of the

braille cell and the least significant digit represents information for the right side. For

example, the letter f, which is represented in braille by dots 1, 2, and 4, would be encoded

as 31h, or 00110001b. Each nibble has a maximum of binary 7, or 0111b, which would

correspond to all three solenoids being fired. This system of encoding leaves two bits

unused, which could be utilized for an eight-dot braille code. A half-cell is output by

stripping off one of the encoded nibbles and sending the remaining byte to port A on the

8155.

Figure 4-1: Braille Cell Encoding Byte Translation. A) The dot numbers in a
braille cell. B) The letter f represented by dots 1, 2, and 4. C) Left and right cell-halves
encode into binary 3 and binary 1 respectively.

The internal buffer holds 40 characters of data. However, at the end of a line the

fill routine checks to see if a word has been cut off. If so, it erases the incomplete word

and decrements the data pointer so the word will be printed in its entirety on the next line.

If in the middle of an internal fill, the end of the external buffer is encountered, the

remainder of the internal buffer is cleared and the CTS is enabled so the external buffer

may refill. This is done because the fill routine can take in characters much faster than

external fill routine can input characters (2400 baud). Word cutoff is eliminated in this
29

case by the external fill subroutine, because as mentioned before, the external buffer

always ends with a completed word.

Figure 4-2: Filling the Internal Buffer (current forty cells of braille).

4.5 External Interrupts

There are only two external interrupts on the 8032, denoted here as left and right.

In this program, they are used to tell the system when to output a character and to keep

track of the shuttle position. The left interrupt corresponds to the left column of three

dots (1,2,3) in a braille cell and the right interrupt corresponds to the right column (4,5,6).

As the shuttle moves, it causes two sets of optical sensors to pass between two sets of

slits that each correspond to a cell column. When a column’s slit is encountered as the

shuttle moves, its corresponding interrupt is generated.

Both interrupts are used for cell position sensing so the direction of shuttle

movement may be known. A boolean flag, f0 is designated for this purpose. Each

interrupt complements the value of the flag (1 or 0) and the left interrupt decides in which

direction the shuttle is moving. Let’s say the left interrupt is executed and the shuttle is

moving forward (to the right). First, the interrupt routine complements f0. If f0 = 0 after
30

complementing its value, the shuttle is perceived to be moving forward. Now if the same

interrupt is executed before the right interrupt has complemented f0 to 1, then the left

interrupt will complement f0 back to 1 and perceive this as a change in direction. This

process is illustrated in Figure 4-3. This only works if the shuttle starts from a known

position. So the shuttle must be moved to the home position to begin reading.

Figure 4-3: Cell Direction/Counting Method A) Left interrupt executes and the
display is moving forward. B) The right interrupt executes, neither count nor direction
changes. C) Left interrupt; count changes direction does not. D) The left interrupt
executes. Since no right interrupt was detected, direction must have changed.

When the shuttle is moving forward, the machine is outputting the information of

the current line of braille being read. When it is moving backward, there is no output,

because the information is still on the pinboard. A timing system ensures the shuttle does

not move too fast for the solenoid stroke while moving forward (the maximum reading

rate of the machine is dependent on the response time of the full solenoid stroke). If the

machine were to read faster than the maximum speed, hardware damage could occur.

When each external interrupt is executed, a timer loaded with a predetermined value is

set. The value is easily changed at the beginning of the program. If the next interrupt is
31

executed before the timer has finished counting, the interrupt has been requested too

early. Though cell count and direction will continue to be updated, there will be no

output to the solenoids.

The external interrupts are also responsible for keeping count of which cell is

being read. Each time a new cell is encountered the count is changed. When the reader

comes to the end of a line (cell 40), the last external interrupt refreshes the internal buffer

so the next line of text is ready. Then, as the shuttle is moved back toward the start

position, the cell count is decremented. If the shuttle were to move forward at a point in

the middle of the line, the middle of the newly refreshed line would be the output.

4.6 Polling Interrupt

The shuttle is equipped with two document navigation buttons, which may be

used to scroll through the document by line or by page. Since there are no remaining

external interrupts and high-speed response is not required, a polling timer interrupt is

used (Timer 2 on the 8032). This timer interrupts the program and checks the two

switches every 50 ms, so no delay can be detected by the user when a switch is pressed.

If a switch has been activated, the subroutine for that switch is called and executed.

Using one of the timers, the depression of the switch is timed. If the switch is depressed

and released quickly (within a half-second), the machine will scroll by line. If the switch

is held down for longer, the machine will scroll by page. Using a polling sequence also

leaves room for more user switches to be added in the future, such as right and left

mouse-click buttons on a PC mouse.


32

4.7 Sound

The program is equipped to make several differentiable sounds. Sound was

primarily used for testing the software (no debugging software was used), but some

sounds remain in the final product. All sounds were made using two timers, Timer 0 and

Timer 1. Since there are only three timers, Timer 0 had to be “borrowed” from the serial

port. Because there are never any sounds activated during an external fill, borrowing the

timer will never pose a problem. One timer determines frequency and the other

determines note length, and all tunes are composed in their playing order in a lookup

table. There are several important sounds to listen for. A click means that the shuttle has

returned to its home position. A short “wip!” means that the internal buffer has filled and

a long “bwwwiiiip!” means the external buffer has filled. When scrolling forward by

page, “Shave and a Haircut” tells you that the buffer limit has been exceeded.

4.8 Monitor Display

For testing purposes and demonstration to sighted people, the machine

simultaneously outputs braille to the display through the parallel port and text to a

monitor through the serial port. In fact, the braille output is translated back to text

directly using a separate lookup table. Examples of characters sent to the screen are

shown in Table 4-1. It must be translated from the braille output because the braille is

different from incoming text, and in this way each cell may be viewed in text form

(number sign, capital sign, etc.). Each time the internal buffer is filled, the data pointer

location is loaded into the character output buffer and each time there is a braille output

during an external interrupt, its translated ASCII character is loaded into the buffer.
33

When the interrupt has finished execution, the main program empties the character output

buffer.

Character Monitor Output


Capital Sign ^
Number Sign #
Lower Case Sign @
+ plus
- minus
>< greater/less than
= equals

Table 4-1: Some Characters As Viewed on the Monitor

Because the serial port interrupt is executed when either the transmit or receive

flag is set, the transmission of data to the monitor is not entirely straightforward. Another

boolean flag was created, called “key”, which is set when the transmit flag executes the

serial port interrupt. Using this flag in the character-send subroutine, the character may

be sent to the monitor.

Another problem encountered was that only one character was transmitted during

an interrupt, but more characters could be transmitted after the interrupt was finished

executing. Since all characters transmitted occur during the external interrupts, a method

to work around this problem was needed. The solution is to fill a small character output

buffer during the interrupt and empty the buffer to the monitor after every interrupt. If no

characters are sent to the buffer, then none will be sent to the monitor. This is achieved

by incrementing the pointer called “obuff” when a character is added to the buffer and

decrementing it when a character is emptied. This way, if the number is zero upon

emptying, no character will be sent.


34

4.9 Testing

During most of the software development, the braille display had not yet been

constructed. Since no debugging software was used, several methods of testing the

software were implemented. Sounds and transmission of data to the external monitor

were useful methods of debugging, but in order to study the interrupts and the outputs in

real-time use, a testing apparatus was needed. The apparatus consisted of two encoder

strips, two optocouplers, and the reset switch (see Figure 4-3). The encoder strips were

attached to the outside of three strips of plywood of the same width but different heights

in such a way that the middle strip of plywood would act as a runner and the plastic strips

were spaced apart from the middle piece of plywood enough to slide between the

optocouplers (Figure 4-3, right). Finally, a wooden base was fitted with two strips of

wood to create a slot for the runner and encoder strips to slide through. The reset switch

was attached to the wooden base. When in use, the encoder strips moved and the

optocouplers remained stationary. Three LEDs on the output control circuit board

allowed the braille output to be monitored, and thus the final machine could be simulated.

Figure 4-4: Apparatus for Testing Software


Chapter 5: Discussion

The refreshable braille display created for this thesis has successfully met the

requirements of the machine as specified in the introduction. It operates as a single unit

without cumbersome external hardware or fragile wiring. The machine has one simple

serial connection to the host computer and when it is powered, it awaits a text file. After

a text file has been sent, the user merely moves the shuttle to the home position and

begins reading the file.

Figure 5-1: The Finished Refreshable Braille Display

5.1 Review of Accomplishments

Standard cell size was achieved with the idea of a translational mechanism using

paddles that are free to rotate on a fixed axis to reduce torque and friction. The end effect

was that all of the striking pins are 0.10 inches apart. The cells on the pinboard are

spaced to meet standard cell size and spacing. This is the first machine at Appalachian

State University to truly achieve this goal.

35
36

The pinboard is a highly stable device and was relatively simple to machine. It

was also made from inexpensive materials. The solenoids chosen were the fastest

available and have no trouble moving the pins to the desired height of 0.02 inch. Once

the pins are up, they may be read many times without being pushed back down. The

Alnico magnet easily erases the cells with downward force provided by the magnetic

attraction to the steel pinboard.

Only three solenoids were used which further simplified the design and made the

solenoid carriage much less expensive to construct. Using three solenoids instead of six

should only slightly slow down the device because the critical governor of speed is the

time of the return stroke of the solenoids. At just over the maximum speed of the braille

display, the striking pins collide with the cell pins, thereby altering the performance of

the machine. This is prevented by software timing.

The solenoids perform very quickly, even equipped with springs and fastened to

the aluminum paddles. The reading speed of the machine was calculated using an

oscilloscope to measure the time between cells when the solenoids were being activated

at every opportunity and the shuttle was moving at a maximum speed. The desired speed

of the machine was at least 150 words per minute. Using an average word length of five

characters, it was calculated that the machine performed at rates up to 200 words per

minute. The speed governor in the software is set according to this maximum mechanical

speed to prevent hardware damage.

The shuttle is a very efficient way to reduce cost and to simplify the machine. It

prevents the need for a motor and drive system that would be associated with it, and it

makes navigation through the document convenient. At the time of this writing, a blind
37

user has not tested the machine. The two possible drawbacks are that the shuttle may

cause fatigue to the reader and it is not a simple way to read. The shuttle was designed to

be relatively ergonomic, but due to time constraints and distance, no visually impaired

people were consulted with an actual model of the system. If the system is deemed

difficult to use in its present state, then it may be redesigned for use with an idle hand or

it may be replaced with an automatic drive system.

The onboard translator stands as a very efficient way of dealing with the text. It

prevents the need for any external software which makes the machine easier to use and

faster to set up. Even though it is only a Grade I translation, the translation subroutine is

the largest section of the program. An ASCII to Grade II translator would be a large

program, but the only requirement to implement it would be more system memory.

Ease of use was a main concern for this project. Its simple connections and

portability will allow the machine to be demonstrated easily in the future.

5.2 Problems

The friction noticed as the shuttle moves back and forth is higher than was

expected. During the construction of the machine, special bearing

collars were considered for their very low friction. However, with

expense in mind, Teflon sliders were made instead. A less frictional

method would be preferred.

The optocoupler/encoder strip combination works fairly well, but because of the

resolutional limitations of the optocouplers, the cell direction often becomes confused,

causing the machine to write backwards. More precise optocouplers should solve the
38

problem. If not, it may be necessary to have a direction sensor that would constantly

send a direction signal to the microcontroller.

Finally, because the striking pins are positioned ahead of the reader’s hand, the

shuttle must move past the beginning of the braille line to align the solenoids with the

first cell and activate the reset switch. There is no solution to this but it remains to be

seen if it will pose a problem.

5.3 Possible Future Endeavors

The next step for this refreshable braille display would be to use it in a text-

editing situation. In this case, the shuttle would become a much more useful device,

because it could be used like a mouse to select the cursor position or other options. When

editing text, the braille output would change to the Nemeth Code. A Grade II translator

for reading mode would be essential for a more natural reading environment. The

ultimate goal would be to use Windows and the Internet.


39

References

1. Roblin, Jean, The Reading Fingers, Life of Louis Braille, 1809-1852, (New York:
American Foundation for the Blind, 1955). pp. 32-35.

2. Private communication, John A. Gardner, Department of Physics, Oregon State


University.

3. English Braille, American Ed., (Louisville, KY: American Printing House for the
Blind, 1994).

4. Enabling Technologies Company, “Tools for Braille Power 1996”, 3102 Jay Street,
Stuart, FL 34997.

5. Blazie, Dean, “Refreshable Braille Now and in the Years Ahead”, Braille Monitor,
43(1) (National Federation for the Blind, 2000) pp. 1-6.

6. Examples of current braille displays located at a private website.


www.deafblind.com/Newpba.jpg

7. The NIST Rotating-Wheel Based Refreshable Braille Display,


www.nist.gov/itl/div895/isis/projects/Braille pp. 1-6.

8. ALVA Satellite Series, http://www.humanware.com/E/E1/E1K.html, pp. 1-2.

9. Lu, Xiong, Development of a Computer-Aided Single Display-Cell Braille Reading


Device, (Appalachian State University, 1993) p. 60.

10. Stansell, Bruce, Design and Development of a Cost Efficient Braille Display,
(Appalachian State University, 1997) p. 69.

11. AFB National Technology Program, Braille Technology, (American Foundation for
the Blind, 2000) pp. 1-2.

12. White, Jerry, Building Braille Reading Speed: Some Helpful Suggestions,
http://nfbn.inetnebr.com/student/NABSinfo/Braille.htm.

13. Private communication, Elinor Pester, American Printing House for the Blind.

14. MacKenzie, I. Scott, The 8051 Microcontroller, (Prentice-Hall, 1999) pp. 210-212.
APPENDIX A

Mechanical and Electronic Schematics

40
41

Figure A-1: SBC-51 Circuit Diagram 14


42

Figure A-1 (continued): SBC-51 Circuit Diagram


43

Figure A-1 (continued): SBC-51 Circuit Diagram


44

Figure A-2: Circuit Diagram for the Optocouplers


45

Figure A-3: Output Control Circuitry


46

Figure A-4: Circuit/wiring Diagram for the Shuttle Switches


47

Figure A-5: Placement of Interior Components


48
49
50

Figure A-6: Specifications for the Solenoid Carriage Parts


51

Figure A-7: Specifications for the Adjustable Mounting


52

Figure A-8: Specifications for the Mounting Plate


APPENDIX B

System Software

53
54

;----------------------------------------------------------------------------
;Cmain.asm
;Chris Tullar
;July 5, 2001
;The following segments work:
; Xbuffer modified to do its job without hanging up by using the
; 8051’s evil serial port interrupt. Waits for character input and is
; open to take interrupts at any time. Characters may be sent to the screen
; for display purposes by using the obuffer during an interrupt. The outchr
; routine may only be accessed by the serial port interrupt. Essential to
; OUTCHR being used by OEMPTY is the 'key' bit. This is set by the SPISR
; upon a high TI flag.
; The internal buffer is used exclusively by the FILL routine. This
; routine translates information from the dptr into grade1 braille using the
; GRADE1 routine (ASCII to braille translator) and stores it in the internal
; cell buffer. Also included in the routine is the ability to wrap words to
; the next line (discarding words that will not fit on the current line).
; The external interrupts (EX0ISR and EX1ISR) have four functions. They
; determine the shuttle direction, output three bits of braille information
; per half-cell, keep count of which cell is being activated, and decide when
; to fill the internal buffer. These interrupts are activated when the begin
; switch is activated. This is initially for reference and subsequently for
; error checking and reinitializing.
; The TUNE routine controls the system sounds. It uses TR0 and TR1 for
; frequency and note length, respectively. The notes to be played are
; selected, as well as speed. Included in reportoire: Shave and a Haircut.
; REHASH is a simple routine to translate braille to ASCII. This is for
; monitor display purposes and allows to see just what is in the internal
; buffer without reading braille. Symbols have been designated for number
; sign, capital sign, etc.
; T2ISR is the polling interrupt initiated by timer2. Its tasks are to
; monitor the fast forward and rewind switches about every 20ms. FF and RW
; subtract or add 40 to the current dptr position. FFPAGE and RWPAGE add
; or subtract a page (about 25 lines of braille). NOTE!: the numbers viewed
; on the screen for the dptr will differ from expected values because the FILL
; routine ignores words it cannot complete, making each line fewer than 40
; characters total.
; Note: interrupts may be interfered with by electrical noise in the
; system. Easy on the software.
;----------------------------------------------------------------------------
$MOD52 ;file including 8032 commands
decdptr macro ;decdptr macro
dec dpl ;decrement low dptr byte
mov r7, dpl ;move to r7
cjne r7, #0ffh,$+4 ;if underflow to ff
dec dph ;dec high byte also
endm ;end of macro
showdptr macro
mov a, dhigh ;look at dph/dhigh
call show
mov a, dlow
call show
endm
showcell macro
mov a, @cell
call show
endm
pushdptr macro ;push dptr macro
push dPH
push dPL
endm
popdptr macro ;reverse order of push
pop DPL
55

pop dPH
endm
cts macro
clr p1.2 ;p1.2 activates the cts signal
endm ; it is connected to the MAXIM
ncts macro
setb p1.2 ;opposite of clear to send
endm
pushcell macro ;push the value of cell
mov a, cell
push acc
endm
popcell macro ;pop the value of cell
pop acc
mov cell, a
endm
return macro
mov a, #0dh
call ofill
mov a, #0ah
call ofill
endm
inchar macro
mov a, sbuf ;read character into a
mov c, p ;set p for odd parity in a
cpl c ;complementing indicates if error
clr acc.7 ;strip off parity
endm
;------------------------INTERNAL BUFFER-------------------------------------
dseg at 40h ;put in data segment (absolute, internal)
length equ 40
buffer: ds length ;40 bytes reserved
;------------------------EXTERNAL BUFFER-------------------------------------
xstart equ 9500h ;external buffer starting at 9000h
xlength equ 300h ;109h ; extending to the end of memory
xseg at xstart ;set up an external data segment
xbuffer: ds xlength ;'buffer' represents 9000h
;-------------------------OUTCHR BUFFER--------------------------------------
;this buffer is to eliminate the problem of not being able to output
;a character during an interrupt. This way the serial port interrupt may
;be used to output up to ten characters to the screen after an interrupt
dseg at 73h ;internal buffer starting at end of 'buffer'
olength equ 10 ; CANNOT start at 69!! messes with memory
obuffer: ds olength ;end is at 6Bh + 10d = 75h
;----------------------------------------------------------------------------
cseg at 8000h ;without this, code isn't recognized
ljmp main ; only after a data seg has been set
ljmp ex0isr ;jump over interrupt vectors
ljmp t0isr
ljmp ex1isr
ljmp t1isr
ljmp spisr
ljmp t2isr
org 8050h
;--------------------------DIRECTIVES----------------------------------------
;bank zero registers r0-r7
cell equ r0 ;braille cell pointer
obuff equ r1 ;obuffer pointer
; r3 ;obuffer place-keeper
bdata equ r4 ;data in external buffer
dlow equ r5 ;dpl gets saved in this
dhigh equ r6 ;dph gets saved in this
; r7 ;open for frequent destruction
56

fnote equ 30h ;final note for tune


note equ 31h ;initial note for tune
speed equ 32h ;note length for tune
speed2 equ 33h
endlow equ 34h ;registers to mark where xbuffer
endhigh equ 35h ; ceased filling
page equ 3e8h ;how many characters/page
ready equ 7EH
key equ 7Fh ;bit-addressable flag
begin equ p1.1 ;'hardware home' position switch
; p1.2 ;cts pin
ffpin equ p1.6 ;user switch for forward
rwpin equ p1.7 ;user switch for reverse
speedlim equ -18000 ;how much allowed time beteween sensors
count equ -2500 ;note time for tune
hold equ 6 ;button hold timer
poll equ -65500 ;for polling interrupt
;-----------------------SETUP OF 8155 COMMAND------------------------------
main: mov dptr, #0100h ;point to the 8155 command register
mov a, #00000001b ;set up A(8155)(1=output) as an output port
movx @dptr, a ;send it over
;Ports B and C are by default imput ports
;---------------------------INTERRUPT SETUP--------------------------------
setb it0 ;edge triggered for ex0
setb it1 ;edge triggered for ex1
setb es
setb et2 ;timer 2 interrupt
setb px0 ;high priority for the external interrupts
setb px1 ; because they must keep their count
;ex0, ex1 must be set later to avoid interrupting xfill and
; fill at the start. Nasty old things could happen.
;NOTE: it0, it1 must be set before enabling ex0 and ex1
;-------------------INITIALIZE SERIAL PORT AND TIMERS----------------------
mov scon, #52h ;serial port, mode 1, force TI int.
mov tmod, #21h ;timer 1, mode 2 (8bit auto), 16bit timer 0
mov th1, #-13 ;reload count for 2400 baud
setb tr1 ;start timer 1
mov t2con, #00h ;16-bit auto reload
mov rcap2h, #high poll ;loading the timer2 recapture registers
mov rcap2l, #low poll
;-----------------------CLEARING THE BUFFERS--------------------------------
mov cell, #buffer ;point at start of ibuffer
iclear: mov @cell, #00h ;clear location
inc cell ;next cell location
cjne cell, #(buffer + length + 20), iclear ;+20 for easy buffer
examination
mov dptr, #xbuffer ;clear external buffer
mov obuff, #obuffer ;output buffer must be cleared here because
oclear: mov @obuff, #00h ;it retains a character from xfill
inc obuff ;step through buffer
cjne obuff, #obuffer+olength, oclear ;end of oclear
xclear: clr a
movx @dptr, a
inc dptr
mov a, dpl ;compare dptr and acc.
cjne a, #00h, xclear ;#low(xbuffer + xlength), xclear
mov a, dph
cjne a, #0A0h, xclear ;#high(xbuffer + xlength), xclear
;****************************************************************************;
; MAIN PROGRAM BEGINS ;
;****************************************************************************;
clr ready
call charge ;a little theme to get you charged up
57

setb tr2 ;if started earlier, there are problems


clr key ;the magic little bean for character output
mov dptr, #xbuffer ;start xfill at the start of xbuffer
mov endlow, dpl ;dptr must always be saved in variables
mov endhigh, dph ;so xfill starts at the start of the buffer
cts ;so the PC can send characters
jnb ri, $ ;a character starts the program
setb ea ; and the interrupts are activated
;XTERNAL BUFFER FILLS
jb begin, $
mov dlow, #low(xbuffer) ;'fill' gets the dptr position from the two
mov dhigh, #high(xbuffer) ; variables dhigh, and dlow
call fill ;INTERNAL BUFFER FILLS
mov obuff, #obuffer ;initialize character-out buffer
mov r3, #0 ; with these two lines
mov dptr, #intro ; the intro message to be displayed
call strung ; display string

execute: jnb begin, lo ;THE ENTIRE PROGRAM WILL INTERRUPT THIS LOOP
call oempty ; waiting on begin switch(active low) and
sjmp execute ; and outputting characters with oempty
lo: clr f0 ;clear direction flag for braille cells
setb tf0 ;tells interrupt not too fast at first
mov cell, #(buffer-1) ;so the first interrupt increments to start
setb ex0 ;now we are ready for external interrupts
setb ex1 ; Play ball!
sjmp execute ;wait to be interrupted by exs, tr2, sp
;****************************************************************************
; SUBROUTINES AND INTERRUPT SERVICE ROUTINES ;
;****************************************************************************
;-------------------RECEIVE OR TRANSMIT A CHARACTER--------------------------
outchr: mov c, p ;put parity bit in c flag
cpl c ;change to odd parity
mov acc.7, c ;add character code
jnb key, $ ;key is set by the sp interrupt
clr key ; ti alone will NOT do the trick!
mov sbuf, a ;send character
clr acc.7 ;strip off parity bit
ret
ofill: mov @obuff, a ;send character to obuffer spot
inc obuff ;go to next spot
inc r3 ;r3 keeps track of where we are
ret ; and leaves it at that value
oempty: cjne r3, #0, oyes ;if r3 is zero then leave subroutine
ret
oyes: mov obuff, #obuffer ;start at beginning of obuffer
o2: mov a, @obuff ;move contents of obuff to a
call outchr ; and output to the screen
inc obuff ;go to next obuffer location
djnz r3, o2 ;decrement until start of buffer
mov obuff, #obuffer ;initialize character-out buffer
mov r3, #0 ; with these two lines
ret
;----------------------------DISPLAY BYTE------------------------------------
;displays a byte held in the accumulator in ASCII form
show: push acc ;save byte
swap a ;swap nibbles in the accumulator
anl a, #0fh ;erase upper nibble
orl a, #30h
cjne a, #':', $+3 ;see if number or letter
jc show1 ;if less than 10, use 3xh
add a, #7 ;make it a letter
show1: call ofill ;output high nibble
58

pop acc ;get low nibble of dlow


anl a, #0fh ;mask high nibble
orl a, #30h ;ASCII-correct
cjne a, #':', $+3
jc show2 ;if less than 10, use 3xh
add a, #7 ;make it a letter
show2: call ofill ;output low nibble
ret
;------------------------OUTCELL SUBROUTINES---------------------------------
; Outputs a three bits to the braille cell through the 8155's port A.
; The forty-cell buffer is ready for export by this point.
;----------------------------------------------------------------------------
Loutcell:
pushdptr ;don't get caught with proverbial pants down
mov a, @cell ;for screen representation
call rehash ;translate back to text
call ofill ;display contents of cell on monitor
mov dptr, #0101h ;point to 8155 output port
lout: mov a, #00h ;to make sure the one-shot is triggered
movx @dptr, a ; it must be initially cleared
call slight ;reset one-shots
mov a, @cell ;which letter we are on
swap a ;exchanges nibbles in a
anl a, #07h ;keep low 3 bits for left side
mov dptr, #0101h ;point to 8155 port a
movx @dptr, a ;export left side of cell
popdptr
ret
Routcell:
pushdptr
mov dptr, #0101h ;point to 8155 output port
rout: mov a, #00h ;to make sure the one-shot is triggered
movx @dptr, a ; it must be initially cleared
call slight ;reset one-shots
mov a, @cell ;opposite of ex0
anl a, #07h ;keep low 3 bits for right side
mov dptr, #0101h ;point to 8155 port A
movx @dptr, a ;schlep the byte out
popdptr
ret
;-----------------------------SLIGHT DELAY---------------------------------
slight: mov r7, #0ffh ;load multi-purpose, destroyable register
djnz r7, $ ;countdown
ret
;-----------------------OUTGOING STRING OF CHARACTERS----------------------
strung: clr a ;string procedure
movc a, @a+dptr ;get string
jz strout ;end of string
call outchr ;schlep character out
inc dptr ;for the string increment
sjmp strung ;do it until end of string
strout: ret
intro: db 'Your file is ready to read.', 0dh, 0ah
db 'Move the shuttle to the start position', 0dh, 0ah
db 'to begin plugging away.', 0dh, 0ah
db '-----------------------------------------',0dh,0ah,0dh,0ah, 00h
;------------------------FILL THE EXTERNAL BUFFER----------------------------
spisr: PUSHDPTR
jb ti, tiout ;spisr not for transmitting
xfill: clr ri ;must be cleared by software
mov dpl, endlow ;so interrupt knows where it left
mov dph, endhigh ; off in the xfill cycle
inchar ;get a character
59

movx @dptr, a ;move character out


mov a, dpl ;look at low nibble
cjne a, #low(xbuffer + xlength - 13), $+3
jc xout ;not at the end, still ready to fill
mov a, dph ;look at high nibble
cjne a, #high(xbuffer + xlength - 13), $+3
jc xout ;
movx a, @dptr ;continue to fill until the end
cjne a, #20h, xout ; of a word- important for communication
ncts ;buffer full, not clear to send
call full ;boooowip! sound
SJMP XOUT2 ;IF FULL DON'T SAVE INCREMENT
xout: inc dptr ;increment, is it at the top?
mov endhigh, dph ;save dptr for current end of
mov endlow, dpl ; xbuffer
XOUT2: popdptr ;BYPASSING KEY FOR RECEIVE INTERRUPT
reti
tiout: clr ti
setb key ;for sending out a character
popdptr
reti
;----------------------FILL THE FORTY-CELL BUFFER----------------------------
; Internal memory segment defined at the beginning of the program
fill: PUSHCELL
showdptr ;show dptr before buffer is filled
return ;these two things for display purposes
mov cell, #buffer ;point to the 1rst buffer location
next: mov dph, dhigh ;get value for xbuffer pointer
mov dpl, dlow ;16 bits
call grade1 ;translate @dptr and transport to @cell
inc cell ;next location in buffer
inc dptr ;next position in xbuffer
mov a, dpl ;look at low nibble
cjne a, #low(xbuffer + xlength-13), $+3
jc filla ;if not at xlength fill normally
mov a, dph ;look at high nibble
cjne a, #high(xbuffer + xlength-13), $+3 ;the -13 is a buffer to
prevent
jc filla ; words from being cut off in xbuffer
;-----------------------------------
movx a, @dptr ;look at contents of dptr position
cjne a, #20h, filla ;if not at a space, keep reading
FILLC: mov @cell, #0 ;whatever is left in the internal buffer, fill
it with
inc cell ; empty spaces. This is done to prevent
reading the
cjne cell, #buffer + length, $+3 ; xbuffer on the fly.
jc fillc ; continue erasing end of line
mov endlow, #low(xbuffer) ;move xfill to start of xbuffer
mov endhigh, #high(xbuffer) ; so it doesn't overfill here
mov dhigh, endhigh ;make sure dptr is not destroyed
mov dlow, endlow ; by an interrupt
popcell
cts
ret
;------------------------------------
filla: mov dhigh, dph ;make sure dptr is not destroyed
mov dlow, dpl ; by an interrupt
cjne cell, #(buffer+length), $+3 ;fill until end of buffer
jc next ;if less than full continue filling
bypass: call xfull ;wip!
wrap: decdptr ;This section wraps a word to the next
line
60

movx a, @dptr ;bring in char. at the end of the line


cjne a, #20h, wrap ;is it a space?
inc dptr ;yes, move to the next character
mov cell, #buffer + length ;Why? because we LIKE you.
backup: dec cell ;backup through the line and
mov a, @cell ; look for the last space
cjne a, #00h, backup ;When the last space written is found,
fillb: inc cell ; go through and erase the rest of the
mov @cell, #00h ; line with braille spaces.
cjne cell, #buffer + length, $+3
JC FILLB
mov dhigh, dph ;make sure dptr is not destroyed
mov dlow, dpl ; by an interrupt
popcell ;saving the previous cell position
ret
;-----------------------SHUTTLE SUBROUTINES----------------------------------
; Shuttle.asm October 21, 2000
; FF = dptr+40, until the xbuffer limit is exceeded, in which case
; it will be refilled and dptr will be at the start
; RW = dptr-40, until the the start of the xbuffer is reached.
; FFPAGE = dptr+page of characters (ex: 1 braille page = 1000char)
; RWPAGE = dptr-page of characters, until buffer limit exceeded
;-----------------------FAST FORWARD-----------------------------------------
ff: call fill ;refresh internal buffer
ret
;-----------------------------REWIND-----------------------------------
rw: pushcell ;store current cell status
mov dph, dhigh ;get value for buffer pointer
mov dpl, dlow ;
mov r7, #2
rwb: clr c ;not to mess up first subb command
mov a, dpl
subb a, #27h ;#4Fh ;subtract line from dptr (40d = 28h)
mov dpl, a ;
mov a, dph ; by using high and low separately
subb a, #00h ; and subtracting high byte with carry
mov dph, a ;replace original value
cjne a, #high(xbuffer), rwa ;compare dph and xbuffer base
mov a, dpl ;if equal, compare low bytes
cjne a, #low(xbuffer), rwa
jmp rwout ;if dpl =, exit subroutine
rwa: jc rwc ;out ;if dptr >, exit subroutine
DJNZ R7, RWB ;two steps back one step forward(fill)
sjmp rwout
rwc: call toofast ;error: that's too far 'blip blip'
mov dptr, #xbuffer ;set dptr at the start
rwout: mov dhigh, dph ;save the value in dptr
mov dlow, dpl
call fill ;refresh internal buffer
popcell
ret
;-------------------------FFPAGE--------------------------------------------
ffpage: pushcell
mov r7, #(page-1h-27h) ;how many lines to proceed
again: inc dptr
mov a, dpl ;compare to the top
cjne a, #endlow-length, $+3 ;so there will be room to fill once
jc ffa
mov a, dph ;if equal, compare low bytes
cjne a, #endhigh, $+3
jc ffa
call shave ;and a haircut, two bits
sjmp fpout ;don't increment any more, run out of space
61

ffa: djnz r7, again


fpout: mov dhigh, dph ;save the value in dptr
mov dlow, dpl
call doo
call fill ;refresh internal buffer
popcell
ret
;-----------------------------RWPAGE------------------------------------
;the page-1 command is due to the fact that subb subtracts one more
;than needed
rwpage: pushcell
mov dph, dhigh ;get value for buffer pointer
mov dpl, dlow
clr c
mov a, dpl ;look at low nibble of dptr
subb a, #low(page) ;subtract a page of lines
mov dpl, a ;restore dpl with new value
mov a, dph ;this is similar to the rw routine
subb a, #high(page)
mov dph, a ;replace original value
cjne a, #high(xbuffer), rpa ;compare dph and xbuffer
mov a, dpl ;if equal, compare low bytes
cjne a, #low(xbuffer), rpa
jmp rpout ;if dpl =, exit subroutine
rpa: jnc rpout ;if dptr >, exit subroutine
call toofast ;error: that's too far 'blip blip'
mov dptr, #xbuffer ;set dptr at the start
rpout: mov dhigh, dph ;save the value in dptr for 'fill'
mov dlow, dpl
call doo
call fill ;refresh internal buffer
mov dhigh, dph
mov dlow, dpl
popcell
ret
;-------------------------EXTERNAL INTERRUPTS------------------------------;
; One interrupt for each optocoupler. Each optocoupler waits for
; the other to pulse before the cell is incremented. If one pulses
; twice without the other pulsing in between, then shuttle direction
; has changed. Direction will be sensed by using the f0 flag.
; A timer is used to make sure the user doesn't exceed hardware speed
; * - - *
; * - and - *
; * - - *
;--------------------------------------------------------------------------;
ex0isr: ;for left 3 dots (1,2,3)
cpl f0 ;flag=1>forward ... flag=0>backward
jnb f0, back ;if backwards
up: inc cell ;if not back, forward
jb tf0, go ;if tf1 is 1 then we are ok
;call too ; otherwise we got here too quickly
jmp out ; and the solenoid won't be activated
go: call loutcell ;flag=1 dot
jmp out ;jump over decrement
back: dec cell ;then backup
cjne cell, #buffer, $+3 ;don't go too low
jnc out ; if >, then we're OK
call click ;a friendly reminder
out: clr tr0 ;stop timer
clr tf0 ;clear overflow flag
mov th0, #high speedlim ;enforce the speed limit
mov tl0, #low speedlim ; by using timer0
setb tr0 ;start timer0
62

reti
;f0=1>backwards for ex1, f0=0>forwards!
ex1isr: ;for right three dots (4,5,6)
cpl f0 ;toggle direction flag
jb f0, nok ;if going backwards no output
jb tf0, ok ;if the timer flag is not set
;call too ; then we got here too quickly
jmp nok ; and the solenoids will not fire
ok: call routcell ;send out character half
cjne cell, #(buffer+length-1), $+3 ;forward until 67h=the top
jc nok ;if <, then keep filling the
buffer
mov cell, #(buffer+length-1) ; if not, don't go off the map
call buzz
call fill ;refill the int buffer
nok: clr tr0 ;clear off the 'too fast' timer
clr tf0
mov th0, #high speedlim ; reload
mov tl0, #low speedlim
setb tr0 ; and restart
reti
;-------------------------TUNE.ASM-------------------------------------------
; September 29, 2000
;A subroutine which plays the tune you call (realtime) on port pin P1.0
;no interrupts used. More of a region than a subroutine I guess.
;----------------------------------------------------------------------------
toofast:
mov r7, #2
x2: mov speed, #4 ;how fast
mov note, #0 ;starting (or present) note
mov fnote, #7 ;ending note
call tune ;play those notes
djnz r7, x2
ret
shave: mov speed, #26 ;shave and a haircut
mov note, #32
mov fnote, #52 ;two bits
call tune
ret
charge: mov speed, #35 ;how fast
mov note, #0 ;starting (or present) note
mov fnote, #8 ;ending note
call tune ;play those notes
ret
click: mov r7, #2 ;a very quick digital phone bell
clicka: mov speed, #2
mov note, #15
mov fnote, #18
call tune
djnz r7, clicka
ret
buzz: mov r7, #2 ;sort of like a digital phone bell
buzza: mov speed, #8
mov note, #9
mov fnote, #12
call tune
djnz r7, buzza
ret
doo: mov speed,#60 ;need I say more?
mov note, #15
mov fnote,#16
call tune
ret
63

full: mov speed, #12 ;a quick wwip!


mov note, #9
mov fnote, #21
call tune
ret
xfull: mov speed, #4 ;a slow wwwwip!
mov note, #9
mov fnote, #21
call tune
ret
too: mov speed, #2 ;a very short click
mov note, #3
mov fnote, #4
call tune
ret
;-------------------------TUNE SUBROUTINE------------------------------------
; PLAYS A TUNE SPECIFIED BY ONE OF THE CALLS ABOVE
; tonex is what actually determines the freq. "Borrows" the serial port
; timer and changes its mode. Don't worry it puts it right back.
;----------------------------------------------------------------------------
tune: clr tr1 ;stop and
clr tf1 ; clear timer1
mov tmod, #11h ;make tr1 16 bit
mov TH1, #high count ;load the timer
mov TL1, #low count ; with a 16 bit number
setb tr1 ;start timer1
mov b, speed ;load multiplier
tonex: mov a, note ;look at current note
cjne a, fnote, tonexa ;if not past fnote, carry on
sjmp tonexb ;if so 'get out', as it were
tonexa: mov a, note
rl a ;x 2, all words (dw)
call song ;get the note count
mov th0, a ; loaded into timer 0
mov a, note
rl a
inc a
call song
mov tl0, a ;timer loaded here
jnz tonexc ;if tl0=0, check th0
mov a, th0 ;if count = 0
jz timer1 ;don't toggle pin
tonexc: setb tr0 ;start the timer
jnb tf0, $ ;wait for flag
cpl p1.0
clr tr0
clr tf0
TIMER1: jnb tf1, tonex ;beep until timer1 flag is set
clr tr1
clr tf1
mov th1, #high count
mov tl1, #low count
setb tr1
djnz speed, tonex ;don't interrupt tune until 0
mov speed, b ;reload multiplier
inc note ;go to next note
sjmp tonex ;start tone again
tonexb: clr tr1 ;stop timer1
clr tf1 ;clear timer1 flag
mov tmod, #21h ;restore timer mode
mov th1, #-13 ;restore timer1 value
setb tr1 ;restart timer1
ret ; it's ready again for the SP
64

;-----------------------SOUND LOOK UP TABLE-----------------------


song: inc a
movc a, @a+pc
ret
;subracting 24 from McKenzie's count numbers
; 1 2 3 4 5 6 7 8
dw -1112,-827,-652,-544,-000,-652,-544,-544
dw -1200,-1100,-1000,-900,-800,-750,-700,-650
dw -600,-550,-500,-450,-425,-652,-544,-544
dw -1112,-827,-652,-544,-000,-652,-544,-544
dw -652, -652,-652,-877,-902,-877,-838,-838 ;shave
dw -838, -877,-877,-000,-000,-000,-000,-677
dw -677, -000,-652,-652
;-----------------------ASCII TO BRAILLE TRANS.-------------------
;GRADE1: Translates an ASCII character
;into its corresponding braille character or characters.
;This should translate the data just before the data from the
;external buffer makes it to the forty cell buffer
; -the final storage is #XYh where X=left and Y=right
; -reads data from dptr, leaves xlation in 'cell'
; -restores dptr
; -'cell' is left at value at last character xlated
;-----------------------------------------------------------------
grade1:
pushdptr
mov dph, dhigh ;retrieve saved dptr value
mov dpl, dlow ;this is basically 'pop dptr'
movx a, @dptr ;mov @dptr to bdata
mov bdata, a ;bdata holds the character to xlate
;---------------------LOWER CASE LETTERS-----------------------
; if the last character was a number, show letter sign
cjne bdata, #'a', $+3 ;greater than 'a'?
jc notlow ;if not get out
cjne bdata, #'z'+1, $+3 ;less than z?
jnc notlow ;if not get out
decdptr ;look at previous character
movx a, @dptr
inc dptr ;restore data pointer
cjne a, #'0', $+3 ;was it a number
jc notlow ;c=1, was not a number
cjne a, #'9'+1, $+3
jnc notlow ;c=1, is a number
mov @cell, #06h ;the letter sign added
inc cell
jmp noxept ;where it will be xlated
;---------------------Capital letters------------------------
;one cap symbol for one capital letter.
;two symbols for multiple capitals
notlow: cjne bdata,#'A',$+3 ;check for capital
jc notcap ;c=1, not cap
cjne bdata,#'Z'+1,$+3
jnc notcap ;c=1, capital
decdptr ;look at previous location
movx a, @dptr
cjne a,#'A',$+3 ;check previous letter
jc cap ;c=1, it was not capped
cjne a,#'Z'+1,$+3
jc nosymb ;c=1, capital
cap: mov @cell, #04h ;cap sign
inc cell ;next cell
inc dptr ;look at next location
inc dptr ; to see if we will need
movx a, @dptr
65

cjne a,#'A',$+3 ; another capital sign


jc nosymb ;c=1, will not be capped
cjne a,#'Z'+1,$+3
jnc nosymb ;c=1, will be capital
mov @cell, #04h ;need one more cap sign
inc cell
nosymb: decdptr ;restore dptr
mov a, bdata
call trans
mov @cell, a
jmp aust
;--------------------------Numbers---------------------------
;number symbol needed if character before was not a number

notcap: cjne bdata, #'0', $+3 ;is it a number?


jc notnum ;c=1, it is not a number
cjne bdata, #'9'+1, $+3
jnc notnum ;c=1, bdata is a number
decdptr ;look at last character
movx a, @dptr
cjne a, #'0', $+3 ;was last char. a number?
jc sym ;c=1, was not a number
cjne a,#'9'+1,$+3
jc nosym ;c=1, was a number
sym: mov @cell, #47h ;number sign
inc cell ;next cell
nosym: inc dptr ;get original position back
mov a, bdata
call trans
mov @cell, a
jmp aust
;------------------Other Multicharacter Exceptions---------------
notnum: cjne bdata, #'"', xcept0 ;quotes (must open or close)
decdptr ;look at previous character
movx a, @dptr
cjne a, #20h, close ;if it was not a space, closing
inc dptr
mov @cell, #64h ;otherwise opening quotes
jmp aust ;exit
close: inc dptr
mov @cell, #46h ;closing quotes
jmp aust ;exit
xcept0: cjne bdata, #'%', xcept1 ; %
mov @cell, #01h
inc cell
mov @cell, #22h
inc cell
mov @cell, #71h
jmp aust
xcept1: cjne bdata, #'&', xcept2 ; &
mov @cell, #01h
inc cell
mov @cell, #75h
jmp aust
xcept2: cjne bdata, #27h, xcept3 ; ' single quotes
decdptr ;look at previous character
movx a, @dptr
cjne a, #20h, close2 ;if it was not a space, closing
inc dptr ;single quotes are treated
mov @cell, #04h ;like doubles except another
inc cell ;character is added
mov @cell, #64h ;otherwise opening quotes
jmp aust ;exit
66

close2: inc dptr


inc dptr ;look at next character
movx a, @dptr
decdptr ;restore dptr
cjne a, #20h, apost ;is it a space?
mov @cell, #46h ;if so it is most of the
inc cell ; time closing quotes
mov @cell, #40h ;closing quotes
jmp aust ;exit
apost: mov @cell, #40h ; '
jmp aust
xcept3: cjne bdata, #'*', xcept4 ; *
mov @cell, #42h
inc cell
mov @cell, #42h
jmp aust
xcept4: cjne bdata, #'+', xcept5
pushdptr
mov dptr, #plus
call string
popdptr
jmp aust
xcept5: cjne bdata, #'=', xcept6 ; =
pushdptr
mov dptr, #equals
call string
popdptr
jmp aust
xcept6: cjne bdata, #'@', xcept7 ; @
pushdptr
mov dptr, #atsymb
call string
popdptr
jmp aust
xcept7: cjne bdata, #'[', xcept8 ; [
mov @cell, #04h
inc cell
mov @cell, #66h
jmp aust
xcept8: cjne bdata, #']', xcept9 ; ]
mov @cell, #66h
inc cell
mov @cell, #40h
jmp aust
xcept9: cjne bdata, #'#', xceptA ; #
mov @cell, #01h
inc cell
mov @cell, #47h
jmp aust
xceptA: cjne bdata, #'<', xceptB ; <
pushdptr
mov dptr, #lthan
call string
popdptr
jmp aust
xceptB: cjne bdata, #'>', noxept ; >
pushdptr
mov dptr, #gthan
call string
popdptr
jmp aust
noxept: mov a, bdata ;if there were none of these
call trans ;exceptions, flat translation
67

mov @cell, a
aust: mov dhigh, dph ;save the value in dptr
mov dlow, dpl
popdptr
ret ;shew!
;---------------------------------------------------------------;
; trans: ASCII to Braille lookup table ;
;format: LRh where L is the left half-cell and R is the right ;
; xLLLxRRR in binary
;---------------------------------------------------------------;
trans: inc a
movc a, @a+pc
ret
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h ;0
db 00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h,00h ;1
db 00h,62h,00h,00h,26h,00h,00h,00h,66h,66h,00h,00h,20h,44h,26h,41h ;2
db 23h,10h,30h,11h,13h,12h,31h,33h,32h,21h,22h,60h,00h,00h,00h,64h ;3
db 00h,10h,30h,11h,13h,12h,31h,33h,32h,21h,23h,50h,70h,51h,53h,52h ;4
db 71h,73h,72h,61h,63h,54h,74h,27h,55h,57h,56h,00h,41h,00h,00h,77h ;5
db 00h,10h,30h,11h,13h,12h,31h,33h,32h,21h,23h,50h,70h,51h,53h,52h ;6
db 71h,73h,72h,61h,63h,54h,74h,27h,55h,57h,56h,66h,43h,66h,44h,00h ;7

string: clr a
movc a, @a+dptr ;get string
jz stout ;end of string
call trans ;loosely translate it into braille
mov @cell, a ;put letter in cell location
inc cell ;get next one ready
inc dptr ;for the string increment
sjmp string ;do it until end of string
stout: ret
plus: db 'plus', 00h
lthan: db 'less than', 00h
gthan: db 'greater than', 00h
equals: db 'equals', 00h
atsymb: db 01h, 'at', 00h
;--------------------------REHASH-------------------------------------;
;this look up table is used to translate the braille information
; inside the internal buffer to ASCII text which can be output
; to the computer monitor. For demonstration only.
rehash: inc a
movc a, @a+pc
ret
; 0 1 2 3 4 5 6 7 8 9 A B C D E F
db 20h,20h,20h,20h,5Eh,20h,40h,20h,00h,00h,00h,00h,00h,00h,00h,00h ;0
db 'a','c','e','d',20h,20h,20h,20h,00h,00h,00h,00h,00h,00h,00h,00h ;1
db 2Ch,'i',3Ah,'j',20h,20h,2Eh,'w',00h,00h,00h,00h,00h,00h,00h,00h ;2
db 'b','f','h','g',20h,20h,20h,20h,00h,00h,00h,00h,00h,00h,00h,00h ;3
db 27h,2Fh,2Ah,7Ch,2Dh,20h,22h,23h,00h,00h,00h,00h,00h,00h,00h,00h ;4
db 'k','m','o','n','u','x','z','y',00h,00h,00h,00h,00h,00h,00h,00h ;5
db ';','s','!','t',22h,20h,28h,20h,00h,00h,00h,00h,00h,00h,00h,00h ;6
db 'l','p','r','q','v',20h,20h,20h,00h,00h,00h,00h,00h,00h,00h,00h ;7
;-----------------------POLLING EXTERNAL SWITCHES----------------------
; October 23, 2000. Debugged December1, 2000
; Uses timer 2 to poll port pins on the 8032.
; A click less than 'hold' means 40 cells forward or backward
; A click longer than 'hold' yields a whole page forward or back
; This routine depends on ff, ffpage, rw, and rwpage
; which fill buffers as necessary. With no signal on polling pins
; only three lines are executed, minimizing time.
;----------------------------------------------------------------------
t2isr: clr tf2 ;clear timer2 flag REQUIRED
68

jnb ffpin, rpin ;ffpin low, check rwpin


mov r7, #hold ;multiplier for holding button down
setb tf0 ;so next inst. doesn't hang up
t2d: jnb tf0, $
clr tf0 ;clear timer 0
clr tr0
mov th0, #high -50000 ;wait for low for a set time
mov tl0, #low -50000 ; for ffpage
setb tr0 ;start timer
djnz r7, t2d ;for a longer delay
jb ffpin, $ ;wait for the return to low
jb tf0, t2a ;timer flag means time's up=ffpage
call ff ;go forward forty cells
sjmp t2out ;skip the remainder
t2a: call ffpage ;go forward a page
sjmp t2c
rpin: jnb rwpin, t2out ;if rpin is high,
mov r7, #hold
setb tf0 ;so next inst. doesn't hang up
t2e: jnb tf0, $ ;a nested loop with timer0
clr tf0 ; must be used for a long
clr tr0 ; enough hold
mov th0, #high -50000 ;wait for low for a set time
mov tl0, #low -50000 ; for ffpage
setb tr0 ;start timer
djnz r7, t2e ;count down
jb rwpin, $ ; wait for the return to low
jb tf0, t2b ;timer flag means time's up=rwpage
call rw ;go back forty cells
sjmp t2c ;skip the remainder
t2b: call rwpage ;go forward a page
t2c: clr tr0 ;stop timer 0
t2out: reti

t1isr: ;unused interrupts taken care of


t0isr: ; this is required

; THE
END
VITA

Chris Tullar was born in Greensboro, North Carolina in 1974, and lived there

until he went to Lenoir-Rhyne College in 1992. He started in a pre-engineering course of

study, but decided physics was too interesting to pass up, so he went on to receive a

Bachelor of Science degree in physics. He applied for graduate school at Appalachian

State University in 1996, but deferred his acceptance for three years. In 1997, he married

Raeleen Wilson who, shortly thereafter, went to graduate school at Wake Forest

University. During that time Chris worked as a faux painter/muralist and an instructor at

Sylvan Learning Center. In August 1999, he started the ASU program in Applied

Physics.

69

You might also like