Lathe Spindle Sensor

25

Click here to load reader

Transcript of Lathe Spindle Sensor

Page 1: Lathe Spindle Sensor
Page 2: Lathe Spindle Sensor

5

5

4

4

3

3

2

2

1

1

D D

C C

B B

A A

Pwr Supply

Modes:

(x) RPM: 00.00 to 1240(y) Turns: 00.00 to 9999(z) Degrees: 00.01 to 360.0All Mode LED's x,y,&z off when simple timer

H LED indicates forward rotationL LED indicates reverse rotation

Misc notes. The segment drivers a-g (port pins PB0..PB6) are driven either low or open-ckt in sync with the digit source drivers(PB7,PD2,PD3,PD6) to form numeric digits. The segment drivers can be driven high to light the misc leds (H,L,X,Y,Z,DP1,DP2). 5 timingstates are needed, one for each digit and one for the misc leds. If a switch is pressed, an idle source driver output (programmed highwith internal pullup resistor) will be seen low - segment drivers should be tri-stated to clear display until switch released.

PD0 Rx (or debug output)PD1 Misc LED's sinkPD2 Digit2 src, Mode Sw SrcPD3 Digit3 src, Zero Sw srcPD4 Encoder BPD5 Encoder APD6 Digit4 source

PB0 Seg A sink, Z srcPB1 Seg B sink, Y srcPB2 Seg C sink, X srcPB3 Seg D sink, L srcPB4 Seg E sink, H srcPB5 Seg F sink, DP2 srcPB6 Seg G sink, DP1 srcPB7 Digit1 src, Sw common

d:\work\avr\lathe\lathespeedsensor.dsn 1

Lathe Speed/Turns/DegofRotation Sensor-Display

A

1 1Friday, December 22, 2006

Title

Size Document Number Rev

Date: Sheet of

g

d

f

b

e

a

c

VCC

VCC

VCC

VCC

VCC

VCC

VCC

VCC

VCC

VCC

a

b

c

d

e

fgg

f

e

d

c

b

a

gf

e

d

c

b

aa

b

c

d

e

fg

1 2 3 4

X

Y

Z

DP2 DP1

DP3H

L

U?

LC204MB

1 3

242

23

114 5 618

717

816 13

109

1412

1522 21 20 19

Z+

1+

XY

Z-

Y+

X+

c-d- 2+ DP

2+D

P2-

DP

3+D

P3-

3+D

P1- L-

4+DP

1+

H+

L+

a-g- e- f- b-

C?10uF

C?.002uF

Q?

VP0104

Q?

VP0104

C?22pF

S?

MODE

S?

ZERO

Q?

VP0104

R? 150

R? 150

R? 150

R? 150

R? 150

R? 150

R? 150

J?

ISP

135

246

Q?

VP0104

J?

12345

J?

12345

U?

HEDS5600

123

54

Gndnc/indexA

BVcc

Y?

12MHz

C?22pF

D? 1N4001

R? 390

R? 390

J?

CON3

123

-+

D?Schottky, noise suppression

R?1500

U?90S231320

10

123

54

6789

191817161514131211

Vcc

Gnd

RESETPD0/RxDPD1/TxD

Xtal-InXtal-Out

PD2/Int0PD3/Int1PD4/T0PD5/T1

PB7/SCKPB6/MISOPB5/MOSI

PB4PB3/OC1

PB2PB1/AIN1PB0/AIN0PD6/ICP

R?10K

R?15K

D?

5.1V

Q?

VP0104

Page 3: Lathe Spindle Sensor

1 AVRASM ver. 2.1.9 D:\Work\AVR\Lathe\code\LatheSensor_ASM.asm Fri Dec 22 04:24:35 2006 D:\Work\AVR\Lathe\code\LatheSensor_ASM.asm(52): Including file 'C:\Program Files\Atmel\AVR Tool ; LatheSensor_ASM.asm ; Instrument uses an HP HEDS5600-A13 shaft encoder and a 4-digit ; 7-segment LED (with some misc led dots). CPU is an Atmel AVR,

10 ; 12 MHz 90S2313 (20 pin AVR microcontroller with 15 I/O pins). ; This project measures the rotation of a shaft (metal working machine), shows ; either RPM, #turns, or degrees of rotation, and utility timer modes. ; 500 PPS quadrature shaft encoder is decoded into 2000 states/revolution, ; or 0.18 degrees, tracks to 2480 rpm; encoder events: ~0..82666/sec, 12 uS ; Timer1 isr runs every 10 uS to keep up, takes 3-4 us to execute. ; Timer0 isr maintains display, runs every 100 uS (so display ok w/chgs every ; (note: tabs in this file expected every 4 spaces, to line up ok) ; ; Display layout ("digit 1" is leftmost):

20 ; _ _ _ _ ; x |_| |_| |_| |_| H ; y |_| |_|2|_|1|_| L ; z ; digits are driven from a common anode (+) pin per digit ; misc leds are driven from a common cathode (-) pin ; x,y,z are small LED dots used to show mode: RPM, Turns, Degrees, respectivel ; H,L are small LED dots used to show forward and reverse rotation, respective ; 1,2 are small LED dots used to show decimal points at those locations ;

30 ;I/O port pin usage, direction registers and output registers: ; DDRB PORTB DDRD PORTD ; 7654 3210 7654 3210 7654 3210 7654 3210 ;Digit1 1sss ssss 0000 0000 0000 000* 0111 111# ;Digit2 0sss ssss 1000 0000 0000 010* 0111 101# ;Digit3 0sss ssss 1000 0000 0000 100* 0111 011# ;Digit4 0sss ssss 1000 0000 0100 000* 0011 111# ;Misc 0sss ssss 1111 1111 0000 001* 0111 110# ; ;* Normally 0 (Rx is input), unless used for a debug output, then it's always

40 ;# Normally 1 (Rx input w/pullup resistor), unless used for a debug output ;s segment-selected; 1 when that segment needs to be lit, otherwise 0 ; ;I/O pins, physical usage: ;PB0 Seg A sink, Z src PD0 Misc LED's sink ;PB1 Seg B sink, Y src PD1 Tx (or debug output) ;PB2 Seg C sink, X src PD2 Digit2 src, Zero Sw sense ;PB3 Seg D sink, L src PD3 Digit3 src, Mode Sw sense ;PB4 Seg E sink, H src PD4 Encoder B ;PB5 Seg F sink, DP2 src PD5 Encoder A

50 ;PB6 Seg G sink, DP1 src PD6 Digit4 source ;PB7 Digit1 src, Sw common PD7 no such pin on 90S2313 ; ;(c)2006 Joe Crittendon. Hands off. ;-------------------------------------------------------------------- .DEVICE AT90S2313 .list ;-------------------------------------------------------------------- ; register allocations

60 ;-------------------------------------------------------------------- ;.def ??? = R0 ; only reg that can be loaded with byte from rom .def zero = R1 ; R1 set to 0, never changed, used as fast constant .def segval = R2 ; used by t0 isr but saved, ok for mainline to use .def portval= R3 ; used by t0 isr but saved, ok for mainline to use .def turnsl = R4 ; t1 isr, LSB of # complete turns of shaft .def turnsh = R5 ; t1 isr, MSB of # complete turns of shaft .def retval = r6 ; return value for functions that have one .def temp3 = r7 ; misc utility var for mainline .def m16u2 = r8 ;16x16 result byte 2 (bytes 0 & 1 in binaryin16)

70 .def m16u3 = r9 ;16x16 result byte 3 (MSB) .def txtemp = R10 ;belongs to tx isr ;.def ??? = R11 ; ;.def ??? = R12 ; .def isrevent= R13 ; event flag from timer 1 isr .def BinaryWk16_L = R14 ; working var for 16-bit utility functions .def BinaryWk16_H = R15 ; "

Page 4: Lathe Spindle Sensor

.def temp = R16 ; belongs only to mainline .def temp2 = R17 ; belongs only to mainline .def t0temp = R18 ; belongs only to timer0 isr

80 .def t1temp= R19 ; belongs only to timer 1 isr .def BinaryIn16_L= R20 ;input for 16-bit binary input to 16-bit utilities .def BinaryIn16_H= R21 ;" or to other funcs needing word input .def encode = R22 ; belongs to timer 1, encoder A&B inputs, bits 0&1, pre .def ticks = R23 ; belongs to timer 1, count of timer irqs since millisecond .def stepsl= R24 ; belongs only to timer 1 isr LSB of # encoder pulses this .def stepsh= R25 ; belongs only to timer 1 isr MSB of # encoder pulses this ;.def ??? = R26 ; X special pointer in this cpu ;.def ??? = R27 ; X special pointer in this cpu ;.def ??? = R28 ; Y special pointer in this cpu

90 ;.def ??? = R29 ; Y special pointer in this cpu ;.def ??? = R30 ; Z very special pointer in this cpu ;.def ??? = R31 ; Z very special pointer in this cpu (eg. reading rom) ; weird rules: ; Some instructions only work with registers R16..R31: ; LDI Rx, K ANDI Rx,K CBR Rx,M ; SBCI Rx,K SBR Rx,M SER Rx (same as LDI Rx,0xff) ; SUBI Rx,K ORI Rx,K ; Different addresses take different instructions ; I/O Registers addressable as data if0x20 added to address

