![]() |
AVR-Anwendungen Eieruhr RGB mit ATmega8515 Assembler-Quellcode |
;
; ***********************************
; * RGB eggtimer with ATmega8515 *
; * PWM controlled LED *
; * (C)2019 by Gerhard Schmidt *
; ***********************************
;
; Optimized for gavrasm assembler
; If you want to use a different assembler
.ifdef ATmega8515
.device "ATmega8515"
.else
.nolist
.include "m8515def.inc"
.list
.endif
;
; *****************************************
; D E B U G G I N G S I M U L A T I O N
; *****************************************
;
; These debug switches have an influence on the
; starting point, the software runs normal from
; this starting point. All switches have to be
; zero for normal operation.
;
; Accelerations (the software runs faster)
; Skip the 8 repetitions of PWM cycles
.equ debug_accelSkip8 = 0 ; 1=Debugging
; Skip the 256 pwm steps down to one
.equ debug_accelShortPwm = 0 ; 1=Debugging
; Display only two colors
.equ debug_accel2Colors = 0 ; 1=Debugging
;
; **********************************
; H A R D W A R E
; **********************************
;
; Device: , Package: 40-pin-PDIP
;
; _________
; 1 / |40
; L1B o--|PB0 VCC|--o V+3.7..5 V
; L1G o--|PB1 PA0|--o L9B
; L1R o--|PB2 PA1|--o L9G
; L2B o--|PB3 PA2|--o L9R
; L2G o--|PB4 PA3|--o L10B
; L2R o--|PB5 PA4|--o L10G
; L3B o--|PB6 PA5|--o L10R
; L3G o--|PB7 PA6|--o L11R
;RESET o--|RESET PA7|--o L11G
; L3R o--|PD0 PE0|--o Key
; L4B o--|PD1 PE1|--o NC
; L4G o--|PD2 PE2|--o OC1B/SPK
; L4R o--|PD3 PC7|--o L8R
; L5B o--|PD4 PC6|--o L8G
; L5G o--|PD5 PC5|--o L8B
; L5R o--|PD6 PC4|--o L7R
; L6B o--|PD7 PC3|--o L7G
; XTAL o--|XTAL2 PC2|--o L7B
; XTAL o--|XTAL1 PC1|--o L6R
; V- o--|GND PC0|--o L6G
; 20|__________|21
;
; **********************************
; H A R D W A R E P I N S
; **********************************
;
; Speaker output pins
.equ pSpkO = PORTE ; Output port
.equ pSpkD = DDRE ; Direction port
.equ bSpkO = PORTE2 ; Output pin
.equ bSpkD = DDE2 ; Direction pin
;
; Key input pins
.equ pKeyO = PORTE ; Key output port
.equ pKeyD = DDRE ; Direction port
.equ bKeyO = PORTE0 ; Output pin
.equ bKeyD = DDE0 ; Direction pin
;
; **********************************
; A D J U S T A B L E C O N S T
; **********************************
;
; Crystal clock
; When changing: adjust the gamut table, too!
; See the sound sheet in the Libre Office file
; eggtimer_rgb_m8515.ods for a tool to adjust
; the gamut table
.equ clock = 4194304 ; Clock frequency in Hz
;
; Sound selection, start with sound in octave
.equ cOctave = 3 ; Octave a^3
;
; Sound when stopping with key or at count end
.equ cSoundOff = 880 ; Sound frequency in Hz, a^2
;
; Sound when re-starting with key
.equ cSoundOn = 7040 ; Sound frequency in Hz, a^5
;
; Use the TC1 as sound starter
.equ tSoundCheck = 250 ; Milliseconds for flag checking
;
; Leave all red LEDs of previous minutes on
.equ cLeaveRedOn = 0 ; 1 Leaves all red LEDs on
; (Consumes up to 180 mA! Not recommended for
; battery operation)
;
; **********************************
; F I X & D E R I V. C O N S T
; **********************************
;
; The CTC value for the clock frequency
.equ cCtcDiv = 60*clock/512/256/8 ; Divider, default=240
.equ cTc0CompA = cCtcDiv-1
;
; Sounds for key operations
.equ CmpSoundOff = (clock + cSoundOff) / (2*cSoundOff)
.equ DurSoundOff = 2*cSoundOff ; Counter for one second
.equ CmpSoundOn = (clock + cSoundOn) /(2*cSoundOn)
.equ DurSoundOn = 2*cSoundOn ; Counter for one second
;
; Check if minute start has been reached
.equ Tc1DivFlg = (clock+500) / 1000 - 1 ; TC1Div
;
; **********************************
; R E G I S T E R S
; **********************************
;
; Start value registers: At PWM cycle start
.def r1Start = R0 ; Start values Led1/2/3
.def r2Start = R1 ; Start values Led4/5/6
.def r3Start = R2 ; Start values Led7/8/9
.def r4Start = R3 ; Start values Led8/9/10
; Current value registers: during PWM cycle
.def r1Curr = R4 ; Current values LEDs 1 to 3
.def r2Curr = R5 ; Current values LEDs 3 to 6
.def r3Curr = R6 ; Current values LEDs 6 to 8
.def r4Curr = R7 ; Current values LEDs 9 to 11
; free: R8..R12
.def rBlue = R13 ; Match value PWM blue LED
.def rGreen = R14 ; Match value PWM green LED
.def rRed = R15 ; Match value PWM red LED
.def rmp = R16 ; Define multipurpose register
.def rFlag = R17 ; Flag register
.equ bPh2 = 0 ; Phase 2 of color adjust
.equ bStopped = 1 ; Timing is stopped
.equ bSoundStart = 2 ; Start next sound
.equ bSoundActive = 3 ; Sound is active (toggle prevention)
; PWM Match values
.def rPCnt = R18 ; Counter number of PWM cycles
.def rBB = R19 ; Blue bit, left-shifted every minute
.def rPwm = R20 ; PWM phase counter
; free: R21..R23
.def rCntL = R24 ; Sound duration counter, LSB
.def rCntH = R25 ; dto., MSB
; Free: R27:R26 = X
; Used: R29:R28 = Y as LED position pointer
; Used: R31:R30 = Z as sound gamut pointer
;
; **********************************
; S R A M
; **********************************
;
.dseg
.org SRAM_START
; (no SRAM used, only for stack operations)
;
; **********************************
; C O D E
; **********************************
;
.cseg
.org 000000
;
; **********************************
; R E S E T & I N T - V E C T O R S
; **********************************
rjmp Main ; Reset vector
reti ; INT0 External Interrupt Request 0
reti ; INT1 External Interrupt Request 1
reti ; TIMER1 CAPT Timer/Counter1 Capture Event
reti ; TIMER1 COMPA Timer/Counter1 Compare Match A
rjmp Tc1CmpBIsr ; TIMER1 COMPB Timer/Counter1 Compare Match B
reti ; TIMER1 OVF Timer/Counter1 Overflow
reti ; TIMER0 OVF Timer/Counter0 Overflow
reti ; SPI, STC Serial Transfer Complete
reti ; USART, RXC USART, Rx Complete
reti ; USART, UDRE USART Data Register Empty
reti ; USART, TXC USART, Tx Complete
reti ; ANA_COMP Analog Comparator
rjmp Int2Isr ; INT2 External Interrupt Request 2
rjmp Tc0CmpIsr ; TIMER0 COMP Timer/Counter0 Compare Match
reti ; EE_RDY EEPROM Ready
reti ; SPM_RDY Store Program memory Ready;
;
; **********************************
; I N T - S E R V I C E R O U T .
; **********************************
;
; TC0 CTC compare interrupt
; occurs every 240/4.194,304 = 57.22 us
; maximum 240 clock cycles available
; increases rPwm and switches blue, green and/or
; red LED off if color matches occur
; if rPwm reaches zero, starts the next eight PWM cycles
; in Tc0CmpNextPwm
Tc0CmpIsr: ; 7 clock cycles for int and rjmp
out DDRA,R7 ; Output the current LED status, LED8 to LED11, +1=8
out DDRC,R6 ; dto., LED6 to LED8, +1=9
out DDRD,R5 ; dto., LED3 to LED5, +1=10
out DDRB,R4 ; dto., LED1 to LED3, +1=11
inc rPwm ; Next PWM value, +1=12
breq Tc0CmpNextPwm ; +1/2=13/14
cp rBlue,rPwm ; Blue value reached? +1=14
brne Tc0CmpNotBlue ; +1/2=15/16
ldd rmp,Y+4 ; Read blue register, +2=17
eor rmp,rBB ; Switch blue off, +1=18
std Y+4,rmp ; Write back to blue, +2=20
Tc0CmpNotBlue: ; 16/20 clock cycles
lsl rBB ; Point to green, +1=17/21
brcc Tc0CmpGreenNoC ; +1/2= 18/22/19/23
inc YL ; Next register, +1=19/23
rol rBB ; Carry to bit 0, +1=20/24
Tc0CmpGreenNoC: ; 19/20/23/24 clock cycles
cp rGreen,rPwm ; Green value reached? +1=20/21/24/25
brne Tc0CmpNotGreen ; No, skip green, +1/2=21/22/25/26/22/23/26/27
ldd rmp,Y+4 ; Read green LED, +2=23/24/27/28
eor rmp,rBB ; Green LED off, +1=24/25/28/29
std Y+4,rmp ; Write green LED, +2=26/27/30/31
Tc0CmpNotGreen: ; 22/23/26/27/30/31 clock cycles
lsl rBB ; Point to red, +1=23/24/27/28/31/32
brcc Tc0CmpRedNoC ; No carry, +1/2=24/25/28/29/31/32/25/26/29/30/33/34
inc YL ; +1=25/26/29/30/32/33
rol rBB ; +1=26/27/30/31/33/34
Tc0CmpRedNoC: ; 25/26/27/29/30/31/33/34 clock cycles
cp rRed,rPwm ; Red value reached? +1=26/27/28/30/31/32/34/35
brne Tc0CmpNotRed ; +1/2=27/28/29/31/32/33/35/36 and .../37
ldd rmp,Y+4 ; Read red led, +2=29/30/31/33/34/35/37/38
eor rmp,rBB ; Red led off, +1=30/31/32/34/35/36/38/39
std Y+4,rmp ; Write red, +2=32/33/34/36/37/38/40/41
Tc0CmpNotRed: ; 27..36 or 32..41 clock cycles
lsr rBB ; Back to green, +1=28..42
brcc Tc0CmpNoCG ; No carry, +1/2=29..43/30..45
dec YL ; Point back, +1=30..44
ror rBB ; Point to green, +1=31..45
Tc0CmpNoCG: ; 30..45 clock cycles
lsr rBB ; Back to blue, +1=31..46
brcc Tc0CmpNoCB ; No carry, +1/2=32..46/33..47
dec YL ; Point back, +1=33..47
ror rBB ; Point to blue, +1=34..48
Tc0CmpNoCB: ; 33..48 clock cycles
.if debug_accelShortPwm == 1
ldi rPwm,255 ; Shorten the PWM cycle
.endif
reti ; Compare complete, +4=37..52
; Compare run: requires 37..52 clock cycles out of 240
;
; The next PWM cycle starts
; starts every 256*240/4,194.304 = 14.65 ms
Tc0CmpNextPwm: ; 14 clock cycles
dec rPCnt ; Count pwm cycles down, +1=15
breq Tc0NxtCol ; Next color, +1/2=16/17
mov R4,R0 ; Copy start values to work, +1=17
mov R5,R1 ; dto., +1=18
mov R6,R2 ; dto., +1=19
mov R7,R3 ; dto., +1=20
reti ; Done, +4=24
; PWM repeat run: 24 cycles out of 240
;
; The next color
; starts every 8*256*240/4,194.304 = 117.19 ms
Tc0NxtCol: ; 17 clock cycles
.if debug_accelSkip8==1
ldi rPcnt,1 ; Skip the 8 repetitions
.else
ldi rPCnt,8 ; Restart PWM cycle counter, +1=18
.endif
sbrc rFlag,bStopped ; Check if stopped, +2/1=20/19
rjmp Tc0NxtColSet ; Stopped, skip increase, +2=21
sbrc rFlag,bPh2 ; Skip next if phase 1, +2/1=20/19
rjmp Tc0NxtCol2 ; Phase 2, +2=21
ld rmp,Y ; Read blue, +2=22
or rmp,rBB ; Set blue start bit, +1=23
st Y,rmp ; Write blue, +2=25
inc rBlue ; Increase blue value, +1=26
dec rGreen ; Decrease green value, +1=27
brne Tc0NxtColSet ; +1/2=28/29
sbr rFlag,1<<bPh2 ; Set phase 2 flag, +1=29
lsl rBB ; Point to green led, +1=30
brcc Tc0NxtColNoCG ; No carry, +1/2=31/32
inc YL ; Next register, +1=32
rol rBB ; Carry to bit 0, +1=33
Tc0NxtColNoCG: ; 32/33 clock cycles
ld rmp,Y ; Read green led, +2=34/35
eor rmp,rBB ; Clear green led, +1=35/36
st Y,rmp ; Write green led, +2=37/38
lsr rBB ; Point back to blue, +1=38/39
brcc Tc0NxtColSet ; No carry, +1/2=39/40/40/41
dec YL ; Point back, +1=40/41
ror rBB ; To blue, +1=41/42
.if debug_accel2Colors == 1
ldi rmp,1
mov rGreen,rmp
ldi rmp,255
mov rBlue,rmp
.endif
rjmp Tc0NxtColSet ; +2=43/44
; Phase 2 is running
; a) Switch red LED on in start register set
; b) Decrease blue, increase red
; c) If not zero: copy to work register set
; d) If zero: switch to next LED
Tc0NxtCol2: ; 21 clock cycles
dec rBlue ; Decrease blue, +1=22
inc rRed ; Increase red, +1=23
breq Tc0NxtLed ; Next LED on, +1/2=24/25
lsl rBB ; Point to green, +1=25
brcc Tc0NextCol2NoCGF ; +1/2=26/27
inc YL ; +1=27
rol rBB ; +1=28
Tc0NextCol2NoCGF: ; 27/28 clock cycles
lsl rBB ; Point to red, +1=28/29
brcc Tc0NextCol2NoCRF ; +1/2=30/31
; Hint: only one of the two shifts can have carry set
inc YL
rol rBB
Tc0NextCol2NoCRF: ; 30/31 clock cycles
ld rmp,Y ; Set red on, +2=32/33
or rmp,rBB ; +1=33/34
st Y,rmp ; +2=35/36
lsr rBB ; Back to green, +1=36/37
brcc Tc0NextCol2NoCRB ; +1/2=37/38/38/39
dec YL ; +1=38/39
ror rBB ; +1=39/40
Tc0NextCol2NoCRB: ; 38/39/40 clock cycles
lsr rBB ; Back to blue, +1=39/40/41
brcc Tc0NextCol2NoCGB ; +1/2=41/42/43
; Hint: Only one of the two shift can have carry set
dec YL
ror rBB
Tc0NextCol2NoCGB: ; 41/42/43 clock cycles
.if debug_accel2Colors == 1
ldi rmp,1
mov rBlue,rmp
ldi rmp,255
mov rRed,rmp
.endif
Tc0NxtColSet: ; 41..43 clock cycles
mov R4,R0 ; Start set to work set, Byte 1, +1=42..44
mov R5,R1 ; dto., Byte 2, +1=43..45
mov R6,R2 ; dto., Byte 3, +1=44..46
mov R7,R3 ; dto., Byte 4, +1=45..47
reti ; Done, +4=49..51
; Next color run = max 51 out of 240
;
; Next LED run
; starts every 512*8*256*240/4,194,304 = 60 s
Tc0NxtLed: ; 25 clock cycles
cbr rFlag,1<<bPh2 ; Clear phase 2 flag, +1=26
sbr rFlag,1<<bSoundStart ; Start sound, +1=27
ld rmp,Y ; Read current blue LED, +2=29
eor rmp,rBB ; Clear current blue LED, +1=30
st Y,rmp ; Write current blue LED, +2=32
ldi rmp,4 ; Set four steps forward, +1=33
cpi YL,3 ; YL at last position? +1=34
brne Tc0NxtLedNotLast ; No, +1/2=35/36
cpi rBB,32 ; rBB at red LED10? +1=36/37
brne Tc0NxtLedNotLed11 ; No, +1/2=37/38/38/39
; Counting is at the end, restart with key
ldi rmp,128 ; Red LED11 on, +1=38/39
out DDRA,rmp ; To led output, +1=39/40
ldi rmp,0 ; Stop TC0, +1=40/41
out TCCR0,rmp ; presc=0, +1=41/42
ldi rmp,1<<OCIE1B ; Clear TC0 ints, +1=42/43
out TIMSK,rmp ; Set int mask, +1=43/44
sbr rFlag,1<<bStopped ; Set stop flag, +1=44/45
ldi rmp,2 ; Prepare for restart, +1=45/46
mov R0,rmp ; +1=46/47
clr R1 ; +1=47/48
clr R2 ; +1=48/49
clr R3 ; +1=49/50
ldi rBB,1 ; +1=50/51
clr YL ; +1=51/52
ldi ZH,High(2*(GamutTable+16*(cOctave+2))) ; Init gamut
ldi ZL,Low(2*(GamutTable+16*(cOctave+2)))
reti ; Done, +4=55/56
Tc0NxtLedNotLed11: ; 38/39 clock cycles
cpi rBB,8 ; LED9 active? +1=39/40
brne Tc0NxtLedNotLast ; No, +1/2=40/41/41/42
ldi rBB,32 ; Set rBB to red LED10, +1=41/42
ldi rmp,96 ; Red LED10 and Green LED11, +1=42/43
mov R3,rmp ; To start register R3, +1=43/44
mov R7,rmp ; and to work register, +1=44/45
rjmp Tc0NxtLedSet ; +2=46/47
Tc0NxtLedNotLast: ; 36 clock cycles
.if cLeaveRedOn == 1
rjmp Tc0NxtLedShiftRbb ; do not clear red LED
.endif
tst YL ; At LED1/2/3? +1=37
brne Tc0NxtLedNotZero ; No, +1/2=38/39
cpi rBB,1 ; LED1? +1=39
breq Tc0NxtLedShiftRbb ; No, +1/2=40/41
Tc0NxtLedNotZero: ; 39/40 clock cycles
lsr rBB ; Point to last red LED, +1=40/41
brcc Tc0NxtLedNoCR ; No carry, +1/2=41/42/42/43
dec YL ; Move back, +1=42/43
ror rBB ; Carry to bit 7, +1=43/44
Tc0NxtLedNoCR: ; 42/43/44 clock cycles
ld rmp,Y ; Read last red LED, +2=44/45/46
eor rmp,rBB ; Clear last red LED, +1=45/46/47
st Y,rmp ; Write last red LED, +2=47/48/49
ldi rmp,5 ; Five positions left=next green, +1=48/49/50
Tc0NxtLedShiftRbb: ; 41/42 (rmp=4) or 49/50 (=5) clock cycles
lsl rBB ; Next led left, +1
brcc Tc0NxtLedNoC ; No carry, +1/2
inc YL ; Next port, +1
rol rBB ; Carry to bit 0, +1
Tc0NxtLedNoC:
dec rmp ; Next left shift, +1
brne Tc0NxtLedShiftRbb ; +1/2
; LSL/BRCC/DEC/BRNE last
; 6 cycles if carry is clear and rmp is not zerp
; 5 cycles if carry is clear and rmp is at zero
; 7 cycles if carry is set and rmp is not zero
; 6 cycles if carry is set and rmp is zero
; rmp can be 4 or five, a carry can only occur once,
; For rmp=4 the range is
; 3*6+5 = 23, if carry occurs: 1*7+2*6+5 = 24
; For rmp=5 the range is
; 4*6+5 = 29, if carry occurs: 1*7+3*6+5 = 30
; rmp=4: 41/42+23/24 = 64/65/66
; rmp=5: 49/50+29/30 = 78/79/80
; = 64..66/78..80 clock cycles
ld rmp,Y ; Read green LED, +2=66..68/80..82
or rmp,rBB ; Set green LED, +1=67..69/81..83
st Y,rmp ; Write green LED, +2=69..71/83..85
lsr rBB ; Shift to blue, +1=70..72/84..86
brcc Tc0NxtLedSet ; No carry, +1/2=71..73/85..87/72..74/86..88
dec YL ; Next register, +1=72..74/86..88
ror rBB ; Carry to bit 0, +1=73..75/87..89
Tc0NxtLedSet: ; 46..47/72..74/73..75/86..88/87..89
mov R4,R0 ; Copy start register set to work, +1
mov R5,R1 ; +1
mov R6,R2 ; +1
mov R7,R3 ; +1
reti ; +4
; Total cycles:
; Normal PWM step: 37..52
; Repeat PWM: 24
; Next Color: 49..51
; Next LED:
; End of count: 55..56
;
; /54..55/55..56/80..82/81..83/94..96/95..97
;
; TC1 Compare interrupt
Tc1CmpBIsr:
sbiw rCntL,1 ; Decrease counter
brne Tc1CmpBIsrRet ; Not zero
sbrs rFlag,bSoundActive ; Sound active?
rjmp Tc1CmpBIsr1 ; No, check sound start
ldi rmp,(1<<COM1B1) ; Clear OC1B on compare match
out TCCR1A,rmp
ldi rmp,High(Tc1DivFlg) ; Reload 1 ms divider
out OCR1AH,rmp ; CTC for 1 ms, MSB
ldi rmp,Low(Tc1DivFlg) ; dto., LSB
out OCR1AL,rmp ; dto., LSB
cbr rFlag,1<<bSoundActive ; Clear flag
Tc1CmpBIsr1:
sbrs rFlag,bSoundStart ; Start a sound?
rjmp Tc1CmpBIsrRestart
lpm rmp,Z+ ; Read note from gamut, MSB
out OCR1AH,rmp
lpm rmp,Z+ ; dto., LSB
out OCR1AL,rmp
lpm rCntL,Z+ ; Read duration from gamut, LSB
lpm rCntH,Z+ ; dto., MSB
ldi rmp,(1<<COM1B0) ; Toggle OC1B
out TCCR1A,rmp
ldi rmp,(1<<CS10)|(1<<WGM12) ; Prescaler = 1
out TCCR1B,rmp
cbr rFlag,1<<bSoundStart ; Clear start flag
sbr rFlag,1<<bSoundActive ; Set active flag
reti
Tc1CmpBIsrRestart:
ldi rCntH,High(tSoundCheck) ; Reload counter, MSB
ldi rCntL,Low(tSoundCheck) ; dto., LSB
Tc1CmpBIsrRet:
reti
;
; Start/Stop key interrupt
Int2Isr:
sbrc rFlag,bSoundActive ; Sound active?
rjmp Int2IsrRet ; Yes
sbrc rFlag,bStopped ; Not stopped?
rjmp Int2IsrStart ; No
ldi rCntH,High(DurSoundOn)
ldi rCntL,Low(DurSoundOn)
ldi rmp,HIGH(CmpSoundOn)
out OCR1AH,rmp
ldi rmp,LOW(CmpSoundOn)
out OCR1AL,rmp
ldi rmp,(1<<COM1B0) ; Toggle OC1B
out TCCR1A,rmp
ldi rmp,(1<<CS10)|(1<<WGM12) ; Prescaler = 1
out TCCR1B,rmp
sbr rFlag,(1<<bSoundActive)|(1<<bStopped)
reti
Int2IsrStart:
ldi rCntH,High(DurSoundOff)
ldi rCntL,Low(DurSoundOff)
ldi rmp,HIGH(CmpSoundOff)
out OCR1AH,rmp
ldi rmp,LOW(CmpSoundOff)
out OCR1AL,rmp
ldi rmp,(1<<COM1B0) ; Toggle OC1B
out TCCR1A,rmp
ldi rmp,(1<<CS10)|(1<<WGM12) ; Prescaler = 1
out TCCR1B,rmp
sbr rFlag,(1<<bSoundActive)
cbr rFlag,(1<<bStopped)
; Prepare the first PWM cycle
mov R4,R0
mov R5,R1
mov R6,R2
mov R7,R3
clr rPwm ; to cycle start
ldi rmp,(1<<WGM01)|(1<<CS00) ; Restart TC0
out TCCR0,rmp
ldi rmp,(1<<OCIE0)|(1<<OCIE1B)
out TIMSK,rmp
Int2IsrRet:
reti
;
; **********************************
; M A I N P R O G R A M I N I T
; **********************************
;
Main:
.ifdef SPH ; if SPH is defined
ldi rmp,High(RAMEND)
out SPH,rmp ; Init MSB stack pointer
.endif
ldi rmp,Low(RAMEND)
out SPL,rmp ; Init LSB stack pointer
; Init TC1 as sound generator
ldi ZH,High(2*(GamutTable+16*(cOctave+2))) ; Z to selected octave
ldi ZL,Low(2*(GamutTable+16*(cOctave+2)))
cbi pSpkO,bSpkO ; Speaker output clear
sbi pSpkD,bSpkD ; Speaker output direction
ldi rCntH,High(tSoundCheck) ; Check sound every ... ms
ldi rCntL,Low(tSoundCheck)
ldi rmp,High(Tc1DivFlg) ; Set division CTC, MSB
out OCR1AH,rmp ; To the compare A port, MSB
ldi rmp,Low(Tc1DivFlg) ; dto., LSB
out OCR1AL,rmp ; dto., LSB
clr rmp ; Set compare interrupt B, MSB
out OCR1BH,rmp ; Set MSB
ldi rmp,1 ; LSB = 1
out OCR1BL,rmp ; dto., LSB
ldi rmp,1<<COM1B1 ; Clear output on match
out TCCR1A,rmp ; in control port A
ldi rmp,(1<<CS10)|(1<<WGM12) ; Prescaler=1, timer mode CTC-A
out TCCR1B,rmp ; in control port B
sbr rFlag,1<<bSoundStart ; Start first sound
; Init registers
ldi rmp,0x02 ; Start with LED 1 green
mov R0,rmp ; To PWM start value
clr R1 ; All other LEDs blanked
clr R2
clr R3
mov R4,rmp ; and to current value
clr R5
clr R6
clr R7
clr rBB ; Set register pointer to LED 1
inc rBB
.if debug_accelSkip8 == 1
ldi rPCnt,1 ; Skip the 8 repetitions
.else
ldi rPCnt,8
.endif
clr YH ; Start pointer with LED 0
clr YL
; Init TC0 as CTC for PWM interrupts
ldi rmp,cTc0CompA ; Compare value
out OCR0,rmp ; to compare port
ldi rmp,(1<<WGM01)|(1<<CS00) ; CTC, Prescaler = 1
out TCCR0,rmp ; To control port
ldi rmp,(1<<OCIE0)|(1<<OCIE1B) ; Compare match int TC0 and TC1
out TIMSK,rmp ; To timer int mask
; Start first PWM cycle
out DDRA,r4Curr
out DDRC,r3Curr
out DDRD,r2Curr
out DDRB,r1Curr ; Start LED 1
; Init Key input and INT2 interrupts
cbi pKeyD,bKeyD ; Direction input
sbi pKeyO,bKeyO ; Pull up resistor on
ldi rmp,1<<ISC2 ; Int2 on falling edges
out EMCUCR,rmp ; To extended MCUCR
ldi rmp,1<<INT2 ; Enable INT2 interrupt
out GICR,rmp ; in interrupt control register
ldi rmp,1<<SE ; Sleep mode idle
out MCUCR,rmp ; To Master control port
sei ; Enable interrupts
;
; **********************************
; P R O G R A M L O O P
; **********************************
;
Loop:
sleep ; Go to sleep
nop ; Dummy after wake-up
rjmp loop
;
; Assembler table with the music notes
; Word 1: Compare value for CTC (MSB first)
; Word 2: Counter value for one second duration
GamutTable:
.dw 0xF194,0x007B ; Tone A1m, 55 Hz (0.00%)
.dw 0xB184,0x0083 ; Tone H1m, 61,7354 Hz (0.00%)
.dw 0x3E7D,0x0093 ; Tone Cm, 65,4064 Hz (0.00%)
.dw 0x946F,0x00A5 ; Tone Dm, 73,4162 Hz (0.00%)
.dw 0x6863,0x00AF ; Tone Em, 82,4069 Hz (0.00%)
.dw 0xD35D,0x00C4 ; Tone Fm, 87,3071 Hz (0.00%)
.dw 0x9753,0x00DC ; Tone Gm, 97,9989 Hz (0.00%)
.dw 0x784A,0x00F7 ; Tone Am, 110 Hz (0.00%)
.dw 0x5842,0x0106 ; Tone Hm, 123,471 Hz (0.00%)
.dw 0x9F3E,0x0126 ; Tone c, 130,813 Hz (0.00%)
.dw 0xCA37,0x014A ; Tone d, 146,832 Hz (0.00%)
.dw 0xB331,0x015D ; Tone e, 164,814 Hz (0.00%)
.dw 0xE92E,0x0188 ; Tone f, 174,614 Hz (0.00%)
.dw 0xCB29,0x01B8 ; Tone g, 195,998 Hz (0.00%)
.dw 0x3C25,0x01EE ; Tone a, 220 Hz (-0.01%)
.dw 0x2B21,0x020B ; Tone h, 246,942 Hz (0.01%)
.dw 0x4F1F,0x024B ; Tone c1, 261,626 Hz (0.00%)
.dw 0xE41B,0x0293 ; Tone d1, 293,665 Hz (0.00%)
.dw 0xD918,0x02BA ; Tone e1, 329,628 Hz (0.00%)
.dw 0x7417,0x0310 ; Tone f1, 349,228 Hz (0.00%)
.dw 0xE514,0x0370 ; Tone g1, 391,995 Hz (0.00%)
.dw 0x9D12,0x03DC ; Tone a1, 440 Hz (0.01%)
.dw 0x9510,0x0417 ; Tone h1, 493,883 Hz (0.01%)
.dw 0xA70F,0x0497 ; Tone c2, 523,251 Hz (0.00%)
.dw 0xF20D,0x0527 ; Tone d2, 587,33 Hz (-0.01%)
.dw 0x6C0C,0x0575 ; Tone e2, 659,255 Hz (0.00%)
.dw 0xBA0B,0x0620 ; Tone f2, 698,456 Hz (-0.01%)
.dw 0x720A,0x06E0 ; Tone g2, 783,991 Hz (0.00%)
.dw 0x4E09,0x07B8 ; Tone a2, 880 Hz (0.01%)
.dw 0x4A08,0x082D ; Tone h2, 987,767 Hz (0.01%)
.dw 0xD307,0x092D ; Tone c3, 1046,5 Hz (0.00%)
.dw 0xF806,0x0A4D ; Tone d3, 1174,66 Hz (0.02%)
.dw 0x3606,0x0AEA ; Tone e3, 1318,51 Hz (-0.03%)
.dw 0xDC05,0x0C40 ; Tone f3, 1396,91 Hz (0.02%)
.dw 0x3805,0x0DC0 ; Tone g3, 1567,98 Hz (0.04%)
.dw 0xA704,0x0F6F ; Tone a3, 1760 Hz (-0.04%)
.dw 0x2504,0x105A ; Tone h3, 1975,53 Hz (-0.04%)
.dw 0xE903,0x125B ; Tone c4, 2093 Hz (0.00%)
.dw 0x7C03,0x149A ; Tone d4, 2349,32 Hz (-0.04%)
.dw 0x1A03,0x15D4 ; Tone e4, 2637,02 Hz (0.03%)
.dw 0xEE02,0x1880 ; Tone f4, 2793,83 Hz (-0.05%)
.dw 0x9C02,0x1B80 ; Tone g4, 3135,96 Hz (-0.04%)
.dw 0x5302,0x1EDE ; Tone a4, 3520 Hz (-0.04%)
.dw 0x1202,0x20B4 ; Tone h4, 3951,07 Hz (-0.04%)
.dw 0xF401,0x24B5 ; Tone c5, 4186,01 Hz (0.00%)
.dw 0xBD01,0x2934 ; Tone d5, 4698,65 Hz (0.07%)
.dw 0x8D01,0x2BA7 ; Tone e5, 5274,05 Hz (-0.09%)
.dw 0x7601,0x3100 ; Tone f5, 5587,67 Hz (0.08%)
.dw 0x4D01,0x3700 ; Tone g5, 6271,93 Hz (0.11%)
.dw 0x2901,0x3DBC ; Tone a5, 7040 Hz (-0.04%)
.dw 0x0801,0x4168 ; Tone h5, 7902,13 Hz (0.15%)
.dw 0xF900,0x496B ; Tone c6, 8372,02 Hz (0.20%)
.dw 0xDE00,0x5268 ; Tone d6, 9397,28 Hz (0.07%)
.dw 0xC600,0x574F ; Tone e6, 10548,08 Hz (-0.09%)
.dw 0xBB00,0x6200 ; Tone f6, 11175,3 Hz (-0.18%)
.dw 0xA600,0x6E00 ; Tone g6, 12543,86 Hz (0.11%)
.dw 0x9400,0x7B79 ; Tone a6, 14080 Hz (-0.04%)
.dw 0x8400,0x82D0 ; Tone h6, 15804,26 Hz (-0.23%)
.dw 0x7C00,0x92D5 ; Tone c7, 16744,03 Hz (0.20%)
.dw 0x6F00,0xA4D0 ; Tone d7, 18794,56 Hz (-0.37%)
.dw 0x6200,0xAE9D ; Tone e7, 21096,16 Hz (0.41%)
.dw 0x5D00,0xC3FF ; Tone f7, 22350,59 Hz (-0.18%)
.dw 0x5300, ; Tone g7, 25087,71 Hz (-0.48%)
;
; End of source code
;
; Copyright information
; .db "(C)2019 by Gerhard Schmidt " ; Source code readable
; .db "C(2)10 9ybG reahdrS hcimtd " ; Machine code format
;