; ATtiny.103.asm
; version 05 Oct 2021
; author: W8DIZ

; Set up the working directory for avra ==> cd ~/Desktop/freddieneil.com/kitsandparts.com/tutorials/ATtiny/103/

; cut and paste the desired ASM CODE to the command line on the LINUX TERMINAL PROGRAM to assemble to your source code.

; Assemble the code ==> avra ATtiny.103.asm

; To enables PB5 and disable External Reset:
; for ATtiny13, clear bit 0 in Fuse High Byte.
; for ATtiny25/45/85, clear bit 7 in Fuse High Byte.
; Must use high voltage programmer like the dragon_hvsp if PB5 enabled

;  avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * avrispv2 * 

; avrdude -P usb -p t13 -c avrispv2 -U ATtiny.103.hex
; avrdude -P usb -p t13 -c avrispv2 -U lfuse:w:0x6A:m -U hfuse:w:0xFF:m
; avrdude -P usb -p t13 -c avrispv2 -U ATtiny.103.hex -U lfuse:w:0x6A:m -U hfuse:w:0xFF:m

; avrdude -P usb -p t45 -c avrispv2 -U ATtiny.103.hex
; avrdude -P usb -p t45 -c avrispv2 -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m
; avrdude -P usb -p t45 -c avrispv2 -U ATtiny.103.hex -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m

; avrdude -P usb -p t85 -c avrispv2 -U ATtiny.103.hex
; avrdude -P usb -p t85 -c avrispv2 -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m
; avrdude -P usb -p t85 -c avrispv2 -U ATtiny.103.hex -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m

; dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp * dragon_hvsp

; avrdude -P usb -p t13 -c dragon_hvsp -U ATtiny.103.hex
; avrdude -P usb -p t13 -c dragon_hvsp -U lfuse:w:0x6A:m -U hfuse:w:0xFF:m
; avrdude -P usb -p t13 -c dragon_hvsp -U ATtiny.103.hex -U lfuse:w:0x6A:m

; avrdude -P usb -p t45 -c dragon_hvsp -U ATtiny.103.hex
; avrdude -P usb -p t45 -c dragon_hvsp -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m
; avrdude -P usb -p t45 -c dragon_hvsp -U ATtiny.103.hex -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m

; avrdude -P usb -p t85 -c dragon_hvsp -U ATtiny.103.hex
; avrdude -P usb -p t85 -c dragon_hvsp -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m
; avrdude -P usb -p t85 -c dragon_hvsp -U ATtiny.103.hex -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m


; define ATtiny version

.equ  ATtiny13  = 0   ; Declares the symbol ATtiny13
.equ  ATtiny25  = 0   ; Declares the symbol ATtiny25
.equ  ATtiny45  = 0   ; Declares the symbol ATtiny45
.equ  ATtiny85  = 1   ; Declares the symbol ATtiny85

.nolist

; conditional assembly: .define .undef .if .ifdef .ifndef .else .elif .endif .error .warning .message 
.if    ATtiny13  ==  1
  .include  "../../include/tn13def.inc"
  .message  "tn13def.inc selected"
.elif  ATtiny25  ==  1
  .include  "../../include/tn25def.inc"
  .message  "tn25def.inc selected"
.elif  ATtiny45  ==  1
  .include  "../../include/tn45def.inc"
  .message  "tn45def.inc selected"
.elif  ATtiny85  ==  1
  .include  "../../include/tn85def.inc"
  .message  "tn85def.inc selected"
.else
  .error  "include file not specified"
.endif

.list

.equ  LED = PB4

; Define register names
; r0 is used by Z-registor

.def  temp1 = r16
.def  temp2 = r17
.def  delay = r24
           
.dseg
.org SRAM_START

.cseg
.org 0

.if ATtiny13  ==  1
  rjmp  RESET         ; Reset Handler
  reti  ; EXT_INT0    ; IRQ0 Handler
  reti  ; PCINT0      ; PCINT0 Handler
  rjmp  TIM0_OVF_ISR  ; Timer0 Overflow
  reti  ; EE_RDY      ; EEPROM Ready Handler
  reti  ; ANA_COMP    ; Analog Comparator Handler
  reti  ; TIM0_COMPA  ; Timer0 CompareA Handler
  reti  ; TIM0_COMPB  ; Timer0 CompareB Handler
  reti  ; WATCHDOG    ; Watchdog Interrupt Handler
  reti  ;	ADC         ; ADC Conversion Handler
