;USER YOUR BROWSER'S BACK BUTTON TO GO BACK.
;Copy this text directly into your assembler editor.
;The code was writtent with AVR Studio 3.5.x
;Copyright 2003 Richard Cappels, projects(at)cappels.org,
; http://www.projects.cappels.org

;*********************************
;2313 waveform capture control and LED display firmware
;*********************************

.include "2313def.inc"


;This program is meant to simulate an ASCII serial terminal for the purpose of displaying
;control panel information from the Waveform Capture controller on a 4 digit LED display
;and accepting input from a set of user input buttons on the cotnrol panel.

;I/O is connected as follows:
;LED display is a 4 character common cathode display.

;LED display segment definition is below:
; AAAAAA
; F B
; F B
; GGGGGG
; E C
; E C
; DDDDDD DP

;ledlut: ;LED Look-Up Table, Segent codes for 0..9 on 7 segment display
; 0 1 2 3 4 5 6 7 8 9 blank minus
;.db $3F,$06,$5B,$4F,$66,$6D,$7d,$07,$7F, $6F, $00, $40
;The look-up table above is only used as a reference.

;PB0 through 1 K resistor to LED segment A
;PB1 through 1 K resistor to LED segment B
;PB2 through 1 K resistor to LED segment C
;PB3 through 1 K resistor to LED segment D
;PB4 through 1 K resistor to LED segment E
;PB5 through 1 K resistor to LED segment F
;PB6 through 1 K resistor to LED segment G
;PB7 through 1 K resistor to LED decimal point (though not used in this firmware)


;PD5 connects to cathode 1 (left-most digit)
;PD4 connects to cathode 2
;PD3 connects to cathdoe 3
;PD2 connects to cathdoe 4 (right-most digit)

;Push button connections are as follows:
;Six bottons are connected from PB0 thorought PB5. The remaining terminal of each
;button is connected to a common conductor that is connected to ground through
;a 1K resistor.

;PD6 is not used.


;UART baud rate calculation
.equ clock = 4000000 ;clock frequency
.equ baudrate = 9600 ;choose a baudrate
.equ baudconstant = (clock/(16*baudrate))-1


;Assign LED Connections
.equ segmentA = 0 ;Port B
.equ segmentB = 1 ;Port B
.equ segmentC = 2 ;Port B
.equ segmentD = 3 ;Port B
.equ segmentE = 4 ;Port B
.equ segmentF = 5 ;Port B
.equ segmentG = 6 ;Port B
.equ decimalpoint = 7;Port B
.equ cathode1 = 5 ;Port D
.equ cathode2 = 4 ;Port D
.equ cathode3 = 3 ;Port D
.equ cathode4 = 2 ;Port D


;Assign working registers

.def temp = r16 ;general purpose variable
.def char1 = r17 ;bit pattern for left-most LED character
.def char2 = r18 ;bit pattern for LED char 2
.def char3 = r19 ;bit pattern for LED char 3
.def char4 = r20 ;bit pattern for right-most LED character
.def buttonimage = r21 ;captured button bit pattern
.def scratch = r22 ;second general purpose variable
.def interruptcount = r23 ;round robin multitask counter

;Assignment of flag bits in waveform capture chip and sent after adding the value $50 to it.
;bit 0 if set, indicates that display is to be erased before being rewritten
;bit 1 if set, allows sampling of analog signal
;bit 2 if set, selects for triggering on positive edge of trigger signal
;bit 3 if set, selects for free run (non-triggered operation)
;bit 4
;bit 5
;bit 6
;bit 7


.org $000
rjmp init ;Reset handler.
.org $006
rjmp timerservice ;Timer interrupt handler.



init:

ldi temp,low(ramend)
out spl,temp ;Set lowe byte of stack pointer (there is no high byte)..

ldi temp,$FF ;Make all I/O poins outputs
out ddrd,temp
out ddrb,temp

ldi temp,baudconstant
out ubrr,temp ;Load baudrate.
sbi ucr,rxen ;Enable WAUT receive (also sets PD0 to input)
sbi ucr,txen ;Enable UART Transmit



ldi temp, $03 ;Use temp to initaize timer prescaler..
out TCCR0, temp
ldi temp,$00 ;Use temp to initialize counter.
out TCNT0,temp
ldi temp, $02 ;Use temp to initialize TIMSK.
out TIMSK,temp

clr interruptcount

sei ;ENABLE THE TIMER INTERRUPTS HERE


ldi char1,$FF
ldi char2,$FF
ldi char3,$40 ;Char 3 is always a minus sign
ldi char4,$FF





loop: ;Main loop checks UART for incoming character and updates display accordingly
;Get char from UART into temp
sbis usr,rxc ;Skip if no char in UART
rjmp nc1
in temp,udr ;Read byte
;Interpret byte


cpi temp,$30 ;Compare incoming byte with timebase codes and
brne n30 ;write the pattern that makes the right display.
rjmp code30
n30:

cpi temp,$31
brne n31
rjmp code31
n31:


cpi temp,$32
brne n32
rjmp code32
n32:
cpi temp,$33
brne n33
rjmp code33
n33:
cpi temp,$34
brne n34
rjmp code34
n34:


cpi temp,$35
brne n35
rjmp code35
n35:


cpi temp,$36
brne n36
rjmp code36
n36:

cpi temp,$37
brne n37
rjmp code37
n37:

cpi temp,$38
brne n38
rjmp code38
n38:

cpi temp,$39
brne n39
rjmp code39
n39:

cpi temp,$3A
brne n3A
rjmp code3A
n3A:

