SlideShare une entreprise Scribd logo
1  sur  25
Télécharger pour lire hors ligne
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.0
All Mode LED's x,y,&z off when simple timer
H LED indicates forward rotation
L 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 timing
states are needed, one for each digit and one for the misc leds. If a switch is pressed, an idle source driver output (programmed high
with 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 sink
PD2 Digit2 src, Mode Sw Src
PD3 Digit3 src, Zero Sw src
PD4 Encoder B
PD5 Encoder A
PD6 Digit4 source
PB0 Seg A sink, Z src
PB1 Seg B sink, Y src
PB2 Seg C sink, X src
PB3 Seg D sink, L src
PB4 Seg E sink, H src
PB5 Seg F sink, DP2 src
PB6 Seg G sink, DP1 src
PB7 Digit1 src, Sw common
d:workavrlathelathespeedsensor.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
f
gg
f
e
d
c
b
a
g
f
e
d
c
b
aa
b
c
d
e
f
g
1 2 3 4
X
Y
Z
DP2 DP1
DP3
H
L
U?
LC204MB
1
3
24
223
11
4
5
6
187
178
16
13
10
9
14
12
15
22
21
20
19
Z+
1+
XYZ-
Y+X+
c-
d-
2+
DP2+
DP2-DP3+
DP3-3+
DP1-
L-
4+
DP1+
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
1
3
5
2
4
6
Q?
VP0104
J?
1
2
3
4
5
J?
1
2
3
4
5
U?
HEDS5600
1
2
3
5
4
Gnd
nc/index
A
B
Vcc
Y?
12MHz
C?
22pF
D? 1N4001
R? 390
R? 390
J?
CON3
1
2
3
-+
D?
Schottky, noise suppression
R?
1500
U?90S2313
20
10
1
2
3
5
4
6
7
8
9
19
18
17
16
15
14
13
12
11
Vcc
Gnd
RESET
PD0/RxD
PD1/TxD
Xtal-In
Xtal-Out
PD2/Int0
PD3/Int1
PD4/T0
PD5/T1
PB7/SCK
PB6/MISO
PB5/MOSI
PB4
PB3/OC1
PB2
PB1/AIN1
PB0/AIN0
PD6/ICP
R?
10K
R?
15K
D?
5.1V
Q?
VP0104
1
AVRASM ver. 2.1.9 D:WorkAVRLathecodeLatheSensor_ASM.asm Fri Dec 22 04:24:35 2006
D:WorkAVRLathecodeLatheSensor_ASM.asm(52): Including file 'C:Program FilesAtmelAVR 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 ; "
.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
.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
;--------------------------------------------------------------------
.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
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
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
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
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)
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
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)
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
;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
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
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
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)
;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
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+
;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)
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
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
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:
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
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

Contenu connexe

Tendances

CODING IN ARDUINO
CODING IN ARDUINOCODING IN ARDUINO
CODING IN ARDUINO
S Ayub
 
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
SANTIAGO PABLO ALBERTO
 

Tendances (20)

Uart VHDL RTL design tutorial
Uart VHDL RTL design tutorialUart VHDL RTL design tutorial
Uart VHDL RTL design tutorial
 
Intro2 Robotic With Pic18
Intro2 Robotic With Pic18Intro2 Robotic With Pic18
Intro2 Robotic With Pic18
 
Practical file
Practical filePractical file
Practical file
 
CODING IN ARDUINO
CODING IN ARDUINOCODING IN ARDUINO
CODING IN ARDUINO
 
Class9
Class9Class9
Class9
 
UART MCU
UART MCUUART MCU
UART MCU
 
Dsd lab Practical File
Dsd lab Practical FileDsd lab Practical File
Dsd lab Practical File
 
FINISHED_CODE
FINISHED_CODEFINISHED_CODE
FINISHED_CODE
 
Lecture 5 (system clock crossbar and gpio) rv012
Lecture 5 (system clock crossbar and gpio) rv012Lecture 5 (system clock crossbar and gpio) rv012
Lecture 5 (system clock crossbar and gpio) rv012
 
Programming A Robot Using
Programming A Robot UsingProgramming A Robot Using
Programming A Robot Using
 
98788885 ic-lab-maual
98788885 ic-lab-maual98788885 ic-lab-maual
98788885 ic-lab-maual
 
abc song
abc songabc song
abc song
 
Original Driver Mosfet IR4427PBF 4427 DIP-8 New
Original Driver Mosfet IR4427PBF 4427 DIP-8 NewOriginal Driver Mosfet IR4427PBF 4427 DIP-8 New
Original Driver Mosfet IR4427PBF 4427 DIP-8 New
 
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
Electrónica: Receptor DTMF integrado MT8870D/MT8870D-1 (Datasheet)
 
Módulo adc 18f4550
Módulo adc   18f4550Módulo adc   18f4550
Módulo adc 18f4550
 
Uart
UartUart
Uart
 
Digital System Design Lab Report - VHDL ECE
Digital System Design Lab Report - VHDL ECEDigital System Design Lab Report - VHDL ECE
Digital System Design Lab Report - VHDL ECE
 