.else
  rjmp RESET
  reti                ; External Interrupt 0
  reti                ; Pin change Interrupt Request 0
  reti                ; Timer/Counter1 Compare Match 1A
  reti                ; Timer/Counter1 Overflow
  rjmp  TIM0_OVF_ISR  ; Timer/Counter0 Overflow
  reti                ; EEPROM Ready
  reti                ; Analog comparator
  reti                ; ADC Conversion ready
  reti                ; Timer/Counter1 Compare Match B
  reti                ; Timer/Counter0 Compare Match A
  reti                ; Timer/Counter0 Compare Match B
  reti                ; Watchdog Time-out
  reti                ; USI START
  reti                ; USI Overflow
.endif

RESET:  ; init stack pointer
  ldi   temp1,  low(RAMEND)
  out   SPL,    temp1 ; Set stack pointer to last internal RAM location
.if ATtiny13  ==  1
.elif  ATtiny25  ==  1
.else
  ldi   temp1,high(RAMEND)
  out   SPH,temp1
.endif

;user init
  ldi   temp1,  $10
  out   DDRB,   temp1   ;make PB4 pin an output

.if ATtiny13  ==  1
  ; set System Clock Prescaler - system default clock is 9.6 MHz - can be changed to 4.8 MHz by Fuse Low Byte
    ldi   temp1,  0b10000000  ; init for prescaler change
    out   CLKPR,  temp1       ; init for prescaler change
  ; ldi   temp1,  0b00000000  ; prescaler / 1
  ; ldi   temp1,  0b00000001  ; prescaler / 2
  ; ldi   temp1,  0b00000010  ; prescaler / 4 - ( 9.6 MHz / 4) = 2.400 MHz = 417 nanoseconds
    ldi   temp1,  0b00000011  ; prescaler / 8 - default set by Fuse Low Byte ( 9.6 MHz / 8) = 1.200 MHz = 833 nanoseconds
  ; ldi   temp1,  0b00000100  ; prescaler / 16 - ( 9.6 MHz / 16) = 600 KHz = 1.667 microseconds
  ; the setting below disable reprogramming the uP - must use "-B 500" with AVRDUDE to fix
  ; ldi   temp1,  0b00000101  ; prescaler / 32 - ( 9.6 MHz / 32) = 300 KHz = 3.333 microseconds
  ; ldi   temp1,  0b00000110  ; prescaler / 64 - ( 9.6 MHz / 64) = 150 KHz = 6.667 microseconds
  ; ldi   temp1,  0b00000111  ; prescaler / 128 - ( 9.6 MHz / 128) = 75 KHz = 13.333 microseconds
  ; ldi   temp1,  0b00001000  ; prescaler / 256 - ( 9.6 MHz / 256) = 37500 Hz = 26.667 microseconds
    out   CLKPR,  temp1
.else
  ; 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
    out   CLKPR,  temp1       ; init for prescaler change
  ; ldi   temp1,  0b00000000  ; prescaler / 1
  ; ldi   temp1,  0b00000001  ; prescaler / 2
  ; 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
    out   CLKPR,  temp1
.endif 

; with prescaler set to 8:
; ATtiny13 - set Timer/Counter Prescaler to System Clock Source
; ATtinyx5 - set Timer/Counter Prescaler to System Clock Source
; 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,  0b00000010  ; overflow interrupt enable bit
.if ATtiny13  ==  1
  out   TIMSK0, temp1       ; enable timer/counter0 overflow interrupt
.else    
  out   TIMSK,  temp1       ; enable TIMER0 overflow interrupts
.endif
    
  sei   ; global all interrupt enable

menu:	  ; main program
.if ATtiny13  ==  1
  ldi   delay,  250   ; 250 * 1 mS = 250 mS for ATtiny13
.else
  ldi   delay,  250   ; 250 * 2 mS = 500 mS for ATtinyx5
.endif
wait1:
  tst   delay
  brne  wait1
  sbi   PINB,   LED ; turn LED off
  rjmp  menu
  
TIM0_OVF_ISR:
  push  temp1
  push  temp2
  in    temp1,  SREG
  push  temp1
.if ATtiny13  ==  1
  ldi   temp1,  256-150 ;	1 mS for ATtiny13
.else
  ldi   temp1,  256-250 ;	2 mS for ATtinyx5
.endif
  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
	
