; Specify Device.
.include "8515def.inc"
;
; registers used
;
.DEF EDIT_STATE1=r16; status of editing for PWM value1
.DEF EDIT_STATE2=r17; status of editing for PWM value2
.DEF SEG7 =r20; Register for seven segment LEDs
.DEF PWM_VALUE =R22; Register that will contain value for PWM
.DEF list_inc =r23;
.DEF rgen1 =r24; general register 1
.DEF rgen2 =R25; general register 2
.DEF EEdrd =r0 ;result data byte
.DEF EEdwr =r26 ;data byte to write to EEPROM
.DEF EEawr =r27 ;address low byte to write to
.DEF EEawrh =r28 ;address high byte to write to
.DEF EEard =r27 ;address low byte to write to
.DEF EEardh =r28 ;address high byte to write to
; Constants
.EQU DIGIT =PortA; Controls the seven segment LEDs
.EQU LEDS_OUT =PortC; handles two LEDs for the switches
.EQU PWM_OUT =PortD; recieves the PWM digital settings
.EQU SW1_PIN =0;
.EQU SW2_PIN =1;
.EQU IN_PORT =PINB; Various push buttons
.EQU EE_addr1 =$10;
.EQU EE_addrh1 =$00;
.EQU EE_addr2 =$20;
.EQU EE_addrh2 =$00;
;
; Code segment start
;
.CSEG
rjmp Start;
rjmp Start;
rjmp Start;
;
; Subroutines here
EEWrite:
sbic EECR,EEWE ;if EEWE not clear
rjmp EEwrite ; wait more
out EEARH,EEawrh ;output address high for 8515
out EEARL,EEawr ;output address low for 8515
out EEDR,EEdwr ;output data
sbi EECR,EEMWE ;set master write enable
sbi EECR,EEWE ;set EEPROM Write strobe
ret
EERead:
sbic EECR,EEWE ;if EEWE not clear
rjmp EERead ; wait more
out EEARH,EEardh ;output address high for 8515
out EEARL,EEard ;output address low for 8515
sbi EECR,EERE ;set EEPROM Read strobe
in EEdrd,EEDR ;get data
ret
delay20ms:
ldi rgen1, 60
outer_loop:
ldi rgen2, 255
inner_loop:
nop
nop
nop
nop
nop
nop
nop
dec rgen2
brne inner_loop
dec rgen1
brne outer_loop
ret
delaysec:
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
rcall delay20ms ;call a debounce delay routine
ret
get_PWM1_value:
ldi EEardh,EE_addrh1
ldi EEard, EE_addr1
rcall EERead
mov list_inc, EEdrd
ret
get_PWM2_value:
ldi EEardh,EE_addrh2
ldi EEard, EE_addr2
rcall EERead
mov list_inc, EEdrd
ret
save_PWM1_value:
mov EEdwr,list_inc
ldi EEawrh,EE_addrh1
ldi EEawr, EE_addr1
rcall EEWrite
ret
save_PWM2_value:
mov EEdwr,list_inc
ldi EEawrh,EE_addrh2
ldi EEawr, EE_addr2
rcall EEWrite
ret
;; the point where list_inc is used to load registers for SEG7 and PWM_VALUE.
;; function goes into the list containing various values for digits and pwm values.
;; it uses registers: r0, SEG7, and PWM_VALUE. It also uses list_inc, which counts
;; its way into pwm_list.
fix_list_len:
dec list_inc
get_PWM_settings:
ldi ZH,high(pwm_list*2)
ldi ZL,low(pwm_list*2)
lpm
mov rgen1, list_inc; dont destroy list_inc
loop1:
adiw ZL, 4
lpm
mov SEG7, r0
cpi SEG7, 0xff ;test for 0xff to see if at the end
breq fix_list_len
dec rgen1
cpi rgen1, 0
brne loop1
mov SEG7, r0 ;load on a value and shift it over four, this is "tens"
lsl SEG7
lsl SEG7
lsl SEG7
lsl SEG7
adiw ZL, 1 ;load on the ones
lpm
add SEG7, r0
adiw ZL, 1
lpm
mov PWM_VALUE, r0
ret
adjust_settings:
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11110011 ;wipe all bits except the 4th and 3rd to last
cpi rgen1, 0b00000100 ;check if one is pressed
brne not_3 ;if not check more
its_3:
rcall delay20ms ;call a debounce delay routine
waitfor_rel3: ;now wait for the switch to be
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11110011 ;wipe all bits except the 4th and 3rd to last
cpi rgen1, 0b00001100 ;perform test for release
brne waitfor_rel3
rcall delay20ms ; debounce after release
inc list_inc
rjmp _end
not_3:
cpi rgen1, 0b00001000 ;check if one is pressed
brne not_4 ;if not check more
its_4:
rcall delay20ms ;call a debounce delay routine
waitfor_rel4: ;now wait for the switch to be
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11110011 ;wipe all bits except the 4th and 3rd to last
cpi rgen1, 0b00001100 ;perform test for release
brne waitfor_rel4
rcall delay20ms ; debounce after release
dec list_inc
rjmp func_end
not_4: ; means that both or none are pressed.
; rcall delay20ms ;call a debounce delay routine
; do stuff here
func_end:
ret
;
; Start of program
;
Start:
;
; Setup the stack for the use of subroutines
;
ldi rgen1,HIGH(RAMEND); Stack setting to highest RAM adress
out SPH,rgen1
ldi rgen1,LOW(RAMEND)
out SPL,rgen1
ldi rgen1, 0b11111111 ;load register with all 1's
out DDRA, rgen1 ;configure PORT A for all outputs
; two of Port B's inputs are not used.
ldi rgen1, 0b00000000 ;load register with all 0's
out DDRB, rgen1 ;configure PORT B for all inputs
ldi rgen1, 0b11111111 ;load register with all 1's
out DDRC, rgen1 ;configure PORT C for all outputs
ldi rgen1, 0b11111111 ;load register with all 1's
out DDRD, rgen1 ;configure PORT D for all outputs
cbi LEDS_OUT, SW1_PIN ; turn em on.
cbi LEDS_OUT, SW2_PIN
ldi EDIT_STATE1, 0
ldi EDIT_STATE2, 0
; stabilize...
rcall delaysec
sbi LEDS_OUT, SW1_PIN ;make sure they're both off
sbi LEDS_OUT, SW2_PIN
main_loop:
; test if the edit switch is on
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11101111 ;wipe all bits except the fifth
cpi rgen1, 0b00000000 ;check if one is pressed
brne edit_switch_off
edit_switch_on:
rcall delay20ms ;call a debounce delay routine
cpi EDIT_STATE1, 1 ;check if EDIT_STATE is already set.
breq allow_edits ;if it is, dont perform other tests
cpi EDIT_STATE2, 1 ;check if EDIT_STATE2 is already set.
breq allow_edits
edit_state_not_set:
sbi LEDS_OUT, SW1_PIN ; turn off the LED for switch 1
sbi LEDS_OUT, SW2_PIN ; turn off the LED for switch 2
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11111100 ;wipe all bits except the last two
cpi rgen1, 0b00000010 ;check if one is pressed
brne not_1 ;if not check more
edit_request1:
rcall delay20ms ;call a debounce delay routine
ldi EDIT_STATE1, 1 ;flip this to ON
rcall get_PWM1_value ;this retreives the value from program memory
cbi LEDS_OUT, SW1_PIN ; turn on the LED for switch 1
sbi LEDS_OUT, SW2_PIN ; turn off the LED for switch 2
rjmp edit_end
not_1:
cpi rgen1, 0b00000001 ;check if one is pressed
brne not_2 ;if not check more
edit_request2:
rcall delay20ms ;call a debounce delay routine
ldi EDIT_STATE2, 1 ;flip this to ON
rcall get_PWM2_value ;this retreives the value from program memory
sbi LEDS_OUT, SW1_PIN ; turn off the LED for switch 1
cbi LEDS_OUT, SW2_PIN ; turn on the LED for switch 2
rjmp edit_end
not_2: ; means that both or none are pressed.
rcall delay20ms ;call a debounce delay routine
rjmp edit_end
allow_edits:
rcall get_PWM_settings
rcall adjust_settings
edit_end:
; set the PWM to a low setting here.
ldi PWM_VALUE, 0b00000011
out PWM_OUT, PWM_VALUE
rjmp _end
; the edit switch is not on.
; This is the "show" state -- when user has edit switch off and
; the driver is displaying its stored values and driving the PWM
; settings.
;First we handle the transition when there was an edit
; happening, and we want to store the edited values.
; Remember: only 100,000 or so writes can be made to the eeprom.
edit_switch_off:
rcall delay20ms ;call a debounce delay routine
cpi EDIT_STATE1, 0 ;check EDIT_STATE1 status.
breq edit1_not_on ;if it is off, jump
edit1_is_on:
ldi EDIT_STATE1, 0 ;turn it off
rcall save_PWM1_value
rjmp edit_test_end
edit1_not_on:
cpi EDIT_STATE2, 0 ;check if EDIT_STATE2 status.
breq edit_test_end ;if it is off, jump
edit2_is_on:
ldi EDIT_STATE2, 0 ;turn it off
rcall save_PWM2_value
edit_test_end:
; now check state of input pin requesting PWM1 or PWM2 setting
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11011111 ;wipe all bits except the sixth
cpi rgen1, 0b00100000 ;check its on
brne setting_is_lo ;if not check more
rcall get_PWM1_value ;this retreives the value from program memory
cbi LEDS_OUT, SW1_PIN ; turn on the LED for switch 1
sbi LEDS_OUT, SW2_PIN ; turn off the LED for switch 2
rjmp put_PWM_on_port
setting_is_lo:
sbi LEDS_OUT, SW1_PIN ; turn off the LED for switch 1
cbi LEDS_OUT, SW2_PIN ; turn on the LED for switch 2
rcall get_PWM2_value ;this retreives the value from program memory
put_PWM_on_port:
rcall get_PWM_settings ;list_inc has been set, call this function to load PWM_VALUE
out PWM_OUT, PWM_VALUE ; show PWM_VALUE to the world
; in this state user may request what the PWM value is for either
; of the PWM settings. This is done by pressing the PWM switches
; without the edit switch set to on. notice that this just pushes
; new values on the SEG7 for display, but the status of PWM_OUT
; stays the same.
mov rgen2, list_inc ;save this guy
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11111110 ;wipe all bits except 2nd
cpi rgen1, 0b00000000 ;check if sw1 is pressed
brne not_show_PWM1 ;if not check more
show_PWM1:
rcall delay20ms ;call a debounce delay routine
rcall get_PWM1_value ;this retreives the value from program memory
rcall get_PWM_settings ;list_inc has been set, call this function to load SEG7
mov list_inc, rgen2 ;restore this so it doesnt get used in put_PWM_on_port
cbi LEDS_OUT, SW1_PIN ; turn on the LED for switch 1
sbi LEDS_OUT, SW2_PIN ; turn off the LED for switch 2
out DIGIT, SEG7
; loop until user releases sw1
wait_for_rel_of_showPWM1:
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11111110 ;wipe all bits except the 2nd
cpi rgen1, 0b00000001 ;perform test for release
brne wait_for_rel_of_showPWM1
rcall delay20ms ; debounce after release
rjmp _end
not_show_PWM1:
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11111101 ;wipe all bits except last
cpi rgen1, 0b00000000 ;check if two is pressed
brne _end ;if here, neither button pressed
show_PWM2:
rcall delay20ms ;call a debounce delay routine
rcall get_PWM2_value ;this retreives the value from program memory
rcall get_PWM_settings ;list_inc has been set, call this function to load SEG7
mov list_inc, rgen2 ;restore this so it doesnt get used in put_PWM_on_port
sbi LEDS_OUT, SW1_PIN ; turn off the LED for switch 1
cbi LEDS_OUT, SW2_PIN ; turn on the LED for switch 2
out DIGIT, SEG7
; loop until user releases sw2
wait_for_rel_of_showPWM2:
in rgen1, IN_PORT ;read input buffer
cbr rgen1, 0b11111101 ;wipe all bits except the 1st
cpi rgen1, 0b00000010 ;perform test for release
brne wait_for_rel_of_showPWM2
rcall delay20ms ; debounce after release
_end:
out DIGIT, SEG7
rjmp main_loop
pwm_list:
.db 0,2,0,0x21
.db 0,6,1,0x21
.db 0,9,2,0x21
.db 1,2,3,0x21
.db 1,5,4,0x21
.db 1,8,5,0x21
.db 2,1,6,0x21
.db 2,4,7,0x21
.db 2,7,8,0x21
.db 3,1,9,0x21
.db 3,4,10,0x21
.db 3,7,11,0x21
.db 4,0,12,0x21
.db 4,3,13,0x21
.db 4,6,14,0x21
.db 4,9,15,0x21
.db 5,2,16,0x21
.db 5,6,17,0x21
.db 5,9,18,0x21
.db 6,2,19,0x21
.db 6,5,20,0x21
.db 6,8,21,0x21
.db 7,1,22,0x21
.db 7,4,23,0x21
.db 7,7,24,0x21
.db 8,1,25,0x21
.db 8,4,26,0x21
.db 8,7,27,0x21
.db 9,0,28,0x21
.db 9,3,29,0x21
.db 9,6,30,0x21
.db 9,9,31,0x21
.db 0xff,0xff,0xff,0xff ;test for 0xff to see if at the end