Programming avr microcontroller digital i
Programming avr microcontroller digital iProgramming avr microcontroller digital i
Programming avr microcontroller digital i
 
Embedded Systems Project Based Training|Engineering Projects,Summer Training
Embedded Systems Project Based Training|Engineering Projects,Summer TrainingEmbedded Systems Project Based Training|Engineering Projects,Summer Training
Embedded Systems Project Based Training|Engineering Projects,Summer Training
 
OptimizingARM
OptimizingARMOptimizingARM
OptimizingARM
 

En vedette

Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
Receipt Bank and Xero Advanced Techniques Certification- Acmad M.Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
Maddybear04231990
 
Khotso Tsaagane(Diploma)
Khotso Tsaagane(Diploma)Khotso Tsaagane(Diploma)
Khotso Tsaagane(Diploma)
Khotso Tsaagane
 
EA Training Document
EA Training DocumentEA Training Document
EA Training Document
Gary Cohen
 
Plano de contas 11638
Plano de contas 11638Plano de contas 11638
Plano de contas 11638
Bruna Castro
 
GIRL'S DENIM PANT (DGL)
GIRL'S DENIM PANT (DGL)GIRL'S DENIM PANT (DGL)
GIRL'S DENIM PANT (DGL)
DGL BD. LTD
 
black history month script edit
black history month script editblack history month script edit
black history month script edit
jovanna romero
 

En vedette (18)

Tc2aecnicas de-estudio1 (1)
Tc2aecnicas de-estudio1 (1)Tc2aecnicas de-estudio1 (1)
Tc2aecnicas de-estudio1 (1)
 
Video marketing presentation
Video marketing presentationVideo marketing presentation
Video marketing presentation
 
SrinathSrinivasan
SrinathSrinivasanSrinathSrinivasan
SrinathSrinivasan
 
Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
Receipt Bank and Xero Advanced Techniques Certification- Acmad M.Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
Receipt Bank and Xero Advanced Techniques Certification- Acmad M.
 
Khotso Tsaagane(Diploma)
Khotso Tsaagane(Diploma)Khotso Tsaagane(Diploma)
Khotso Tsaagane(Diploma)
 
Apuntes filiacion
Apuntes filiacionApuntes filiacion
Apuntes filiacion
 
EA Training Document
EA Training DocumentEA Training Document
EA Training Document
 
簡報004 (6年2班)&動畫&切換&音樂
簡報004  (6年2班)&動畫&切換&音樂簡報004  (6年2班)&動畫&切換&音樂
簡報004 (6年2班)&動畫&切換&音樂
 
Plano de contas 11638
Plano de contas 11638Plano de contas 11638
Plano de contas 11638
 
Glosario- Laura Camacho
Glosario- Laura CamachoGlosario- Laura Camacho
Glosario- Laura Camacho
 
Blazstar
BlazstarBlazstar
Blazstar
 
Epifin_u3_ea_masj
Epifin_u3_ea_masjEpifin_u3_ea_masj
Epifin_u3_ea_masj
 
GIRL'S DENIM PANT (DGL)
GIRL'S DENIM PANT (DGL)GIRL'S DENIM PANT (DGL)
GIRL'S DENIM PANT (DGL)
 
black history month script edit
black history month script editblack history month script edit
black history month script edit
 
Jari Turunen: Mikä GAS-menetelmässä haastaa ja mikä tuntuu helpolta?
Jari Turunen: Mikä GAS-menetelmässä haastaa ja mikä tuntuu helpolta?Jari Turunen: Mikä GAS-menetelmässä haastaa ja mikä tuntuu helpolta?
Jari Turunen: Mikä GAS-menetelmässä haastaa ja mikä tuntuu helpolta?
 
Six Sigma Green Belt
Six Sigma Green BeltSix Sigma Green Belt
Six Sigma Green Belt
 
Contabilidad en egipto
Contabilidad en egiptoContabilidad en egipto
Contabilidad en egipto
 
I pone.
I pone.I pone.
I pone.
 

Similaire à Lathe Spindle Sensor

ARM Architecture Instruction Set
ARM Architecture Instruction SetARM Architecture Instruction Set
ARM Architecture Instruction Set
Dwight Sabio
 
Arm teaching material
Arm teaching materialArm teaching material
Arm teaching material
John Williams
 
Vechicle accident prevention using eye bilnk sensor ppt
Vechicle accident prevention using eye bilnk sensor pptVechicle accident prevention using eye bilnk sensor ppt
Vechicle accident prevention using eye bilnk sensor ppt
satish 486
 
What will be quantization step size in numbers and in voltage for th.pdf
What will be quantization step size in numbers and in voltage for th.pdfWhat will be quantization step size in numbers and in voltage for th.pdf
What will be quantization step size in numbers and in voltage for th.pdf
SIGMATAX1
 

Similaire à Lathe Spindle Sensor (20)

EEE UNIT-2 PPT.pdf
EEE UNIT-2 PPT.pdfEEE UNIT-2 PPT.pdf
EEE UNIT-2 PPT.pdf
 
Lec2.ppt
Lec2.pptLec2.ppt
Lec2.ppt
 
