Pfad: Home => AVR-DE => Anwendungen => Eieruhr RGB m8515 => Assembler-Software   This page in english: Flag EN Logo
RGB-Eieruhr AVR-Anwendungen

Eieruhr RGB mit ATmega8515
Assembler-Quellcode

Assembler-Software für die Eieruhr RGB mit ATmega8515

Der Assembler-Quellcode im asm-Format ist hier verfügbar.

;
; ***********************************
; * 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
;



Lob, Tadel, Fehlermeldungen, Genöle und Geschimpfe oder Spam bitte über das Kommentarformular an mich.

©2019 by http://www.avr-asm-tutorial.net