Path: Home => AVR-EN => Applications => Circular led => Asm source code clock   Diese Seite in Deutsch: Flag DE Logo
Circular-led

Assembler source code for the circular LED clock with ATmega324PA

The original assembler source code for the circular LED clock in asm format is here.


;
; ********************************
; * Circular clock with 32 LEDs  *
; * for ATmega324PA, version 1.0 *
; * (C)2021 by Gerhard Schmidt   *
; ********************************
;
.nolist
.include "m324padef.inc" ; Define device ATmega324PA
.list
;
; **********************************
;        H A R D W A R E
; **********************************
;
; Device: ATmega324PA, Package: 40-pin-PDIP
;
;            __________
;         1 /          |40
; LED32 o--|PB0     PA0|--o LED1
; LED31 o--|PB1     PA1|--o LED2
; LED30 o--|PB2     PA2|--o LED3
; LED29 o--|PB3     PA3|--o LED4
; LED28 o--|PB4     PA4|--o LED5
; LED27 o--|PB5     PA5|--o LED6
; LED26 o--|PB6     PA6|--o LED7
; LED25 o--|PB7     PA7|--o LED8
; RESET o--|RESET  AREF|--o
;  +3V3 o--|VCC     GND|--o 0 V
;   0 V o--|GND    AVCC|--o
;   XT2 o--|XTAL2   PC7|--o LED9
;   XT1 o--|XTAL1   PC6|--o LED10
; LED24 o--|PD0     PC5|--o LED11
; LED23 o--|PD1     PC4|--o LED12
; LED22 o--|PD2     PC3|--o LED13
; LED21 o--|PD3     PC2|--o LED14
; LED20 o--|PD4     PC1|--o LED15
; LED19 o--|PD5     PC0|--o LED16
; LED18 o--|PD6     PD7|--o LED17
;        20|___________|21
;
; **********************************
;   A D J U S T A B L E   C O N S T
; **********************************
;
; Blink frequency minutes and hours
;   0 = Very fast minutes, Normal hours
;   1 = Fast minutes, Slow hours
;   2 = Normal minutes, very slow hours
;   3 = Slow minutes, blink hours
;   4 = Very slow minutes, hours constantly on
;   5 = Blink minutes, hours constantly on
;   6..7 = Minutes and hours constantly on 
.equ cBlink = 2 ; Set blink frequency
;
; 16-Bit-TC (from calc sheet)
.equ clock = 2097152 ; in Hz
.equ cPresc16 = 8 ; Prescaler 16-Bit-TC
.equ cCtcDiv16 = 15360 ; CTC-Divider 16-Bit-TC
.equ cPrescBits16 = (1<<CS11) ; Prescaler Bits 16-Bit-TC
;
; Start time (from calc sheet)
.equ cStartHour = 0xFFFBFFFF
.equ cStartMinute = 0xFFFFFF7F
.equ cStartRndHour = 15360 ; Counter for rest of the hour
.equ cStartRndMinute = 1920 ; Counter for rest of the minute
;
; Seconds increases (from calc sheet)
.equ cSecDiv = 15 ; Seconds divider
.equ cPresc8 = 1024 ; Prescaler 8-bit-TC
.equ cPrescBits8 = (1<<CS02)|(1<<CS00) ; Prescaler bits
;
; Minutes and hour counters (from calc sheet)
.equ cCntMin = 1920 ; Minute increase count
.equ cCntHr = 23040 ; Hour increase count
;
; **********************************
;       R E G I S T E R S
; **********************************
;
.def rLed0 = R0 ; LED registers
.def rLed1 = R1
.def rLed2 = R2
.def rLed3 = R3
.def rMin0 = R4 ; Minute registers
.def rMin1 = R5
.def rMin2 = R6
.def rMin3 = R7
.def rHr0 = R8 ; Hour registers
.def rHr1 = R9
.def rHr2 = R10
.def rHr3 = R11
; free: R12..R15
.def rmp = R16 ; Multipurpose register
.def rCntRnd = R17 ; Count the 58-ms-rounds
.def rSec = R18 ; Second count
.def rSecDiv = R19 ; Divider for second increase
; free: R20 .. R25
; used: R27:R26 = X for minutes counting
; used: R29:R28 = Y for hours counting
; free: R31:R30 = Z
;
; **********************************
;           S R A M
; **********************************
;
; (No SRAM used)
;;
; **********************************
;      C O D E   S E G M E N T
; **********************************
;
.cseg
.org 000000
;
; ************************************
; R E S E T  &  I N T - V E C T O R S
; ************************************
	rjmp Main ; Reset vector
	nop
	reti ; INT0
	nop
	reti ; INT1
	nop
	reti ; INT2
	nop
	reti ; PCI0
	nop
	reti ; PCI1
	nop
	reti ; PCI2
	nop
	reti ; PCI3
	nop
	reti ; WDT
	nop
	reti ; OC2A
	nop
	reti ; OC2B
	nop
	reti ; OVF2
	nop
	reti ; ICP1
	nop
	jmp Oc1AIsr ; OC1A
	reti ; OC1B
	nop
	reti ; OVF1
	nop
	reti ; OC0A
	nop
	reti ; OC0B
	nop
	jmp Ovf0Isr ; OVF0
	reti ; SPI
	nop
	reti ; URXC0
	nop
	reti ; UDRE0
	nop
	reti ; UTXC0
	nop
	reti ; ACI
	nop
	reti ; ADCC
	nop
	reti ; ERDY
	nop
	reti ; TWI
	nop
	reti ; SPMR
	nop
	reti ; URXC1
	nop
	reti ; UDRE1
	nop
	reti ; UTXC1