ARM Architecture Instruction Set
ARM Architecture Instruction SetARM Architecture Instruction Set
ARM Architecture Instruction Set
 
Arm teaching material
Arm teaching materialArm teaching material
Arm teaching material
 
Arm teaching material
Arm teaching materialArm teaching material
Arm teaching material
 
Vechicle accident prevention using eye bilnk sensor ppt
Vechicle accident prevention using eye bilnk sensor pptVechicle accident prevention using eye bilnk sensor ppt
Vechicle accident prevention using eye bilnk sensor ppt
 
Microcontroller avr
Microcontroller avrMicrocontroller avr
Microcontroller avr
 
LCD_Example.pptx
LCD_Example.pptxLCD_Example.pptx
LCD_Example.pptx
 
ARM instruction set
ARM instruction  setARM instruction  set
ARM instruction set
 
What will be quantization step size in numbers and in voltage for th.pdf
What will be quantization step size in numbers and in voltage for th.pdfWhat will be quantization step size in numbers and in voltage for th.pdf
What will be quantization step size in numbers and in voltage for th.pdf
 
Digital logic-formula-notes-final-1
Digital logic-formula-notes-final-1Digital logic-formula-notes-final-1
Digital logic-formula-notes-final-1
 
8255
82558255
8255
 
ARM instruction set
ARM instruction  setARM instruction  set
ARM instruction set
 
set de instrucciones primera parte de atmel
set de instrucciones primera parte de atmelset de instrucciones primera parte de atmel
set de instrucciones primera parte de atmel
 
knowledge in daily life.ppt
knowledge in daily life.pptknowledge in daily life.ppt
knowledge in daily life.ppt
 
ARM AAE - Intrustion Sets
ARM AAE - Intrustion SetsARM AAE - Intrustion Sets
ARM AAE - Intrustion Sets
 
6to4tunnel sample config
6to4tunnel sample config6to4tunnel sample config
6to4tunnel sample config
 
Microcontroller 8051
Microcontroller 8051Microcontroller 8051
Microcontroller 8051
 
LUMOS
LUMOSLUMOS
LUMOS
 
Galil rio catalog
Galil rio catalogGalil rio catalog
Galil rio catalog
 

Lathe Spindle Sensor

  • 1.
  • 2. 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.0 All Mode LED's x,y,&z off when simple timer H LED indicates forward rotation L 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 timing states are needed, one for each digit and one for the misc leds. If a switch is pressed, an idle source driver output (programmed high with 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 sink PD2 Digit2 src, Mode Sw Src PD3 Digit3 src, Zero Sw src PD4 Encoder B PD5 Encoder A PD6 Digit4 source PB0 Seg A sink, Z src PB1 Seg B sink, Y src PB2 Seg C sink, X src PB3 Seg D sink, L src PB4 Seg E sink, H src PB5 Seg F sink, DP2 src PB6 Seg G sink, DP1 src PB7 Digit1 src, Sw common d:workavrlathelathespeedsensor.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 f gg f e d c b a g f e d c b aa b c d e f g 1 2 3 4 X Y Z DP2 DP1 DP3 H L U? LC204MB 1 3 24 223 11 4 5 6 187 178 16 13 10 9 14 12 15 22 21 20 19 Z+ 1+ XYZ- Y+X+ c- d- 2+ DP2+ DP2-DP3+ DP3-3+ DP1- L- 4+ DP1+ 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 1 3 5 2 4 6 Q? VP0104 J? 1 2 3 4 5 J? 1 2 3 4 5 U? HEDS5600 1 2 3 5 4 Gnd nc/index A B Vcc Y? 12MHz C? 22pF D? 1N4001 R? 390 R? 390 J? CON3 1 2 3 -+ D? Schottky, noise suppression R? 1500 U?90S2313 20 10 1 2 3 5 4 6 7 8 9 19 18 17 16 15 14 13 12 11 Vcc Gnd RESET PD0/RxD PD1/TxD Xtal-In Xtal-Out PD2/Int0 PD3/Int1 PD4/T0 PD5/T1 PB7/SCK PB6/MISO PB5/MOSI PB4 PB3/OC1 PB2 PB1/AIN1 PB0/AIN0 PD6/ICP R? 10K R? 15K D? 5.1V Q? VP0104
  • 3. 1 AVRASM ver. 2.1.9 D:WorkAVRLathecodeLatheSensor_ASM.asm Fri Dec 22 04:24:35 2006 D:WorkAVRLathecodeLatheSensor_ASM.asm(52): Including file 'C:Program FilesAtmelAVR 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 ; "
  • 4. .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
  • 5. .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 ;--------------------------------------------------------------------
  • 6. .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
  • 7. 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
  • 8. 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
  • 9. 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
  • 10. 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)
  • 11. 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
  • 12. 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)
  • 13. 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
  • 14. ;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
  • 15. 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
  • 16. 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
  • 17. 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)
  • 18. ;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
  • 19. 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+
  • 20. ;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)
  • 21. 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
  • 22. 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
  • 23. 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:
  • 24. 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
  • 25. 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