100 ;Recommendation for the use of registers ;(per http://www.avr-asm-tutorial.net/avr_en/beginner/REGISTER.html ) ; 1. Define names for registers with the .DEF directive, never use rn name ; 2. If you need pointer access reserve R26 to R31 for that purpose. ; 3. 16-bit-counter are best located R25:R24. ; 4. If you read constants from program memory, use Z (R31:R30) and R0. ; 5. For access to single bits within certain registers , use R16 to R23. ;-------------------------------------------------------------------- ; mnemonic names for patterns & numbers used ;--------------------------------------------------------------------

110 .equ AbitIn = 5 ;bit position for encoder input A from physical input .equ BbitIn = 4 ;bit position for encoder input B from physical input .equ AbitOld = 3 ;bit position for encoder input A where stored as previous .equ BbitOld = 2 ;bit position for encoder input B where stored as previous .equ AbitNew = 1 ;bit position for encoder input A where stored as new .equ BbitNew = 0 ;bit position for encoder input B where stored as new .equ SWModebit = 3 ;bit position for mode switch sensing .equ SWZerobit = 2 ;bit position for zero switch sensing ; i/o register PortD masks for each digit position .equ PORTDMASK = 0x32 ;the 0 bits are loaded by isr

120 .equ DDRDMASK = 0x32 .equ PORTBMASK = 0x00 .equ DDRBMASK = 0x00 ;portd settings by digit position .equ DIG1PORTD = 0x7d .equ DIG2PORTD = 0x79 .equ DIG3PORTD = 0x75 .equ DIG4PORTD = 0x3d .equ DIG5PORTD = 0x7c ;ddrd settings by digit position

130 .equ DIG1DDRD = 0x00 .equ DIG2DDRD = 0x04 .equ DIG3DDRD = 0x08 .equ DIG4DDRD = 0x40 .equ DIG5DDRD = 0x01 ;portb settings by digit position .equ DIG1PORTB = 0x00 .equ DIG2PORTB = 0x80 .equ DIG3PORTB = 0x80 .equ DIG4PORTB = 0x80

140 .equ DIG5PORTB = 0xff ;ddrb settings by digit position .equ DIG1DDRB = 0x80 .equ DIG2DDRB = 0x00 .equ DIG3DDRB = 0x00 .equ DIG4DDRB = 0x00 .equ DIG5DDRB = 0x00 ;segment patterns for characters '0' through 'F', destined for DDRB. .equ DDRS_ZERO = 0x3f ;"0" bits .equ DDRS_ONE = 0x06 ;"1" bits

150 .equ DDRS_TWO = 0x5b ;"2" bits .equ DDRS_THREE = 0x4f ;"3" bits .equ DDRS_FOUR = 0x66 ;"4" bits

Page 5: Lathe Spindle Sensor

.equ DDRS_FIVE = 0x6d ;"5" bits .equ DDRS_SIX = 0x7d ;"6" bits .equ DDRS_SEVEN = 0x07 ;"7" bits .equ DDRS_EIGHT = 0x7f ;"8" bits .equ DDRS_NINE = 0x67 ;"9" bits .equ DDRS_A = 0x77 ;"A" bits (programmer always wants hex around) .equ DDRS_B = 0x7c ;"B" bits (hex is lower case where possible)

160 .equ DDRS_C = 0x58 ;"C" bits .equ DDRS_D = 0x5e ;"D" bits .equ DDRS_E = 0x79 ;"E" bits .equ DDRS_F = 0x71 ;"F" bits ;misc letters possible, *NOT* in continuous sequence from #'s above .equ DDRS_G = 0x3d ;"G" bits .equ DDRS_H = 0x76 ;"H" bits .equ DDRS_I = 0x30 ;"I" bits (like 1, but uses left side) .equ DDRS_J = 0x1e ;"J" bits .equ DDRS_K = 0x70 ;"K" bits (UGLY)

170 .equ DDRS_L = 0x38 ;"L" bits .equ DDRS_M = 0x37 ;"M" bits (bigger ugly) .equ DDRS_N = 0x54 ;"N" bits (bigger ugly) .equ DDRS_O = 0x63 ;"o" bits (like "0", but only bottom half) .equ DDRS_P = 0x73 ;"P" bits .equ DDRS_Q = 0x7b ;"Q" bits (ugly) .equ DDRS_R = 0x50 ;"R" bits .equ DDRS_S = 0x6d ;"S" bits .equ DDRS_T = 0x78 ;"T" bits .equ DDRS_U = 0x3e ;"U" bits (ugly, big bucket)

180 .equ DDRS_V = 0x5c ;"V" bits (ugly, little bucket) .equ DDRS_W = 0x41 ;"W" bits (bonzo ugly, looks like "=") .equ DDRS_X = 0x64 ;"X" bits (really, really ugly ) .equ DDRS_Y = 0x6e ;"Y" bits (really, really ugly ) .equ DDRS_Z = 0x52 ;"Z" bits (really, really ugly ) .equ DDRS_MINUS = 0x40 ;"-" bits minus sign ;segment patterns for misc leds .equ DDRS_FWD = 0x10 ;setup segment port ddr for mode led "H" bit .equ DDRS_REV = 0x08 ;setup segment port ddr for mode led "L" bit .equ DDRS_RPM = 0x04 ;setup segment port ddr for mode led "X" bit

190 .equ DDRS_TURNS = 0x02 ;setup segment port ddr for mode led "Y" bit .equ DDRS_DEGREES = 0x01 ;setup segment port ddr for mode led "Z" bit .equ DDRS_DP1 = 0x40 ;setup segment port ddr for mode led "DP1" bit .equ DDRS_DP2 = 0x20 ;setup segment port ddr for mode led "DP2" bit ;setup constants from timer isrs .equ TIMER0RELOAD = 256-19 ;reload value for timer0 irq every 19 incr's ( .equ TIMER1COMPARE= 15 ;reload value for timer1 irq every 15 incr's (10uS .equ TICKS_PER_MS = 100 ;100 (timer1) interrupts are exactly 1 millisecond .equ MODE_RPM = 0x00 ;mode is to show rpm .equ MODE_TURNS = 0x01 ;mode is to show #turns

200 .equ MODE_DEGREES = 0x02 ;mode is to show degrees .equ MODE_SECS = 0x03 ;debug mode is to show seconds .equ MODE_STEPS = 0x04 ;debug mode is to show raw encoder step count .equ MODE_CTDOWN = 0x05 ;count down .equ MODE_DEBUG = 0x06 ;debug mode is to show debug vars in hex .equ MODE_MAXMODE = 0x03 ;highest mode value reached by pressing the mode bu .equ ENCODERSTEPS = 2000 ;2000 steps per revolution .equ MILLISECRPM = 1000/(ENCODERSTEPS/60) ;# milliseconds where encoder steps .equ DEBUGPINBIT = 1 ;--------------------------------------------------------------------

210 ; macros ;-------------------------------------------------------------------- #define DEBUG 1 #undef DEBUG .macro DEBUGLO #ifdef DEBUG #endif .endmacro .macro DEBUGHI #ifdef DEBUG

220 #endif .endmacro .macro DEBUGTOGGLE #ifdef DEBUG #endif .endmacro ;-------------------------------------------------------------------- ; Global (bwaahahaha) Data ;--------------------------------------------------------------------

Page 6: Lathe Spindle Sensor

.dseg 230 DATASTART:

000060 milliseconds: .byte 2 ;16 bits - milliseconds (0..999) - 2nd byte is msb 000062 seconds: .byte 1 ;8 bits - seconds count (0..59) 000063 minutes: .byte 1 ;8 bits - minutes count (0..99) 000064 negseconds: .byte 5 ;8 bits - seconds count (59..0) 000069 negminutes: .byte 1 ;8 bits - minutes count (59..0) 00006a bcdresult: .byte 10 ;holds result of binary-bcd conversion 000074 displaybfr: .byte 6 ;holds segment patterns for digits 1..4, misc 00007a displayidx: .byte 1 ;holds display state (0..4); i.e. which digit to do 00007b displaydwell: .byte 1 ;used to keep extra time on misc leds(for brightnes

240 00007c rpmturnssnew: .byte 2 ;holds #turns at previous 30ms boundary 00007e rpmturnsprev: .byte 2 ;holds #turns at previous 30ms boundary 000080 rpmstepsnew: .byte 2 ;holds #steps at previous 30ms boundary 000082 rpmstepsprev: .byte 2 ;holds #steps at previous 30ms boundary 000084 rpmsamplecnt: .byte 1 ;holds running (0..30) counter to check rpm 000085 rpm: .byte 2 ;most recent captured rpm value 000087 displaymode: .byte 1 ;holds mode (MODE_RPM, etc) 000088 switchstate_mode:.byte 1 ;holds prev/new inputs from mode switch in bits 000089 switchstate_zero:.byte 1 ;holds prev/new inputs from zero switch in bits 00008a rotation: .byte 1 ;set to 1 for fwd, 0 for rev by t1 isr

250 00008b debugL: .byte 1 ;utility var to show on display 00008c debugH: .byte 1 ;" 00008d downcount: .byte 1 ;utility timing var decr by mainline every 10 ms 00008e downcountedge: .byte 1 ;cntr used to detect 10 ms events 00008f zeroturn: .byte 1 ;set if reversing into 1st negative turn 000090 txptr: .byte 1 ;pointer to char to transmit next 000091 txbfr: .byte 30;serial transmit buffer DATAEND: ;-------------------------------------------------------------------- ; Interrupt Vector Table

260 ;-------------------------------------------------------------------- .cseg .org 0 ; Reset 000000 c11e rjmp reset .org INT0addr ; External Interrupt Request 0 000001 9518 reti .org INT1addr ; External Interrupt Request 1 000002 9518 reti .org ICP1addr ; Timer/Counter1 Capture Event 000003 9518 reti

270 .org OC1addr ; Timer/Counter1 Compare Match 000004 c06f rjmp OC1_Interrupt .org OVF1addr ; Timer/Counter1 Overflow 000005 9518 reti .org OVF0addr ; Timer/Counter0 Overflow 000006 c0b1 rjmp OVF0_Interrupt .org URXCaddr ; UART, Rx Complete 000007 9518 reti .org UDREaddr ; UART Data Register Empty 000008 c055 rjmp TxISR

280 .org UTXCaddr ; UART, Tx Complete 000009 9518 reti .org ACIaddr ; Analog Comparator 00000a 9518 reti ;-------------------------------------------------------------------- ; constant (ROM) data table arrays ; note that byte-aligned data MUST be in pairs, or it gets "worded" ;-------------------------------------------------------------------- ; table of initial display chars for hello msg tablehello:

290 00000b 581e 00000c 7d3f .db DDRS_J, DDRS_C, DDRS_zero, DDRS_six Labelbuilddate: 00000d 0d0d 00000e 280a 00000f 2963 000010 3032 000011 3630 000012 6a20 000013 656f

300 000014 6320 000015 6972 000016 7474 000017 6e65 000018 6f64

Page 7: Lathe Spindle Sensor

000019 006e .db 0x0d,0x0d,0x0a,"(c)2006 joe crittendon",0 ; table of segment patterns for digits 0-9, a-f tabledigits: 00001a 063f .db DDRS_ZERO, DDRS_ONE 00001b 4f5b .db DDRS_TWO, DDRS_THREE

310 00001c 6d66 .db DDRS_FOUR, DDRS_FIVE 00001d 077d .db DDRS_SIX, DDRS_SEVEN 00001e 677f .db DDRS_EIGHT, DDRS_NINE 00001f 7c77 .db DDRS_A, DDRS_B 000020 5e58 .db DDRS_C, DDRS_D 000021 7179 .db DDRS_E, DDRS_F ; table of port pin values for each digit, indexed into by T0 isr tabledigitselects: 000022 007d 000023 8000 .db DIG1PORTD, DIG1DDRD, DIG1PORTB, DIG1DDRB ; digit 1 port settings

320 000024 0479 000025 0080 .db DIG2PORTD, DIG2DDRD, DIG2PORTB, DIG2DDRB ; digit 2 port settings 000026 0875 000027 0080 .db DIG3PORTD, DIG3DDRD, DIG3PORTB, DIG3DDRB ; digit 3 port settings 000028 403d 000029 0080 .db DIG4PORTD, DIG4DDRD, DIG4PORTB, DIG4DDRB ; digit 4 port settings 00002a 017c 00002b 00ff .db DIG5PORTD, DIG5DDRD, DIG5PORTB, DIG5DDRB ; digit 5 (misc ldes) port sett ; table of port init values tableportinit: ;0x20 added to allow addressing in data space

330 00002c 4f31 .db DDRD+0x20, 0x4f ; setup port d 00002d 4259 .db TIMSK+0x20, 0x42 ; timer 0 overflow & timer 1 compare irq's 00002e 0353 .db TCCR0+0x20, 0x03 ; timer 0 increments on crystal/64 00002f 004f .db TCCR1A+0x20,0x00 ; no pwm, no timer output to pin 000030 0a4e .db TCCR1B+0x20,0x0a ; timer 1 incr on crystal/8,clr on compare 000031 004b .db OCR1AH+0x20,high(TIMER1COMPARE) ; set compare limit 000032 0f4a .db OCR1AL+0x20,low(TIMER1COMPARE) 000033 002a .db UCR+0x20, 0 ;disable serial transmit, enable when needed 000034 4d29 .db UBRR+0x20, 0x4d ; ( (12Mhz/16) / baud ) - 1 000035 004d .db TCNT1H+0x20,0x00 ; start timer off at zero

340 000036 004c .db TCNT1L+0x20,0x00 000037 0000 .db 0x00,0x00 ;null terminates ; table of data init values tabledatainit: 000038 0f69 .db negminutes, 15 ;start countdown timer at 15 minutes 000039 3b64 .db negseconds, 59 ;..and 59 seconds 00003a 0087 .db displaymode, MODE_RPM ;set initial mode to RPM 00003b 0388 .db switchstate_mode, 3 ;set mode switch to idle 00003c 0389 .db switchstate_zero, 3 ;set zero switch to idle 00003d 0000 .db 0x00,0x00 ;null terminates table

350 ;jump table to handle encoder samples, per old state, new state: OldA OldB new tableencoderjump: 00003e c074 rjmp encodezero ;encode=0000 old AB was 00, new AB is 00, so no change 00003f c063 rjmp encodedecr ;encode=0001 old AB was 00, new AB is 01, so decrement 000040 c049 rjmp encodeincr ;encode=0010 old AB was 00, new AB is 10, so increment 000041 c05c rjmp encode_bad ;encode=0011 should never get from 00 to 11 in one step 000042 c047 rjmp encodeincr ;encode=0100 ...and so on. 000043 c06f rjmp encodezero ;encode=0101 000044 c059 rjmp encode_bad ;encode=0110 000045 c05d rjmp encodedecr ;encode=0111

360 000046 c05c rjmp encodedecr ;encode=1000 000047 c056 rjmp encode_bad ;encode=1001 000048 c06a rjmp encodezero ;encode=1010 000049 c040 rjmp encodeincr ;encode=1011 00004a c053 rjmp encode_bad ;encode=1100 00004b c03e rjmp encodeincr ;encode=1101 00004c c056 rjmp encodedecr ;encode=1110 00004d c065 rjmp encodezero ;encode=1111 ;jump table to handle update of display for current mode tablemodejump:

370 00004e c263 rjmp showrpm ;0 MODE_RPM 00004f c2a0 rjmp showfracturns ;1 MODE_TURNS 000050 c267 rjmp showdegrees ;2 MODE_DEGREES 000051 c2d9 rjmp showseconds ;3 MODE_SECS 000052 c2d3 rjmp showsteps ;4 MODE_STEPS 000053 c2f8 rjmp showctdown ;5 MODE_CTDOWN 000054 c2f8 rjmp showdebug ;6 MODE_DEBUG ; table of misc led settings for each mode(keep aligned with tablemodejump abo tablemodeleds: 000055 0204 .db DDRS_RPM, DDRS_TURNS

380 000056 2041 .db DDRS_DEGREES|DDRS_DP1, DDRS_DP2

Page 8: Lathe Spindle Sensor

000057 2003 .db DDRS_TURNS|DDRS_DEGREES, DDRS_DP2 000058 0000 .db 0, 0 000059 5220 00005a 4d50 00005b 003a LabelRPM: .db " RPM:", 0 00005c 5420 00005d 003a LabelTurns: .db " T:", 0 ;-------------------------------------------------------------------- ; TxISR - transmit data byte at (txptr). Kills Tx Intr when zero byte

390 ;-------------------------------------------------------------------- TxISR: 00005e b6af in txtemp, sreg ; save status register 00005f 92af push txtemp ; sei ;*** reenable interrupts to allow higher priority timer ;*** locks up cpu, why? (moot, ok to block for this amt of time) 000060 93af push xl 000061 93bf push xh 000062 91a0 0090 lds xl, txptr 000064 27bb clr xh

400 000065 90ad ld txtemp, x+ 000066 14a1 cp txtemp, zero 000067 f021 breq txisrcomplete 000068 b8ac out udr, txtemp 000069 93a0 0090 sts txptr, xl 00006b c003 rjmp txisrdone txisrcomplete: 00006c b1aa in xl, ucr 00006d 7daf andi xl, ~(1<<UDRIE) ;clear bit UDRIE in the UCR register to stop irqs 00006e b9aa out ucr, xl

410 txisrdone: 00006f 91bf pop xh 000070 91af pop xl 000071 90af pop txtemp 000072 beaf out sreg, txtemp 000073 9518 reti ;-------------------------------------------------------------------- ; Timer 1 Compare Match Interrupt Service Routine. Main timebase, sampler ; Samples encoder inputs, increment/decrement #steps, #turns ; 12 Mhz crystal, /8 prescale, reload for irq every 15 increments (256-15)

420 ; 12M/(8*30) = 100 KHz interrupt rate, i.e. every 10 uS ; takes 3.5-4 uS to execute ;-------------------------------------------------------------------- OC1_Interrupt: ; DEBUGLO 000074 b73f in t1temp, sreg ; save status register 000075 933f push t1temp 000076 93ff push ZH 000077 93ef push ZL 000078 9573 inc ticks ; bump fine grain irq count (ticks)

430 000079 3674 cpi ticks, TICKS_PER_MS ; compare to # of ticks in 1 mS 00007a f010 brlo OC1_ticksdone ; branch if still waiting 00007b 2777 clr ticks ; hit it, so re-zero counter and set flag 00007c 94d3 inc isrevent ; isr flag shows a new ms occurred. Mainline clears OC1_ticksdone: ;get encoder inputs, build jump index in proper bit positions 00007d b330 in t1temp, PIND ; use port input pins, not the logical port ! 00007e fb35 bst t1temp, AbitIn ; copy new A input bit into T flag 00007f f961 bld encode, AbitNew ; copy T flag into new A bit position in encode 000080 fb34 bst t1temp, BbitIn ; ditto for B input

440 000081 f960 bld encode, BbitNew ; encode now holds xxxx ABab (A is old a is new) ;build pointer to jump table 000082 e0f0 ldi ZH, high(tableencoderjump) ; point Z to jmp table (position 0) 000083 e3ee ldi ZL, low(tableencoderjump) ;" 000084 0fe6 add ZL, encode ;bump index to 0..15 per encoder prev/new state 000085 1df1 adc ZH, zero ;" ;now move the "new" encoder bits into the "previous" bit positions 000086 0f66 lsl encode 000087 0f66 lsl encode 000088 706f andi encode, 0x0f

450 ;jump to handler appropriate for current and previous encoder inputs 000089 9409 ijmp ;*** entry point for increment encoder steps encodeincr: 00008a 9583 inc stepsl 00008b 2388 tst stepsl 00008c f409 brne encodeincr1

Page 9: Lathe Spindle Sensor

00008d 9593 inc stepsh encodeincr1: ;now check if at ENCODERSTEPS, which is one full turn

460 00008e e037 ldi t1temp, high(ENCODERSTEPS) 00008f 1339 cpse t1temp, stepsh 000090 c009 rjmp encodeincr2 000091 ed30 ldi t1temp, low(ENCODERSTEPS) 000092 1338 cpse t1temp, stepsl 000093 c006 rjmp encodeincr2 ;new turn, zero steps, so increment # turns (16 bit) 000094 2788 clr stepsl 000095 2799 clr stepsh 000096 9443 inc turnsl

470 000097 2044 tst turnsl 000098 f409 brne encodeincr2 000099 9453 inc turnsh encodeincr2: ;one last thing..since incr, light the fwd led 00009a e031 ldi t1temp, 1 00009b 9330 008a sts rotation, t1temp 00009d c015 rjmp isroc1done ;*** entry point for bad encoder steps (if here, missed an encoder step(s)! encode_bad:

480 00009e 2766 clr encode ;no way to know right value, zap it 00009f e037 ldi t1temp, 7 ;light up xyz leds to show problem 0000a0 9330 0078 sts displaybfr+4,t1temp 0000a2 c010 rjmp isroc1done ;*** entry point for decrement encoder steps encodedecr: 0000a3 958a dec stepsl 0000a4 3f8f cpi stepsl, 0xff 0000a5 f409 brne encodedecr2 0000a6 959a dec stepsh

490 encodedecr2: ;now check if decremented from 0 to ffff; set to 1999 0000a7 3f9f cpi stepsh, 0xff 0000a8 f441 brne decrdone 0000a9 3f8f cpi stepsl, 0xff 0000aa f431 brne decrdone ; complete rotation, decr #turns 0000ab e097 ldi stepsh, high(ENCODERSTEPS-1) 0000ac ec8f ldi stepsl, low(ENCODERSTEPS-1) 0000ad 2044 tst turnsl ;is low byte of #turns is zero ?

500 0000ae f409 brne encodedecr3 0000af 945a dec turnsh ;turnsl is zero, will roll to ff, will need decr msb encodedecr3: 0000b0 944a dec turnsl ;if turns decr below 0000, it is - & displayed that way decrdone: ;one last thing..since decr, light the rev led 0000b1 9210 008a sts rotation, zero encodezero: ;nothing to do, fall out isroc1done:

510 0000b3 91ef pop ZL 0000b4 91ff pop ZH 0000b5 913f pop t1temp ;restore status register 0000b6 bf3f out sreg, t1temp ; " ; DEBUGHI 0000b7 9518 reti ;-------------------------------------------------------------------- ; Timer 0 Interrupt Service Routine (lower priority than timer1) ; updates led display, showing one digit per isr. Checks switch inputs. ; 12 Mhz crystal, /64 prescale, reload for irq every increments (w/256-19 )

520 ; 12M/(64*19) = 9868 KHz interrupt rate, i.e. every 101 microsecs ; (or whatever TIMER0RELOAD is set to, if not 19) ; Timer0 updates display, one digit position per interrupt ; typ. takes 10-11 uS to execute ;-------------------------------------------------------------------- OVF0_Interrupt: ; DEBUGLO 0000b8 b72f in t0temp, sreg ;save status register 0000b9 932f push t0temp 0000ba 9478 sei ;*** reenable interrupts to allow higher priority timer

530 0000bb ee2d ldi t0temp, TIMER0RELOAD ;reload counter (need to hurry) 0000bc bf22 out tcnt0, t0temp ; " 0000bd 93ff push ZH

Page 10: Lathe Spindle Sensor

0000be 93ef push ZL 0000bf 922f push segval 0000c0 923f push portval 0000c1 920f push r0 ; first turn off segment drivers to prevent ghosting 0000c2 ba17 out ddrb, zero ; get segments for current digit

540 0000c3 9120 007a lds t0temp, displayidx;get current digit to load 0000c5 e0f0 ldi ZH, high(displaybfr);point Z to display buffer 0000c6 e7e4 ldi ZL, low(displaybfr) ;" 0000c7 0fe2 add ZL, t0temp ;now move pointer to desired character (0..9) 0000c8 1df1 adc ZH, zero ;(in case carry from low byte needed) 0000c9 8020 ld segval, Z ;* segval now holds segment pattern ;get pointer to register masks 0000ca e0f0 ldi ZH, high(2*tabledigitselects);point Z to the port reg setup vals 0000cb e4e4 ldi ZL, low(2*tabledigitselects) ;" 0000cc 0f22 lsl t0temp ;bump digit index*4;set of reg masks has 4 values

550 0000cd 0f22 lsl t0temp ;" 0000ce 0fe2 add ZL, t0temp ;" 0000cf 1df1 adc ZH, zero ;* now Z points to port set values ;do portd 0000d0 b322 in t0temp, portd 0000d1 7322 andi t0temp, PORTDMASK ;whack the bits that belong to display maint. 0000d2 95c8 lpm ;get bits to set 0000d3 9631 adiw z,1 ;(too bad this old 2313 doesn't have auto-inc) 0000d4 2920 or t0temp, r0 ;set the bits that need it 0000d5 bb22 out portd, t0temp

560 ;do ddrd 0000d6 b321 in t0temp, ddrd 0000d7 7322 andi t0temp, DDRDMASK ;whack the bits that belong to display maint. 0000d8 95c8 lpm ;get bits to set 0000d9 9631 adiw z,1 ;(too bad this old 2313 doesn't have auto-inc) 0000da 2920 or t0temp, r0 ;set the bits that need it 0000db bb21 out ddrd, t0temp ;do portb 0000dc b328 in t0temp, portb 0000dd 7020 andi t0temp, PORTBMASK ;whack the bits that belong to display maint.

570 0000de 95c8 lpm ;get bits to set 0000df 9631 adiw z,1 ;(too bad this old 2313 doesn't have auto-inc) 0000e0 2920 or t0temp, r0 ;set the bits that need it 0000e1 bb28 out portb, t0temp ;do ddrb 0000e2 b327 in t0temp, ddrb 0000e3 7020 andi t0temp, DDRBMASK ;whack the bits that belong to display maint. 0000e4 95c8 lpm ;get bits to set 0000e5 9631 adiw z,1 ;(too bad this old 2313 doesn't have auto-inc) 0000e6 2920 or t0temp, r0 ;set the bits that need it

580 ;check if mode switch is being held down; leave segments off if so 0000e7 91e0 0088 lds zl, switchstate_mode 0000e9 ffe0 sbrs zl, 0 ;if mode sw is low, skip segment load 0000ea 2922 or t0temp, segval ;finally, hit the segment bits displayskipsegs: 0000eb bb27 out ddrb, t0temp displaydone: ;check input switches before bumping index 0000ec 9120 007a lds t0temp, displayidx 0000ee 3020 cpi t0temp, 0 ;on digit 1?

590 0000ef f4a1 brne display_adjidx dig1: ;now on digit 1, check if that low is shorted to digit 2(mode) or digit 3(z 0000f0 91e0 0088 lds zl, switchstate_mode 0000f2 30e1 cpi zl, 1 ;bit 0 is last sample, bit 1 the one before that 0000f3 f081 breq display_adjidx ;if "just released", leave alone for mainline 0000f4 0fee lsl zl ;else move old sample into bit position 1 0000f5 70e3 andi zl, 3 ;make sure code stays in valid range 0000f6 9b83 sbis pind, SWModebit ;skip next inst if mode sw high (not pressed) 0000f7 60e1 ori zl, 1 ;now bit 0 of zl holds current input from ping

600 ;if zl = xxxx xx01, the mode switch was just released 0000f8 93e0 0088 sts switchstate_mode, zl ;now check zero switch 0000fa 91e0 0089 lds zl, switchstate_zero 0000fc 30e1 cpi zl, 1 ;bit 0 is last sample, bit 1 the one before that 0000fd f031 breq display_adjidx ;if "just released", leave alone for mainline 0000fe 0fee lsl zl ;else move old sample into bit position 1 0000ff 70e3 andi zl, 3 ;make sure code stays in valid range 000100 9b82 sbis pind, SWZerobit ;skip next inst if zero sw high (not pressed)

Page 11: Lathe Spindle Sensor

000101 60e1 ori zl, 1 ;now bit 0 of zl holds current input from ping 610 ;if zl = xxxx xx01, the zero switch was just released

000102 93e0 0089 sts switchstate_zero, zl display_adjidx: 000104 9120 007a lds t0temp, displayidx 000106 9523 inc t0temp 000107 3025 cpi t0temp, 5 000108 f060 brlo isrdone ;on digit 5, stay there a couple of loops 000109 9120 007b lds t0temp, displaydwell ;stay on misc leds extra to bighten them 00010b 9523 inc t0temp

620 00010c 9320 007b sts displaydwell, t0temp 00010e 3022 cpi t0temp, 2 00010f f410 brsh displayidxrst 000110 e024 ldi t0temp, 4 000111 c003 rjmp isrdone displayidxrst: 000112 9210 007b sts displaydwell, zero 000114 2722 clr t0temp isrdone: 000115 9320 007a sts displayidx, t0temp

630 000117 900f pop r0 000118 903f pop portval 000119 902f pop segval 00011a 91ef pop ZL 00011b 91ff pop ZH 00011c 912f pop t0temp ;restore status register 00011d bf2f out sreg, t0temp ; " t0done: ; DEBUGHI 00011e 9518 reti

640 ;-------------------------------------------------------------------- ; ; Reset - main program entry ; ;-------------------------------------------------------------------- RESET: ; setup stack POINTER 00011f ed0f ldi temp,LOW(RAMEND) 000120 bf0d out SPL,temp 000121 2fe0 mov zl, temp

650 000122 27ff clr zh 000123 ea0a ldi temp, 0xaa markstack: ;fill stack with 0xaa (to test depth used) 000124 9302 st -z, temp 000125 3aef cpi zl, DATAEND 000126 f7e8 brsh markstack 000127 d174 rcall InitData ;data zapping in subroutine since used in UI ;set up ports 000128 e5e8 ldi ZL, low(2*tableportinit)

660 000129 e0f0 ldi ZH, high(2*tableportinit) 00012a 27bb clr XH 00012b d101 rcall RegisterInit 00012c 9478 sei ; enable interrupts ;show "hello" msg 00012d ec08 ldi temp, 200 ; set downcounter for 2 seconds (200 * 10 ms) 00012e 9300 008d sts downcount, temp 000130 e1e6 ldi zl, low(2*tablehello) ;load display from rom table 000131 e0f0 ldi zh, high(2*tablehello) 000132 d221 rcall Display4ROM

670 ;halt transmitter 000133 b81a out ucr, zero 000134 e1ea ldi zl, low(LabelBuildDate*2) 000135 e0f0 ldi zh, high(LabelBuildDate*2) 000136 e9a1 ldi xl, low(txbfr) 000137 93a0 0090 sts txptr, xl 000139 27bb clr xh 00013a d0fd rcall TxStr 00013b 921d st x+, zero

680 00013c e208 ldi temp, 0x28 00013d b90a out ucr, temp pwrupmsg: 00013e 10d1 cpse isrevent, zero ;check if interrupt hit millisecond boundary 00013f d02c rcall UpdateISRevent ;update accounting per new ms

Page 12: Lathe Spindle Sensor

000140 9100 008d lds temp, downcount 000142 3000 cpi temp, 0 ;check downcount 000143 f7d1 brne pwrupmsg ;enter mainloop mainloop:

690 ;check for work to do left by interrupt 000144 14d1 cp isrevent, zero 000145 f3f1 breq mainloop 000146 d025 rcall UpdateISRevent ;update whatever needs it on new millisecs ;check to see if mode switch was just released (increment mode if so) 000147 9100 0088 lds temp, switchstate_mode 000149 3001 cpi temp, 1 ;mode switch just released? 00014a f471 brne chkzerosw 00014b e003 ldi temp, 3 ;force prev/new states to high (unpressed) 00014c 9300 0088 sts switchstate_mode, temp

700 00014e 9100 0087 lds temp, displaymode 000150 9503 inc temp ;next display mode 000151 3004 cpi temp, MODE_MAXMODE+1 ;rollover at last one 000152 f008 brlo stsnewmode 000153 e000 ldi temp, 0 ;reset to first mode stsnewmode: 000154 9300 0087 sts displaymode, temp ;save new mode of operation (displaymode) 000156 d0c8 rcall ShowModeLEDs ;light the misc mode leds per (displaymode) 000157 e40d ldi temp, 'M' ;transmit recognition of the mode switch 000158 b90c out udr, temp

710 chkzerosw: ;check to see if mode switch was just released (increment mode if so) 000159 9100 0089 lds temp, switchstate_zero 00015b 3001 cpi temp, 1 ;zero switch just released? 00015c f469 brne jumptomode 00015d e003 ldi temp, 3 ;force prev/new states to high (unpressed) 00015e 9300 0089 sts switchstate_zero, temp ;zero data 000160 9100 0087 lds temp, displaymode 000162 930f push temp ;will init all data; save mode on stack

720 000163 94f8 cli ;disable interrupts while data zapped 000164 d137 rcall initdata 000165 910f pop temp 000166 9300 0087 sts displaymode, temp 000168 d0b6 rcall ShowModeLEDs ;light the misc mode leds per (displaymode) 000169 9478 sei ;reenable interrupts jumptomode: 00016a d0ad rcall showmode 00016b cfd8 rjmp mainloop ;--------------------------------------------------------------------

730 ; UpdateISRevent - update data;ISR said there's another millisecond ; this is the accounting department ;-------------------------------------------------------------------- UpdateISRevent: ; DEBUGLO 00016c 24dd clr isrevent ;decr event ctr from interrupt ;Update one-shot downcounter 00016d 9100 008e lds temp, downcountedge 00016f 9503 inc temp 000170 9300 008e sts downcountedge, temp

740 000172 300a cpi temp, 10 ;check if it's been 10 ms 000173 f048 brlo nextdown1 000174 9210 008e sts downcountedge, zero ;so reset the 10 ms counter & decr downcount 000176 9100 008d lds temp, downcount 000178 1501 cp temp, zero 000179 f019 breq nextdown1 00017a 950a dec temp ;decr in case it needs it, and set flags 00017b 9300 008d sts downcount, temp nextdown1: ;update milliseconds counter

750 00017d 9100 0060 lds temp, milliseconds 00017f 9503 inc temp 000180 9300 0060 sts milliseconds, temp 000182 2300 tst temp 000183 9110 0061 lds temp2, milliseconds+1 ;temp2 needs to be valid 000185 f419 brne chk1000 000186 9513 inc temp2 000187 9310 0061 sts milliseconds+1, temp2 ;check for hitting the 1000 ms boundary chk1000:

760 000189 3013 cpi temp2, high(1000)

Page 13: Lathe Spindle Sensor

00018a f551 brne nosecboundary;msdone 00018b 3e08 cpi temp, low(1000) 00018c f541 brne nosecboundary;msdone 00018d 9210 0060 sts milliseconds, zero 00018f 9210 0061 sts milliseconds+1, zero ;update seconds 000191 d0d5 rcall TxInitiate ;load serial buffer with data string 000192 9100 0062 lds temp, seconds 000194 9503 inc temp

770 000195 9300 0062 sts seconds, temp 000197 330c cpi temp,60 000198 f459 brne msdone 000199 2700 clr temp 00019a 9300 0062 sts seconds, temp ;update minutes 00019c 9100 0063 lds temp, minutes 00019e 9503 inc temp 00019f 3604 cpi temp,100 ;don't let minutes exceed two digits allocated 0001a0 f409 brne mok

780 0001a1 2700 clr temp mok: 0001a2 9300 0063 sts minutes, temp msdone: ;now do down count time 0001a4 9100 0064 lds temp, negseconds 0001a6 950a dec temp 0001a7 9300 0064 sts negseconds, temp 0001a9 3f0f cpi temp, 0xff 0001aa f451 brne nonegsecroll

790 0001ab 2700 clr temp 0001ac 9300 0064 sts negseconds, temp 0001ae 9100 0069 lds temp, negminutes 0001b0 950a dec temp 0001b1 3f0f cpi temp, 0xff 0001b2 f011 breq nonegsecroll 0001b3 9300 0069 sts negminutes, temp nonegsecroll: nosecboundary: ;now check for 30 ms boundary; encoder steps/30ms = rpm

800 0001b5 9100 0084 lds temp, rpmsamplecnt 0001b7 9503 inc temp 0001b8 310e cpi temp, MILLISECRPM ;30 milliseconds elapsed? 0001b9 f019 breq rpmread 0001ba 9300 0084 sts rpmsamplecnt, temp 0001bc c049 rjmp rpmdone rpmread: ;tricky bits: ; at top speed, there's 1.5 turns in this 30 ms sample window (i.e. 3000 ; rpm = newsteps - oldsteps + 2000(newturns-oldturns)

810 ; in reverse, the old count is bigger than the new one, unless the ; count passes 0, then the new count may be bigger or smaller ; in reverse, the old count is bigger than the new one, unless the ; count passes 2000, then the new count may be bigger or smaller. ; ;get stable copy of the volatile vars stepsl:h, turnsl:h #define newstepL binarywk16_L #define newstepH binarywk16_H #define newturnL binaryin16_L #define newturnH binaryin16_H

820 0001bd 2ee8 mov newstepL, stepsl ;get new step count, lsb 0001be 2ef9 mov newstepH, stepsh ;get new step count, msb 0001bf 2d44 mov newturnL, turnsl ;get new turns count, lsb 0001c0 2d55 mov newturnH, turnsh ;get new turns count, msb 0001c1 16e8 cp newstepL, stepsl ;movement while reading? 0001c2 f7d1 brne rpmread ;so read it again already 0001c3 9210 0084 sts rpmsamplecnt, zero ;save as the old step for next time 0001c5 9100 0082 lds temp, rpmstepsprev 0001c7 9110 0083 lds temp2, rpmstepsprev+1

830 0001c9 92e0 0082 sts rpmstepsprev, newstepL 0001cb 92f0 0083 sts rpmstepsprev+1, newstepH 0001cd 1ae0 sub newstepL, temp 0001ce 0af1 sbc newstepH, temp2 ;newstep now holds (newsteps-oldsteps). Might be negative. save on stack 0001cf 20ff tst newstepH 0001d0 f442 brpl stepsnotneg

Page 14: Lathe Spindle Sensor

;so negate it back to positive (but need to re-negate after multiplying) 0001d1 94e0 com newstepL 0001d2 94f0 com newstepH

840 0001d3 2d0e mov temp, newstepL 0001d4 5f0f subi temp,low(-1) ;Add 0x0001, low byte ;bits then adding 0001d5 2ee0 mov newstepL,temp 0001d6 2d0f mov temp, newstepH 0001d7 4f0f sbci temp,high(-1) ;Add high byte ;one (0x0001) 0001d8 2ef0 mov newstepH,temp stepsnotneg: 0001d9 92ef push newstepL 0001da 92ff push newstepH 0001db 9100 007e lds temp, rpmturnsprev

850 0001dd 9110 007f lds temp2, rpmturnsprev+1 0001df 9340 007e sts rpmturnsprev, newturnL ;save new turns as next time's prev turns 0001e1 9350 007f sts rpmturnsprev+1, newturnH 0001e3 1b40 sub newturnL, temp 0001e4 0b51 sbc newturnH, temp2 ;newturn now holds (new turns - old turns). Might be negative ;if it is negative, needs to be negated before multiplying 0001e5 2711 clr temp2 ;show difference is positive 0001e6 2355 tst newturnH 0001e7 f42a brpl turnsnotneg

860 ;so negate it back to positive (but need to re-negate after multiplying) 0001e8 9540 com newturnL 0001e9 9550 com newturnH 0001ea 5f4f subi newturnL,low(-1) ;Add 0x0001, low byte ;bits then adding 0001eb 4f5f sbci newturnH,high(-1) ;Add high byte ;one (0x0001) 0001ec e011 ldi temp2, 1 ;remember difference is negative turnsnotneg: 0001ed ed00 ldi temp, low(ENCODERSTEPS) 0001ee 2ee0 mov newstepL, temp 0001ef e007 ldi temp, high(ENCODERSTEPS)

870 0001f0 2ef0 mov newstepH, temp 0001f1 d1fc rcall mpy16u ;binaryin16 = 2000(newturns-oldturns) ;now newturn holds product 0001f2 3011 cpi temp2, 1 0001f3 f001 breq norenegate ;need to negate back norenegate: 0001f4 9540 com newturnL 0001f5 9550 com newturnH 0001f6 5f4f subi newturnL,low(-1) ;Add 0x0001, low byte ;bits then adding

880 0001f7 4f5f sbci newturnH,high(-1) ;Add high byte ;one (0x0001) ;now newturn holds 2000(newturns-oldturns), and could be negative ;add in the (possibly negative) step delta 0001f8 90ff pop newstepH 0001f9 90ef pop newstepL 0001fa 0d4e add newturnL, newstepL 0001fb 1d5f adc newturnH, newstepH ;newturn holds rpm. ok, now see if *that* rascal is negative 0001fc 2355 tst newturnH 0001fd f422 brpl rpmpositive

890 0001fe 9540 com newturnL 0001ff 9550 com newturnH 000200 5f4f subi newturnL,low(-1) ;Add 0x0001, low byte ;bits then adding 000201 4f5f sbci newturnH,high(-1) ;Add high byte ;one (0x0001) rpmpositive: 000202 9340 0085 sts rpm, newturnL 000204 9350 0086 sts rpm+1, newturnH rpmdone: ;update display per isr's note of fwd, rev ;rotation

900 ;one last thing..update fwd/rev led per (rotation) set by interrupt routine 000206 9100 008a lds temp, rotation 000208 1501 cp temp, zero 000209 f039 breq rpmfwd 00020a 9100 0078 lds temp, displaybfr+4 00020c 7e07 andi temp, ~(DDRS_FWD | DDRS_REV) 00020d 6008 ori temp, DDRS_REV 00020e 9300 0078 sts displaybfr+4,temp 000210 c006 rjmp rpmexit rpmfwd:

910 000211 9100 0078 lds temp, displaybfr+4 000213 7e07 andi temp, ~(DDRS_FWD | DDRS_REV) 000214 6100 ori temp, DDRS_FWD

Page 15: Lathe Spindle Sensor

000215 9300 0078 sts displaybfr+4,temp rpmexit: ; DEBUGHI 000217 9508 ret ;-------------------------------------------------------------------- ; Showmode - run selected display mode subroutine ; jumps to routine, returns from there

920 ;-------------------------------------------------------------------- showmode: ;build pointer to jump table 000218 e4ee ldi ZL, low(tablemodejump) ; point Z to jmp table (position 0) 000219 e0f0 ldi ZH, high(tablemodejump) ;" 00021a 9100 0087 lds temp, displaymode 00021c 0fe0 add ZL, temp 00021d 1de1 adc ZL, zero 00021e 9409 ijmp ;jump to (displaymode)'s subroutine entry ;--------------------------------------------------------------------

930 ; ShowModeLEDs - load misc LED's per (displaymode) ;-------------------------------------------------------------------- ShowModeLEDs: ;set up misc leds per the displaymode 00021f 9100 0087 lds temp, displaymode 000221 e0f0 ldi ZH, high(2*tablemodeleds);point Z to the segment pattern table in r 000222 eaea ldi ZL, low(2*tablemodeleds);" 000223 0fe0 add ZL, temp ;now move pointer to desired character (0..9) 000224 1df1 adc ZH, zero ;(in case carry from low byte needed) 000225 95c8 lpm ;r0 holds segments to light for (displaymode)

940 000226 9100 0078 lds temp, displaybfr+4 000228 7908 andi temp, ~(DDRS_DEGREES | DDRS_TURNS | DDRS_RPM | DDRS_DP1 | DDRS_DP2) 000229 2900 or temp, r0 00022a 9300 0078 sts displaybfr+4, temp 00022c 9508 ret ;-------------------------------------------------------------------- ; RegisterInit - loads port registers from rom table at ZL:ZH ;-------------------------------------------------------------------- RegisterInit: 00022d 27bb clr xh ;*ASSUME* i/o address high byte always zero

950 reginitloop: 00022e 95c8 lpm ;read port address from rom 00022f 2da0 mov xl, r0 ;save port address in XL 000230 9631 adiw Z, 1 ;bump ptr to port value 000231 95c8 lpm ;read port data from rom 000232 9631 adiw Z, 1 ;bump ptr to next port address 000233 30a0 cpi xl, 0 ;if port address is 0x00, we're done 000234 f011 breq reginitdone 000235 920d st X+, r0 000236 cff7 rjmp reginitloop

960 reginitdone: 000237 9508 ret ;-------------------------------------------------------------------- ;Transmit utilities - all assume XL:H points to next spot in tx bfr ; input is in BinaryIn16_L:H ;-------------------------------------------------------------------- TxStr: ;transmit null-terminated ASCII string stored in rom at ZL:H 000238 95c8 lpm 000239 9631 adiw z, 1 00023a 1401 cp r0, zero

970 00023b f011 breq Txstrexit 00023c 920d st x+, r0 00023d cffa rjmp TxStr Txstrexit: 00023e 9508 ret Tx2Hex: ;transmit BinaryIn16_L as two ascii hex digits 00023f 2f04 mov temp, BinaryIn16_L 000240 9502 swap temp 000241 700f andi temp, 0x0f 000242 e310 ldi temp2, 0x30

980 000243 300a cpi temp, 10 000244 f008 brlo tx2hexaddhex 000245 e317 ldi temp2, 0x37 tx2hexaddhex: 000246 0f01 add temp, temp2 000247 930d st x+, temp 000248 2f04 mov temp, BinaryIn16_L 000249 700f andi temp, 0x0f

Page 16: Lathe Spindle Sensor

00024a e310 ldi temp2, 0x30 990 00024b 300a cpi temp, 10

00024c f008 brlo tx2hexaddhex2 00024d e317 ldi temp2, 0x37 tx2hexaddhex2: 00024e 0f01 add temp, temp2 00024f 930d st x+, temp 000250 9508 ret Tx5bcd: ;transmit 5 decimal digits from BinaryIn16_L:H 000251 e005 ldi temp, 5 ;# digits

1000 000252 c006 rjmp Txndigits Tx4bcd: ;transmit 4 decimal digits from BinaryIn16_L:H 000253 e004 ldi temp, 4 ;# digits 000254 c004 rjmp Txndigits Tx3bcd: ;transmit 3 decimal digits from BinaryIn16_L:H 000255 e003 ldi temp, 3 ;# digits 000256 c002 rjmp Txndigits Tx2bcd: ;transmit 2 decimal digits from BinaryIn16_L 000257 2755 clr BinaryIn16_H 000258 e002 ldi temp, 2 ;# digits

1010 TxnDigits: 000259 e6ea ldi zl, low(bcdresult) 00025a 27ff clr zh 00025b d169 rcall bin2tobcd5 00025c e6ef ldi zl, low(bcdresult+5) 00025d 1be0 sub zl, temp 00025e 27ff clr zh 00025f e310 ldi temp2, 0x30 tx5bcd_xmitloop:;load xmit buffer at (x) with (temp) chars retrieved from (z) 000260 9001 ld r0, z+

1020 000261 0e01 add r0, temp2 000262 920d st x+, r0 000263 950a dec temp 000264 1101 cpse temp, zero 000265 cffa rjmp tx5bcd_xmitloop tx5bcd_exit: 000266 9508 ret ;-------------------------------------------------------------------- ; TxInitiate - initiates transmission of data string

1030 ; "mm:ss rpm:nnnn turns:nnnnn steps:nnnn " ;-------------------------------------------------------------------- TxInitiate: ;halt transmitter 000267 e000 ldi temp, 0 000268 b90a out ucr, temp ;init data ptrs 000269 e9a1 ldi xl, low(Txbfr) ;XL:H is output pointer into transmit buffer 00026a 93a0 0090 sts txptr, xl ;txptr used by txisr to pull bytes from buffer

1040 00026c 27bb clr xh ;start with cr/lf 00026d e00d ldi temp, 0x0d ;carriage return 00026e 930d st x+, temp 00026f 930d st x+, temp 000270 e00a ldi temp, 0x0a ;linefeed 000271 930d st x+, temp ;lds BinaryIn16_L, DATAEND+1 ;show if stack or tx bfr overrun ;rcall tx2hex

1050 ;minutes ;not room for time ; lds BinaryIn16_L, minutes ; rcall Tx2BCD ;colon ; ldi temp, ':' ; st x+, temp ;seconds ; lds BinaryIn16_L, seconds ; rcall Tx2BCD

1060 ;" RPM: " 000272 ebe2 ldi zl, low(LabelRPM*2) 000273 e0f0 ldi zh, high(LabelRPM*2) 000274 dfc3 rcall TxStr ;rpm value

Page 17: Lathe Spindle Sensor

000275 9140 0085 lds BinaryIn16_L, rpm+0 000277 9150 0086 lds BinaryIn16_H, rpm+1 000279 dfd9 rcall tx4bcd ;" Turns: " 00027a ebe8 ldi zl, low(LabelTurns*2)

1070 00027b e0f0 ldi zh, high(LabelTurns*2) 00027c dfbb rcall TxStr ;turns readturns: 00027d 2fc8 mov YL, stepsl 00027e 2fd9 mov YH, stepsh 00027f 2d44 mov BinaryIn16_L, turnsl 000280 2d55 mov BinaryIn16_H, turnsh 000281 2f08 mov temp, stepsl 000282 130c cpse temp, YL

1080 000283 cff9 rjmp readturns 000284 2355 tst BinaryIn16_H 000285 f452 brpl turnspos ;negate #turns, fractional turn should be considered negative; 2000-stepsl: 000286 9550 com BinaryIn16_H ;negate turns into a a normal looking # 000287 9540 com BinaryIn16_L ; subi XL,low(-1) ;need to sub 1 anyway, so don't add usual 1 ; sbci XH,high(-1) ;"negate" # steps, subtracting from 2000

1090 000288 ed00 ldi temp, low(ENCODERSTEPS) 000289 1b0c sub temp, YL 00028a 2fc0 mov YL, temp 00028b e007 ldi temp, high(ENCODERSTEPS) 00028c 0b0d sbc temp, YH 00028d 2fd0 mov YH, temp 00028e e20d ldi temp, '-' 00028f 930d st x+, temp turnspos: 000290 95d6 lsr yh ;divide #steps by 2 to convert to decimal fraction

1100 000291 95c7 ror yl 000292 dfc0 rcall tx4bcd 000293 e20e ldi temp, '.' 000294 930d st x+, temp ;steps 000295 2f4c mov BinaryIn16_L, YL 000296 2f5d mov BinaryIn16_H, YH 000297 dfbd rcall tx3bcd InitTxdone: 000298 921d st x+, zero ;null-terminate to end transmission

1110 000299 e208 ldi temp, 0x28 00029a b90a out ucr, temp 00029b 9508 ret ;-------------------------------------------------------------------- ; InitData - initialize data and registers ;-------------------------------------------------------------------- InitData: ;zero all the registers from r1 to r29 (r30:r31 aka ZL:ZH are used for this 00029c 2411 clr r1 ;R1 ("zero") shalt be zero from here on foever 00029d 27ff clr zh

1120 00029e e1ee ldi zl, 30 initdataregloop: 00029f 9212 st -z, zero 0002a0 11e1 cpse zl, zero 0002a1 cffd rjmp initdataregloop ;clear data memory from DATASTART to DATAEND 0002a2 e6e0 ldi zl, low(DATASTART) initdataloop: 0002a3 9211 st z+, zero 0002a4 3be0 cpi zl, low(DATAEND+1)

1130 0002a5 f7e9 brne initdataloop ;load the data that should not be zero 0002a6 e7e0 ldi ZL, low(2*tabledatainit) 0002a7 e0f0 ldi ZH, high(2*tabledatainit) 0002a8 df84 rcall RegisterInit ;load the mode leds 0002a9 df75 rcall ShowModeLEDs ;testcase for turns at boundary ;#define testturns -9 ;#ifdef testturns

1140 ;ldi temp, low(testturns)

Page 18: Lathe Spindle Sensor

;mov turnsl, temp ;ldi temp, high(testturns) ;mov turnsh, temp ;#endif ;get encoder inputs, build jump index in proper bit positions 0002aa b300 in temp, PIND ; use port input pins, not the logical port ! 0002ab fb05 bst temp, AbitIn ; copy new A input bit into T flag 0002ac f961 bld encode, AbitNew ; copy T flag into new A bit position in encode 0002ad f963 bld encode, AbitOld ; copy T flag into new A bit position in encode

1150 0002ae fb04 bst temp, BbitIn ; ditto for B input 0002af f960 bld encode, BbitNew ; encode now holds xxxx ABab (A is old a is new) 0002b0 f962 bld encode, BbitOld ; encode now holds xxxx ABab (A is old a is new) 0002b1 9508 ret ;-------------------------------------------------------------------- ; ShowRPM - load display buffer with RPM ; - input:none (reads from rpml:rpmh, maint. by UpdateISREvent() ) ; - return:none (output placed in displaybfr[0..3], maint. by T0 isr) ;-------------------------------------------------------------------- ShowRPM:

1160 0002b2 9140 0085 lds BinaryIn16_L, rpm 0002b4 9150 0086 lds BinaryIn16_H, rpm+1 0002b6 d0c2 rcall Display4Dec 0002b7 9508 ret ;-------------------------------------------------------------------- ; ShowDegrees - load display buffer with current angular position (degrees) ; - input:none (calc from stepsl:stepsh, maint. by T1 isr) ; - return:none (output placed in displaybfr[0..3], maint. by T0 isr) ; need degrees = (steps/2000)*360 = (steps/100)*18 ; (if ENCODERSTEPS = 2000, that is)

1170 ; so, multiply steps*18, then convert to 5 bcd digits. use only the top 4 ;-------------------------------------------------------------------- ShowDegrees: 0002b8 2f48 mov BinaryIn16_L, stepsl 0002b9 2f59 mov BinaryIn16_H, stepsh ;multiply by 18, convert to bcd, display 0002ba e000 ldi temp, high((360*100)/ENCODERSTEPS) ;load 18 (if .equ's haven't changed) 0002bb 2ef0 mov Binarywk16_H, temp 0002bc e102 ldi temp, low((360*100)/ENCODERSTEPS) 0002bd 2ee0 mov Binarywk16_L, temp

1180 0002be d12f rcall mpy16u ;multiply binaryin16*binarywk16->binaryin16 0002bf e6ea ldi ZL, low(bcdresult+0) ; point to result for binary-to-bcd conversion 0002c0 e0f0 ldi ZH, high(bcdresult+0) 0002c1 d0da rcall DisplayTop4Dec ; 0002c2 9508 ret ;-------------------------------------------------------------------- ; calcturns - build up 10 digit # turns in bcdresult; ttttt.ssss ; ;-------------------------------------------------------------------- CalcTurns:

1190 0002c3 93af push xl 0002c4 93bf push xh 0002c5 2400 clr r0 ;r0 holds the number of leading zeros 0002c6 2711 clr temp2 ;temp2 holds flag (1) if #turns is negative rereadturns: 0002c7 2da4 mov XL, turnsl ;get stable copy of turnsl:h into X 0002c8 2db5 mov XH, turnsh 0002c9 2fc8 mov YL, stepsl ;get stable copy of stepsl:h into Y 0002ca 2fd9 mov YH, stepsh 0002cb 17c8 cp YL, stepsl ;movement while reading?

1200 0002cc f7d1 brne rereadturns ;so read it again ;check if turns is negative 0002cd 23bb tst XH ;check if msb of #turns is a negative # 0002ce f44a brpl ShowfTurnspositive ;negate #turns, fractional turn should be considered negative; 2000-stepsl: 0002cf e011 ldi temp2, 1 ;remember turns are negative 0002d0 95b0 com XH ;negate turns into a a normal looking # 0002d1 95a0 com XL ; subi XL,low(-1) ;need to sub 1 anyway, so don't add 1 here ; sbci XH,high(-1)

1210 ;"negate" # steps, subtracting from 2000 0002d2 ed00 ldi temp, low(ENCODERSTEPS) 0002d3 1b0c sub temp, yl 0002d4 2fc0 mov yl, temp 0002d5 e007 ldi temp, high(ENCODERSTEPS) 0002d6 0b0d sbc temp, yh 0002d7 2fd0 mov yh, temp

Page 19: Lathe Spindle Sensor

showfturnspositive: ;convert #steps from 0-1999 t0 0..998 fractional (divide by two) 0002d8 95d6 lsr yh

1220 0002d9 95c7 ror yl ;build the fractional part (steps) to bottom of bcdresult[5..9] 0002da 2f4c mov binaryin16_l, yl 0002db 2f5d mov binaryin16_h, yh 0002dc e6ed ldi ZL, low(bcdresult+3) ; start at 4th char 0002dd e0f0 ldi ZH, high(bcdresult+3) 0002de d0e6 rcall Bin2ToBcd5 ; load bcdresult array with bcd values ;build the integer part (turns) to top of bcdresult[0..4] 0002df 2f4a mov binaryin16_l, xl 0002e0 2f5b mov binaryin16_h, xh

1230 0002e1 e6ea ldi ZL, low(bcdresult) ; point to result for binary-to-bcd conversion 0002e2 e0f0 ldi ZH, high(bcdresult) 0002e3 d0e1 rcall Bin2ToBcd5 ; load bcdresult array with bcd values ;count number of leading zeros 0002e4 e6aa ldi XL, low(bcdresult) 0002e5 e0b0 ldi XH, high(bcdresult) 0002e6 efef ldi ZL, -1 ;start with -1 leading zeroes leadzcount: 0002e7 95e3 inc ZL ;zeroed on first pass 0002e8 30e4 cpi ZL, 4

1240 0002e9 f019 breq maxed 0002ea 910d ld temp, x+ 0002eb 1501 cp temp, zero 0002ec f3d1 breq leadzcount maxed: 0002ed 91bf pop xh 0002ee 91af pop xl 0002ef 9508 ret ;-------------------------------------------------------------------- ; ShowFracTurns - load display buffer with current # turns (-999 to 9999)

1250 ; - input:none (uses turnsl:turnsh maint. by T1 isr) ; - return:none (output placed in displaybfr[0..3], maint. by T0 isr) ; note: if #turns decrements behind zero, the count becomes ffff; this is ; detected by bit 15 ;-------------------------------------------------------------------- ShowFracTurns: 0002f0 dfd2 rcall calcturns ;set up pointers to bcd number (nnnnn.nnnnn) and to display (1234) 0002f1 93e0 008b sts debugl, zl ;save for examination using debug display mode 0002f3 e7c4 ldi YL, low(displaybfr) ;Yl:h points to display buffer

1260 0002f4 e0d0 ldi YH, high(displaybfr) 0002f5 e6aa ldi XL, low(bcdresult) ;xl:h points to ttttt.sssss (turns.fractturns) 0002f6 e0b0 ldi XH, high(bcdresult) ; ;check polarity 0002f7 3011 cpi temp2, 1 0002f8 f041 breq showturnsnegative ;positive turns: adjust offsets based on positive number (4 digits avail) ;offset into bcdresult by # leading zeroes, but not less than 1 or more tha 0002f9 30e4 cpi zl, 4 0002fa f008 brlo under4lz

1270 0002fb e0e3 ldi zl, 3 ;adjust to 3 max under4lz: 0002fc 11e1 cpse zl, zero 0002fd 95ea dec zl ;decr cancels next line, unless # leading zeroes is zero 0002fe 95e3 inc zl ;#leading zeroes is 0, bump up to floor (1) 0002ff 0fae add xl, ZL ;offset by (adjusted) # leading zeroes 000300 c009 rjmp showplus showturnsnegative: ;negative turns: adjust offsets based on negative number (1st digit is a '-

1280 ;offset into bcdresult by # leading zeroes, but not less than 2 or more tha 000301 30e2 cpi zl, 2 000302 f418 brsh showminus 000303 e0e2 ldi zl, 2 ;don't go below 2 000304 0fae add xl, ZL ;offset by (adjusted) # leading zeroes 000305 c000 rjmp showminus showminus: 000306 0fae add xl, ZL ;offset by (adjusted) # leading zeroes 000307 e400 ldi temp, DDRS_MINUS 000308 9309 st y+, temp

1290 000309 c005 rjmp lower showplus: 00030a 910d ld temp, x+

Page 20: Lathe Spindle Sensor

;rcall getsegments 00030b 2c01 mov r0, zero 00030c 1101 cpse temp, zero ;if first digit of positive is zero, leave it blank 00030d d040 rcall getsegments 00030e 9209 st y+, r0 ;store digit lower: 00030f 910d ld temp, x+

1300 000310 d03d rcall getsegments 000311 9209 st y+, r0 ;store digit 000312 910d ld temp, x+ 000313 d03a rcall getsegments 000314 9209 st y+, r0 ;store digit 000315 910d ld temp, x+ 000316 d037 rcall getsegments 000317 9209 st y+, r0 ;store digit ;now see where that decimal point goes; digits at (bcdresult+5) & up are fr 000318 9100 0078 lds temp, displaybfr+4

1310 00031a 790f andi temp, ~(DDRS_DP1 | DDRS_DP2) 00031b 37a1 cpi xl, low(bcdresult+7) 00031c f019 breq showft_dp2 00031d 37a0 cpi xl, low(bcdresult+6) 00031e f019 breq showft_dp1 00031f c003 rjmp showft_nodp showft_dp2: 000320 6200 ori temp, DDRS_DP2 000321 c001 rjmp showft_nodp showft_dp1:

1320 000322 6400 ori temp, DDRS_DP1 showft_nodp: 000323 9300 0078 sts displaybfr+4, temp showfturnsexit: 000325 9508 ret ;-------------------------------------------------------------------- ; ShowSteps - load display buffer with raw encoder count (bcd) ; - input:none (reads from stepsl:stepsh, maint. by T1 isr) ;(debug use,ui ?) - return:none (output in displaybfr[0..3] for use by T0 isr ;--------------------------------------------------------------------

1330 ShowSteps: 000326 2f48 mov BinaryIn16_L, stepsl 000327 2f59 mov BinaryIn16_H, stepsh ;note: stepsl:h is volatile but no need to re-read; would overwrite before ;and nothing depends on display from this debug function. 000328 d050 rcall Display4Dec 000329 9508 ret ;-------------------------------------------------------------------- ; Showmilliseconds - load display buffer w/millisecond (0..999) + seconds(0..9 ; - input:none (reads from milliseconds maint. mainline)

1340 ;(debug use,not ui) - return:none (output in displaybfr[0..3] for use by T0 ;-------------------------------------------------------------------- ShowMilliseconds: #ifdef _showmilliseconds #endif 00032a 9508 ret ;-------------------------------------------------------------------- ; Showseconds - load display buffer with second count ; - input:none (reads from seconds maint. mainline) ;(debug use,not ui) - return:none (output in displaybfr[0..3] for use by T0

1350 ;-------------------------------------------------------------------- Showseconds: ;load bottom 2 digits with seconds 00032b 9140 0062 lds BinaryIn16_L, seconds 00032d 2755 clr BinaryIn16_H 00032e e6ea ldi ZL, low(bcdresult) ; point to result for binary-to-bcd conversion 00032f e0f0 ldi ZH, high(bcdresult) 000330 d094 rcall Bin2ToBcd5 ; load bcdresult array with bcd values 000331 9100 006e lds temp, bcdresult+4 000333 d01a rcall getsegments

1360 000334 9200 0077 sts displaybfr+3, r0 000336 9100 006d lds temp, bcdresult+3 000338 d015 rcall getsegments 000339 9200 0076 sts displaybfr+2, r0 ;load top 2 digits with minutes 00033b 9140 0063 lds BinaryIn16_L, minutes 00033d 2755 clr BinaryIn16_H 00033e e6ea ldi ZL, low(bcdresult) ; point to result for binary-to-bcd conversion 00033f e0f0 ldi ZH, high(bcdresult)

Page 21: Lathe Spindle Sensor

000340 d084 rcall Bin2ToBcd5 ; load bcdresult array with bcd values 1370 000341 9100 006e lds temp, bcdresult+4

000343 d00a rcall getsegments 000344 9200 0075 sts displaybfr+1, r0 000346 9100 006d lds temp, bcdresult+3 000348 d005 rcall getsegments 000349 9200 0074 sts displaybfr+0, r0 00034b 9508 ret ;-------------------------------------------------------------------- ; Showctdown - load display buffer with second count ; - input:none (reads from seconds maint. mainline)

1380 ;(debug use,not ui) - return:none (output in displaybfr[0..3] for use by T0 ;-------------------------------------------------------------------- Showctdown: #ifdef countdown #endif 00034c 9508 ret ;-------------------------------------------------------------------- ; Showdebug - load display buffer with debug vars debugl:h ; - input:debugl:h ;(debug use,not ui) - return:none (output in displaybfr[0..3] for use by T0

1390 ;-------------------------------------------------------------------- ShowDebug: #ifdef _showdebug #endif 00034d 9508 ret ;-------------------------------------------------------------------- ; getsegments - load segment pattern for digit in temp, into r0 ; input: temp (bcd value), output:r0 (segment pattern) ;-------------------------------------------------------------------- getsegments:

1400 00034e e0f0 ldi ZH, high(2*tabledigits) ;point Z to the segment pattern table in ro 00034f e3e4 ldi ZL, low(2*tabledigits) ;" 000350 0fe0 add ZL, temp ;now move pointer to desired character (0..9) 000351 1df1 adc ZH, zero ;(in case carry from low byte needed) 000352 95c8 lpm ; r0 now holds byte from rom 000353 9508 ret ;---------------------------------------------------------------------------- ; Display4ROM - load display with 4 chars from ROM at ZL:ZH ;---------------------------------------------------------------------------- Display4ROM:

1410 000354 93af push XL 000355 93bf push XH 000356 e7a4 ldi XL, low(displaybfr) 000357 e0b0 ldi XH, high(displaybfr) 000358 e004 ldi temp, 4 Display4ROMloop: 000359 95c8 lpm ;r0 now holds segments 00035a 9631 adiw z, 1 00035b 920d st X+, r0 00035c 950a dec temp

1420 00035d 3000 cpi temp, 0 00035e f7d1 brne Display4ROMloop 00035f 91bf pop XH 000360 91af pop XL 000361 9508 ret ;---------------------------------------------------------------------------- ; Display4Hex ; Input is 16-bit binary value in BinaryIn16_H:L ; output is stored as 4 hex characters in the display bfr ;----------------------------------------------------------------------------

1430 Display4Hex: 000362 2f04 mov temp, BinaryIn16_L 000363 700f andi temp, 0x0f 000364 dfe9 rcall getsegments 000365 9200 0077 sts displaybfr+3, r0 000367 2f04 mov temp, BinaryIn16_L 000368 9502 swap temp 000369 700f andi temp, 0x0f 00036a dfe3 rcall getsegments

1440 00036b 9200 0076 sts displaybfr+2, r0 00036d 2f05 mov temp, BinaryIn16_H 00036e 700f andi temp, 0x0f 00036f dfde rcall getsegments

Page 22: Lathe Spindle Sensor

000370 9200 0075 sts displaybfr+1, r0 000372 2f05 mov temp, BinaryIn16_H 000373 9502 swap temp 000374 700f andi temp, 0x0f

1450 000375 dfd8 rcall getsegments 000376 9200 0074 sts displaybfr+0, r0 000378 9508 ret ;---------------------------------------------------------------------------- ; Display4Dec ; Input is 16-bit binary value in BinaryIn16_H:L ; output is stored as 4 decimal characters in the display bfr ; leading zeroes are blanked ; note that numbers over 9999 will not show the 10,000 place number ;----------------------------------------------------------------------------

1460 Display4Dec: 000379 931f push temp2 00037a e6ea ldi ZL, low(bcdresult); point to result for binary-to-bcd conversion 00037b e0f0 ldi ZH, high(bcdresult) 00037c d048 rcall Bin2ToBcd5 ; load bcdresult array with bcd values ;load digit1 00037d 2400 clr r0 ;default seg pattern is off (zero) 00037e 9100 006b lds temp, bcdresult+1 000380 2f10 mov temp2, temp ;start tracking leading zeroes 000381 1111 cpse temp2, zero

1470 000382 dfcb rcall getsegments ;load R0 with seg only if not zero 000383 9200 0074 sts displaybfr+0, r0;store segments in display buffer ;load digit2 000385 9100 006c dd2:lds temp, bcdresult+2 000387 2b10 or temp2, temp ;temp2 now zero only if 1st & 2nd digits zero 000388 2400 clr r0 000389 1111 cpse temp2, zero 00038a dfc3 rcall getsegments 00038b 9200 0075 sts displaybfr+1, r0 ;load digit3

1480 00038d 9100 006d lds temp, bcdresult+3 00038f 2b10 or temp2, temp ;temp2 now zero only if 1st & 2nd digits zero 000390 2400 clr r0 000391 1111 cpse temp2, zero 000392 dfbb rcall getsegments 000393 9200 0076 sts displaybfr+2, r0 ;load digit4 (least signigicant) of the display buffer 000395 9100 006e lds temp, bcdresult+4 000397 dfb6 rcall getsegments 000398 9200 0077 sts displaybfr+3, r0

1490 00039a 911f pop temp2 00039b 9508 ret ;----------------------------------------------------------------------------- ; DisplayTop4Dec ; Input is 16-bit binary value in BinaryIn16_H:L ; output is stored as 4 decimal characters in the display bfr ; The 4 most sig. digits are shown; lsb not shown but it *will* round up the o ;(allows showing a 5 digit number, divided by 10 and rounded up) ;----------------------------------------------------------------------------- DisplayTop4Dec:

1500 00039c e6ea ldi ZL, low(bcdresult) ; point to result for binary-to-bcd conversion 00039d e0f0 ldi ZH, high(bcdresult) 00039e d026 rcall Bin2ToBcd5 ; load bcdresult array with bcd values ;check for need to round up, based on the 5th lsb not seen 00039f 9100 006e lds temp, bcdresult+4 0003a1 3005 cpi temp, 5 ;if it is 5, should roundup 0003a2 f020 brlo displt4hdone ;bummer. when lsb+3 is incr, it might carry into higher digits. 0003a3 5004 subi temp, 4 ; how much to increment. 0003a4 0f40 add BinaryIn16_L, temp

1510 0003a5 1d51 adc BinaryIn16_H, zero 0003a6 cff5 rjmp DisplayTop4Dec ;bin2tobcd5 preserved BinaryIn16_L:H displt4hdone: ;load digit1 0003a7 2400 clr r0 0003a8 9100 006a lds temp, bcdresult 0003aa 2f10 mov temp2, temp ;start tracking leading zeroes 0003ab 1111 cpse temp2, zero 0003ac dfa1 rcall getsegments 0003ad 9200 0074 sts displaybfr+0, r0

1520 ;load digit2

Page 23: Lathe Spindle Sensor

0003af 9100 006b lds temp, bcdresult+1 0003b1 2b10 or temp2, temp ;temp2 now zero only if 1st & 2nd digits zero 0003b2 2400 clr r0 0003b3 1111 cpse temp2, zero 0003b4 df99 rcall getsegments 0003b5 9200 0075 sts displaybfr+1, r0 ;load digit3 0003b7 9100 006c lds temp, bcdresult+2 0003b9 2b10 or temp2, temp ;temp2 now zero only if 1st & 2nd digits zero

1530 0003ba 2400 clr r0 0003bb 1111 cpse temp2, zero 0003bc df91 rcall getsegments 0003bd 9200 0076 sts displaybfr+2, r0 ;load digit4 (least signigicant) of the display buffer 0003bf 9100 006d lds temp, bcdresult+3 0003c1 df8c rcall getsegments 0003c2 9200 0077 sts displaybfr+3, r0 0003c4 9508 ret

1540 ;---------------------------------------------------------------------------- ; public utility code used, from Atmel.com, www.avr-asm-tutorial.net ;---------------------------------------------------------------------------- ; Bin2ToBcd5 ; ========== ; converts a 16-bit-binary to a 5-digit-BCD ; In: 16-bit-binary in BinaryIn16_H:L, Z points to first digit ; where the result goes to ; Out: 5-digit-BCD, Z points to first BCD-digit

1550 ; Used registers: BinaryIn16_H:L (unchanged), BinaryWk16_H:L (changed), ; temp ; Called subroutines: Bin2ToDigit Bin2ToBcd5: 0003c5 935f push BinaryIn16_H ; Save number 0003c6 934f push BinaryIn16_L 0003c7 930f push temp 0003c8 e207 ldi temp,HIGH(10000) ; Start with tenthousands 0003c9 2ef0 mov BinaryWk16_H,temp 0003ca e100 ldi temp,LOW(10000)

1560 0003cb 2ee0 mov BinaryWk16_L,temp 0003cc d015 rcall Bin2ToDigit ; Calculate digit 0003cd e003 ldi temp,HIGH(1000) ; Next with thousands 0003ce 2ef0 mov BinaryWk16_H,temp 0003cf ee08 ldi temp,LOW(1000) 0003d0 2ee0 mov BinaryWk16_L,temp 0003d1 d010 rcall Bin2ToDigit ; Calculate digit 0003d2 e000 ldi temp,HIGH(100) ; Next with hundreds 0003d3 2ef0 mov BinaryWk16_H,temp 0003d4 e604 ldi temp,LOW(100)

1570 0003d5 2ee0 mov BinaryWk16_L,temp 0003d6 d00b rcall Bin2ToDigit ; Calculate digit 0003d7 e000 ldi temp,HIGH(10) ; Next with tens 0003d8 2ef0 mov BinaryWk16_H,temp 0003d9 e00a ldi temp,LOW(10) 0003da 2ee0 mov BinaryWk16_L,temp 0003db d006 rcall Bin2ToDigit ; Calculate digit 0003dc 8340 st z,BinaryIn16_L ; Remainder are ones 0003dd 9734 sbiw ZL,4 ; Put pointer to first BCD 0003de 910f pop temp

1580 0003df 914f pop BinaryIn16_L ; Restore original binary 0003e0 915f pop BinaryIn16_H 0003e1 9508 ret ; and return ; ; Bin2ToDigit ; =========== ; converts one decimal digit by continued subraction of a ; binary coded decimal ; Used by: Bin2ToBcd5, Bin2ToAsc5, Bin2ToAsc ; In: 16-bit-binary in BinaryIn16_H:L, binary coded decimal in

1590 ; BinaryWk16_H:L, Z points to current BCD digit ; Out: Result in Z, Z incremented ; Used registers: BinaryIn16_H:L (holds remainder of the binary), ; BinaryWk16_H:L (unchanged), temp ; Called subroutines: - ; Bin2ToDigit:

Page 24: Lathe Spindle Sensor

0003e2 2700 clr temp ; digit count is zero Bin2ToDigita: 0003e3 155f cp BinaryIn16_H,BinaryWk16_H ; Number bigger than decimal?

1600 0003e4 f038 brcs Bin2ToDigitc ; MSB smaller than decimal 0003e5 f411 brne Bin2ToDigitb ; MSB bigger than decimal 0003e6 154e cp BinaryIn16_L,BinaryWk16_L ; LSB bigger or equal decimal 0003e7 f020 brcs Bin2ToDigitc ; LSB smaller than decimal Bin2ToDigitb: 0003e8 194e sub BinaryIn16_L,BinaryWk16_L ; Subtract LSB decimal 0003e9 095f sbc BinaryIn16_H,BinaryWk16_H ; Subtract MSB decimal 0003ea 9503 inc temp ; Increment digit count 0003eb cff7 rjmp Bin2ToDigita ; Next loop Bin2ToDigitc:

1610 0003ec 9301 st z+,temp ; Save digit and increment 0003ed 9508 ret ; done ;*************************************************************************** ;* ;* "mpy16u" - 16x16 Bit Unsigned Multiplication ;* ;* This subroutine multiplies the two 16-bit register variables ;* BinaryIn16_H:BinaryIn16_L and BinaryWk16_H:BinaryWk16_L ;* The result is placed in m16u3:m16u2:binaryin16H:binary16in_L

1620 ;* ;* Number of words :14 + return ;* Number of cycles :153 + return ;* Low registers used : ;* High registers used :7 (mp16uL,mp16uH,mc16uL/m16u0,mc16uH/m16u1,m16u2, ;* m16u3,temp) ;* ;*************************************************************************** mpy16u: 0003ee 2499 clr m16u3 ;clear 2 highest bytes of result

1630 0003ef 2488 clr m16u2 0003f0 e100 ldi temp,16 ;init loop counter 0003f1 9556 lsr BinaryIn16_H 0003f2 9547 ror BinaryIn16_L m16u_1: 0003f3 f410 brcc noad8 ;if bit 0 of multiplier set 0003f4 0c8e add m16u2,Binarywk16_l ;add multiplicand Low to byte 2 of res 0003f5 1c9f adc m16u3,BinaryWk16_H ;add multiplicand high to byte 3 of res noad8: 0003f6 9497 ror m16u3 ;shift right result byte 3

1640 0003f7 9487 ror m16u2 ;rotate right result byte 2 0003f8 9557 ror binaryin16_h;m16u1 ;rotate result byte 1 and multiplier High 0003f9 9547 ror binaryin16_l;m16u0 ;rotate result byte 0 and multiplier Low 0003fa 950a dec temp ;decrement loop counter 0003fb f7b9 brne m16u_1 ;if not done, loop more 0003fc 9508 ret RESOURCE USE INFORMATION ------------------------

1650 Notice: The register and instruction counts are symbol table hit counts, and hence implicitly used resources are not counted, eg, the 'lpm' instruction without operands implicitly uses r0 and z, none of which are counted. x,y,z are separate entities in the symbol table and are counted separately from r26..r31 here.

1660 .dseg memory usage only counts static data declared with .byte AT90S2313 register use summary: r0 : 43 r1 : 38 r2 : 4 r3 : 2 r4 : 7 r5 : 5 r6 : 0 r7 : 0 r8 : 3 r9 : 3 r10: 7 r11: 0 r12: 0 r13: 4 r14: 19 r15: 19 r16: 225 r17: 36 r18: 40 r19: 15 r20: 34 r21: 35 r22: 11 r23: 3 r24: 16 r25: 11 r26: 28 r27: 18 r28: 13 r29: 11 r30: 68 r31: 32 x : 19 y : 5 z : 15 Registers used: 31 out of 35 (88.6%)

1670 AT90S2313 instruction use summary: adc : 9 add : 15 adiw : 8 and : 0 andi : 18 asr : 0 bclr : 0 bld : 6 brbc : 0 brbs : 0 brcc : 1 brcs : 2

Page 25: Lathe Spindle Sensor

breq : 16 brge : 0 brhc : 0 brhs : 0 brid : 0 brie : 0 brlo : 8 brlt : 0 brmi : 0 brne : 22 brpl : 5 brsh : 3 brtc : 0 brts : 0 brvc : 0 brvs : 0 bset : 0 bst : 4 cbi : 0 cbr : 0 clc : 0 clh : 0 cli : 1 cln : 0 clr : 34 cls : 0 clt : 0 clv : 0 clz : 0 com : 12 cp : 10 cpc : 0 cpi : 35 cpse : 14 dec : 11 eor : 0 icall : 0 ijmp : 2 in : 10 inc : 18 ld : 8 ldd : 0

1680 ldi : 107 lds : 52 lpm : 10 lsl : 6 lsr : 3 mov : 54 neg : 0 nop : 0 or : 10 ori : 6 out : 17 pop : 23 push : 23 rcall : 55 ret : 25 reti : 10 rjmp : 51 rol : 0 ror : 7 sbc : 5 sbci : 4 sbi : 0 sbic : 0 sbis : 2 sbiw : 1 sbr : 0 sbrc : 0 sbrs : 1 sec : 0 seh : 0 sei : 3 sen : 0 ser : 0 ses : 0 set : 0 sev : 0 sez : 0 sleep : 0 st : 23 std : 0 sts : 58 sub : 6 subi : 5 swap : 3 tst : 9 wdr : 0 Instructions used: 52 out of 100 (52.0%)

1690 AT90S2313 memory use summary [bytes]: Segment Begin End Code Data Used Size Use% --------------------------------------------------------------- [.cseg] 0x000000 0x0007fa 1922 120 2042 2048 99.7% [.dseg] 0x000060 0x0000af 0 79 79 128 61.7% [.eseg] 0x000000 0x000000 0 0 0 128 0.0% Assembly complete, 0 errors, 0 warnings