;
; **********************************
;  I N T - S E R V I C E   R O U T .
; **********************************
;
; OVF0 advances the seconds
Ovf0Isr:
  dec rSecDiv ; Decrease second divides
  brne Ovf0Isr1 ; Not yet zero
  ldi rSecDiv,cSecDiv ; Restart second divider
  dec rSec ; Decrease second
  brne Ovf0Isr1 ; Not yet zero
  ldi rSec,32 ; Restart seconds
Ovf0Isr1:
  reti
;
Oc1aIsr:
  cp rCntRnd,rSec ; Check round smaller than seconds 
  brcs Oc1aIsr1 ; Do not shift LEDs
  sec ; Rotate LEDs
  ror rLed0
  ror rLed1
  ror rLed2
  rol rLed3
Oc1aIsr1:
  dec rCntRnd ; Down count rouds
  brne Oc1aIsr2 ; Not yet zero, continue
  ldi rCntRnd,32 ; Restart round counter
  ldi rmp,0x7F ; Restart round, start with PC7
  mov rLed0,rmp
  ldi rmp,0xFF ; All other LEDs off
  mov rLed1,rmp
  mov rLed2,rmp
  mov rLed3,rmp
Oc1aIsr2:
  sbiw XL,1 ; Count minute counter down
  brne Oc1aIsr3 ; Minute not over
  ldi XH,High(cCntMin) ; Restart minute counter
  ldi XL,Low(cCntMin)
  sec ; Shift next minute LED
  ror rMin0
  ror rMin1
  ror rMin2
  rol rMin3
  brcs Oc1aIsr3 ; No zero rolled out
  ldi rmp,0x7F ; Zero, restart with PC7 
  and rMin0,rmp
Oc1aIsr3:
  sbiw YL,1 ; Decrease hour counter
  brne Oc1aIsr4 ; Not yet zero, continue
  ldi YH,High(cCntHr) ; Restart hour counter
  ldi YL,Low(cCntHr)
  sec ; Shift next hour LED
  ror rHr0
  ror rHr1
  ror rHr2
  rol rHr3
  brcs Oc1aIsr4 ; No zero rolled out
  ldi rmp,0x7F ; Zero, restart with PC7
  and rHr0,rmp
