; ATmega328.102.asm Dec 01, 2021
;basic source file to mak an LED blink at a variable rate with interrupts

; cd ~/Desktop/freddieneil.com/kitsandparts.com/tutorials/ATmega328/102/

; avra ATmega328.102.asm

; avrdude -P usb -p m328p -c avrispv2 -U ATmega328.102.hex
; avrdude -P usb -p m328p -c avrispv2 -U flash:w:ATmega328.102.hex -U eeprom:w:ATmega328.102.eep.hex
; avrdude -P usb -p m328p -c avrispv2 -U lfuse:w:0x62:m  -U hfuse:w:0xD9:m  -U efuse:w:0xFF:m

; define ATmega version
.equ  ATmega = 1   ; Declares the symbol ATmega328
;.equ  ATmega = 2   ; Declares the symbol ATmega644

.nolist

; conditional assembly: .define .undef .if .ifdef .ifndef .else .elif .endif .error .warning .message 
.if    ATmega  ==  1
  .include  "../../include/m328Pdef.inc"
  .message  "m328Pdef.inc selected"
.elif  ATmega  ==  2
  .include  "../../include/m644Adef.inc"
  .message  "m644Adef.inc selected"
.else
  .error  "include file not specified"
.endif

.list

.equ  LED = PORTD0
.equ  delaytime = 250

; Define register names
; r0 is used by Z-registor (sometimes)
.def  temp1 = r16
.def  temp2 = r17
.def  delay = r18
; r24-r31 used as 16 bit register pointers W, X, Y ,Z

.eseg
.org 0

.dseg
.org SRAM_START

.cseg
.org 0
  jmp RESET
  jmp NOT_USED  ; External Interrupt Request 0
  jmp NOT_USED  ; External Interrupt Request 1
  jmp NOT_USED	; Pin Change Interrupt Request 0
  jmp NOT_USED	; Pin Change Interrupt Request 1
  jmp NOT_USED	; Pin Change Interrupt Request 2
  jmp NOT_USED	; Watchdog Time-out Interrupt
  jmp NOT_USED	; Timer/Counter2 Compare Match A
  jmp NOT_USED	; Timer/Counter2 Compare Match A
  jmp NOT_USED	; Timer/Counter2 Overflow
  jmp NOT_USED	; Timer/Counter1 Capture Event
  jmp NOT_USED	; Timer/Counter1 Compare Match A
  jmp NOT_USED	; Timer/Counter1 Compare Match B
  jmp NOT_USED	; Timer/Counter1 Overflow
  jmp NOT_USED	; TimerCounter0 Compare Match A
  jmp NOT_USED	; TimerCounter0 Compare Match B
  jmp  TIM0_OVF_ISR  ; Timer/Counter0 Overflow
  jmp NOT_USED	; SPI Serial Transfer Complete
  jmp NOT_USED	; USART Rx Complete
  jmp NOT_USED	; USART, Data Register Empty
  jmp NOT_USED	; USART Tx Complete
  jmp NOT_USED	; ADC Conversion Complete
  jmp NOT_USED	; EEPROM Ready
  jmp NOT_USED	; ;Analog Comparator
  jmp NOT_USED	; Two-wire Serial Interface
  jmp NOT_USED	; Store Program Memory Read
NOT_USED: 
  reti

RESET:
	ldi		temp1,  low(RAMEND)
	out   SPL,    temp1			    ; Set stack pointer to last internal RAM location
	ldi		temp1,  high(RAMEND)
	out		SPH,    temp1

; set System Clock Prescaler - system default clock is 8.0 MHz - can be changed to 6.4 MHz by Fuse Low Byte
  ldi   temp1,  0b10000000  ; init for prescaler change
  sts   CLKPR,  temp1       ; else out instruction to CLKPR will not take effect
; ldi   temp1,  0b00000000  ; prescaler / 1 - ( 8.0 MHz / 1) = 8.000 MHz = 125 nanoseconds
; ldi   temp1,  0b00000001  ; prescaler / 2 - ( 8.0 MHz / 2) = 4.000 MHz = 250 nanoseconds
; ldi   temp1,  0b00000010  ; prescaler / 4 - ( 8.0 MHz / 4) = 2.000 MHz = 500 nanoseconds
  ldi   temp1,  0b00000011  ; prescaler / 8 - factory default; set by Fuse Low Byte ( 8.0 MHz / 8) = 1.000 MHz = 1.000 microsecond
; ldi   temp1,  0b00000100  ; prescaler / 16 - ( 8.0 MHz / 16) = 500 KHz = 2.000 microseconds
; the setting below disable reprogramming the uP - must use "-B 500" with AVRDUDE to fix
; ldi   temp1,  0b00000101  ; prescaler / 32 - ( 8.0 MHz / 32) = 250 KHz = 4.000 microseconds
; ldi   temp1,  0b00000110  ; prescaler / 64 - ( 8.0 MHz / 64) = 125 KHz = 8.000 microseconds
; ldi   temp1,  0b00000111  ; prescaler / 128 - ( 8.0 MHz / 128) = 62.5 KHz = 16.000 microseconds
; ldi   temp1,  0b00001000  ; prescaler / 256 - ( 8.0 MHz / 256) = 31250 Hz = 32.000 microseconds
  sts   CLKPR,  temp1

; with prescaler set to 8:
; ldi   temp1,  0b00000001  ; no prescaling
  ldi   temp1,  0b00000010  ; CLK 1/8 from prescaler (6.667 uS fo ATtiny13, 8.000 uS for ATtinyx5)
; ldi   temp1,  0b00000011  ; CLK 1/64
; ldi   temp1,  0b00000100  ; CLK 1/256
; ldi   temp1,  0b00000101  ; CLK 1/1024
  out   TCCR0B, temp1	      ; set timer prescaler
  
  ldi   temp1,  1           ; overflow interrupt enable bit
  sts   TIMSK0, temp1       ; enable TIMER0 overflow interrupts
    
  sei   ; global all interrupt enable

;user init
  ldi   temp1,  1
  out   DDRD,   temp1   ;make PD0 pin an output

menu:	  ; main program

  ldi   delay,  delaytime
wait1:
  tst   delay
  brne  wait1
  sbi   PIND,   LED ; toggle LED on/off
  rjmp  menu
  
TIM0_OVF_ISR:
  push  temp1
  push  temp2
  in    temp1,  SREG
  push  temp1
  ldi   temp1,  256-delaytime
  out   TCNT0,  temp1   ;	set for next overflow
  tst   delay
  breq  TIM0_exit
  dec   delay
TIM0_exit:
  pop   temp1
  out   SREG,   temp1
  pop   temp2
  pop   temp1
  reti