cpi temp,$3B
brne n3B
rjmp code3B
n3B:

cpi temp,$3C
brne n3C
rjmp code3C
n3C:

nc1:
rjmp loop ;Do forever





; These are short routines to write the necessary bit patterns to the LED timebase display.

code30: ;1us
ldi char1,$00
ldi char2,$06
ldi char4,$7D
rjmp loop

code31: ;2us
ldi char1,$00
ldi char2,$5B
ldi char4,$7D
rjmp loop

code32: ;5us
ldi char1,$00
ldi char2,$6D
ldi char4,$7D
rjmp loop


code33: ;10us
ldi char1,$06
ldi char2,$3F
ldi char4,$7D
rjmp loop


code34: ;20us
ldi char1,$5B
ldi char2,$3F
ldi char4,$7D
rjmp loop

code35: ;50us
ldi char1,$6D
ldi char2,$3F
ldi char4,$7D
rjmp loop


code36: ;100us
ldi char1,$00
ldi char2,$06
ldi char4,$66
rjmp loop

code37: ;200us
ldi char1,$00
ldi char2,$5B
ldi char4,$66
rjmp loop

code38: ;500us
ldi char1,$00
ldi char2,$6D
ldi char4,$66
rjmp loop

code39: ;1ms
ldi char1,$00
ldi char2,$06
ldi char4,$4F
rjmp loop

code3A: ;2ms
ldi char1,$00
ldi char2,$5B
ldi char4,$4F
rjmp loop

code3B: ;5ms
ldi char1,$00
ldi char2,$6D
ldi char4,$4F
rjmp loop

code3C: ;10ms
ldi char1,$06
ldi char2,$3F
ldi char4,$4F
rjmp loop



buttest: ;Used by interrupt service routine
sca1:
rcall buttoncap ;Return if no buttons down
cpi buttonimage,$FF
brne buttonisdown
ret

buttonisdown:
mov scratch,buttonimage

sd1: rcall buttoncap
cpi buttonimage,$FF
brne sd1

cpi scratch,$EF
brne notef
ldi temp,$41
rjmp sendit

notef:
cpi scratch,$DF
brne notdf
ldi temp,$46
rjmp sendit

notdf:

cpi scratch,$F7
brne notf7
ldi temp,$44
rjmp sendit

notf7:
cpi scratch,$FB
brne notfb
ldi temp,$49
rjmp sendit

notfb:

cpi scratch,$FE
brne notfe
ldi temp,$45
rjmp sendit

notfe:
cpi scratch,$FD
brne notfd
ldi temp,$43
rjmp sendit

notfd:
ret

sendit: rcall emitchar

ret


buttoncap: ;Capture status of buttons into buttonimage.
;Leave Port D and B as inputs
ldi temp,$00
out DDRD,temp ;Make PORT D inputs.
out DDRB,temp ;Make PORT B inputs.
ldi temp,$FF
out PORTB,temp ;Turn on pullups on port B.
ldi temp,$00 ;Wait for lines to settle.
dl1: dec temp
brne dl1
in buttonimage,PINB ;Capture button state.
ldi temp,$00
out PORTB,temp ;Write $00 to port B. (leave Port D as inputs)
ret


emitchar: ;Send character from temp via UART
sbis usr,udre ;wait until the register is cleared
rjmp emitchar
out udr,temp ;send the byte
ret



receivechar: ;Get char from UART into temp
sbis usr,rxc ;Check for byte in UART from terminal
rjmp receivechar
in temp,udr ;Read byte
ret




timerservice: ;service timer interrupt

;round-robin multitasking, different task on each interrupt.
;Here are the tasks:
;display digit1
;display digit2
;display digit3
;display digit4
;check buttons

push temp
lds temp,$5F ;Push status register onto stack.
push temp

inc interruptcount ;Point to the next task.
cpi interruptcount,$05 ;Only 5 tasks allowed, the wrap around to first.
brne cne1
ldi interruptcount,$00
cne1:


ldi temp,$00 ;Turn off display
out ddrd,temp
; Round-robin starts here
cpi interruptcount,$00
breq showchar1
cpi interruptcount,$01
breq showchar2
cpi interruptcount,$02
breq showchar3
cpi interruptcount,$03
breq showchar4
cpi interruptcount,$04
breq checkbuttons
rjmp endoftimerservice ;This jump should not execute if things are going well.

showchar1:
out portb,char1
ldi temp,$00
out portd,temp
sbi ddrd,5
ldi temp,$FF
out ddrb,temp
rjmp endoftimerservice


showchar2:
out portb,char2
ldi temp,$00
out portd,temp
sbi ddrd,4
ldi temp,$FF
out ddrb,temp
rjmp endoftimerservice



showchar3:
out portb,char3
ldi temp,$00
out portd,temp
sbi ddrd,3
ldi temp,$FF
out ddrb,temp
rjmp endoftimerservice



showchar4:
out portb,char4
ldi temp,$00
out portd,temp
sbi ddrd,2
ldi temp,$FF
out ddrb,temp
rjmp endoftimerservice


checkbuttons:
in temp,udr ;Read byte in UART to clear char from buffer
rcall buttest
rjmp endoftimerservice


endoftimerservice:
pop temp
sts $5F,temp ;restore status register
pop temp
reti

;
;This is example code and is neither warranted to be useful for any particular purpose, nor to be safe to any degree.
;See http://www.projects.cappels.org for intellectual property and non-liability statement.
;
;  /////END OF DOCUMENT\\\\\\