Oc1aIsr4:
  mov rmp,rLed0 ; Read LEDs for Port C
  sbrc rCntRnd,cBlink ; Check minutes blinking
  and rmp,rMin0 ; Blink minutes
  sbrs rCntRnd,cBlink+2 ; Check hours blinking
  and rmp,rHr0 ; Blink hours
  out PORTC,rmp ; Write LEDs to Port C
  mov rmp,rLed1 ; Read LEDs for Port D
  sbrc rCntRnd,cBlink ; Check minutes blinking
  and rmp,rMin1 ; Blink minutes
  sbrs rCntRnd,cBlink+2 ; Check hours blinking
  and rmp,rHr1 ; Blink hours
  out PORTD,rmp ; Write LEDs to Port D
  mov rmp,rLed2 ; Read LEDs for Port B
  sbrc rCntRnd,cBlink ; Check minutes blinking
  and rmp,rMin2 ; Blink minutes
  sbrs rCntRnd,cBlink+2 ; Check hours blinking
  and rmp,rHr2 ; Blink hours
  out PORTB,rmp ; Write LEDs to Port B
  mov rmp,rLed3 ; Read LEDs for Port A
  sbrc rCntRnd,cBlink+2 ; Check minutes blinking
  and rmp,rMin3 ; Minutes blinking
  sbrs rCntRnd,cBlink+2 ; Check hours blinking
  and rmp,rHr3 ; Hours blinking
  out PORTA,rmp ; Write LEDs to Port A
  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
  ; First LED on PC7 on
  ldi rmp,0x7F ; Init LED
  mov rLed0,rmp
  ldi rmp,0xFF
  mov rLed1,rmp
  mov rLed2,rmp
  mov rLed3,rmp
  ldi rCntRnd,32 ; Round counter to 32
  ; Start time minutes
  ldi rmp,Byte4(cStartMinute)
  mov rMin3,rmp
  ldi rmp,Byte3(cStartMinute)
  mov rMin2,rmp
  ldi rmp,Byte2(cStartMinute)
  mov rMin1,rmp
  ldi rmp,Byte1(cStartMinute)
  mov rMin0,rmp
  ; Start time hours
  ldi rmp,Byte4(cStartHour)
  mov rHr3,rmp
  ldi rmp,Byte3(cStartHour)
  mov rHr2,rmp
  ldi rmp,Byte2(cStartHour)
  mov rHr1,rmp
  ldi rmp,Byte1(cStartHour)
  mov rHr0,rmp
; All ports inactive  
  out PORTC,rmp
  out PORTD,rmp
  out PORTB,rmp
  out PORTA,rmp
  ; All port bits output
  ldi rmp,0xFF
  out DDRC,rmp
  out DDRD,rmp
  out DDRB,rmp
  out DDRA,rmp
  ; Start all counters
  ldi rCntRnd,32
  ldi rSec,32
  ; Start counters 
  ldi XH,High(cStartRndMinute)
  ldi XL,Low(cStartRndMinute)
  ldi YH,High(cStartRndHour)
  ldi YL,Low(cStartRndHour)
  ; Init the 16-bit-timer TC1
  ldi rmp,High(cCtcDiv16-1) ; Set compare A value for CTC
  sts OCR1AH,rmp
  ldi rmp,Low(cCtcDiv16-1)
  sts OCR1AL,rmp
  clr rmp ; CTC mode and prescaler
  sts TCCR1A,rmp
  ldi rmp,cPrescBits16|(1<<WGM12)
  sts TCCR1B,rmp
  ldi rmp,1<<OCIE1A ; Compare A interrupt
  sts TIMSK1,rmp
  ; Init the 8-bit-timer TC0
  ldi rSecDiv,cSecDiv ; Start second divider
  ldi rmp,0 ; Normal mode and prescaler
  out TCCR0A,rmp
  ldi rmp,cPrescBits8
  out TCCR0B,rmp
  ldi rmp,1<<TOIE0 ; Overflow interrupt
  sts TIMSK0,rmp
; Sleep mode and interrupts
  ldi rmp,1<<SE
  out SMCR,rmp
  sei ; Enable interrupts
;
; **********************************
;    P R O G R A M   L O O P
; **********************************
;
Loop:
  sleep ; Go to sleep again
  rjmp loop
;
; End of source code
;
; Copyright information
  .db "(C)2021 by Gerhard Schmidt  " ; Source code readable
  .db "C(2)20 1ybG reahdrS hcimtd  " ; Machine code format
;

To the top of this page

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