; ATtiny.106.asm - LCD / Si5351A Demo
; version 30 Nov 2021 - final version
; tune a Si5351 clock chip and display data on LCD
; author: W8DIZ

; cut and paste the desired AVRA or AVRDUDE commands to the command line on the LINUX TERMINAL PROGRAM.

; Set up the working directory for avra ==> cd ~/Desktop/freddieneil.com/kitsandparts.com/tutorials/ATtiny/106/

; Assemble the code ==> avra ATtiny.106.asm

; Upload the code ==>  avrdude -P usb -p t85 -c avrispv2 -U ATtiny.106.hex -U eeprom:w:ATtiny.106.eep.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.106.hex -U lfuse:w:0x62:m -U hfuse:w:0xDF:m -U efuse:w:0xFF:m

; 1-Rst--------Vcc-8
; 2-PB3--------PB2-7
; 3-PB4--------PB1-6
; 4-Gnd--------PB0-5

.nolist
.include  "../../include/tn85def.inc"
.list
 
.equ  DDRx      = DDRB
.equ  PINx      = PINB
.equ  PORTx     = PORTB

.equ  PCINTa    = PCINT3
.equ  PCINTb    = PCINT4

.equ  lcd_cp	  =	portb0    ; clock line for 74HC164
.equ  sda_bit   = portb0
.equ  scl_bit   = portb1
.equ  lcd_e	    =	portb2    ; lcd Enable
.equ  tune_bit  = portb3
.equ  lcd_drs   =	portb4    ; data line for 74HC164
.equ  led_bit   = portb4
.equ  LED       = portb4
.equ  not_used  = portb5
.equ  si5351_i2cAddr  = 0xC0  ; si5351A address = 0x60 but needs to shift left 1 bit


; Define register names
; r0 is used by Z-registor
.def  lastPot = r1
.def  temp29  = r2  ; r29_VCOa P1[15:8]
.def  temp30  = r3  ; r30_VCOa P1[7:0]
.def  temp31  = r4  ; r31_VCOa P3[19:16]:P2[19:16]
.def  temp32  = r5  ; r32_VCOa P2[15:8]
.def  temp33  = r6  ; r33_VCOa P2[7:0]
.def  temp34  = r7  ; extra byte for finer inc/dec resolution

.def  step0   = r8  ; high byte add/sub for inc/dec
.def  step1   = r9  ; next byte add/sub for inc/dec
.def  step2   = r10 ; next byte add/sub for inc/dec
.def  step3   = r11 ; next byte add/sub for inc/dec
.def  step4   = r12 ; low byte add/sub for inc/dec

.def  temp1             = r16
.def  temp2             = r17
.def  current_pot_value = r18
.def  last_pot_value    = r19
.def  delay_1ms         = r20
.def  i2cData           = r21
.def  temp3             = r21
.def	si5351_regNum     = r22
.def  temp4             = r22
.def	si5351_regVal     = r23
.def  temp5             = r23
; r24-r31 used as 16 bit register pointers W, X, Y ,Z
            
.dseg
.org SRAM_START
cursor_number_sram: .byte 1

.cseg
.org 0

  rjmp  RESET
  reti  ; EXT_INT0    ; External Interrupt 0
  reti  ; PCINT       ; Pin change Interrupt Request 0
  reti  ; OC1A        ; Timer/Counter1 Compare Match 1A
  reti  ; TIMER1_OVF  ; Timer/Counter1 Overflow
  rjmp  TIMER0_OVF    ; Timer/Counter0 Overflow
  reti  ; EE_RDY      ; EEPROM Ready
  reti  ; ANA_COMP    ; Analog comparator
  reti  ; ADCC        ; ADC Conversion ready
  reti  ; OC1B        ; Timer/Counter1 Compare Match B
  reti  ; OC0A        ; Timer/Counter0 Compare Match A
  reti  ; OC0B        ; Timer/Counter0 Compare Match B
  reti  ; WATCHDOG    ; Watchdog Interrupt Handler
  reti  ; USI_START   ; USI START
  reti  ; USI_OVF     ; USI Overflow

; 100 Hz sets at 7 MHz, A=35, D=100, XTAL=20 MHz
REGS2933_FL: .db $0F,$80,$F0,$00,$00,$00
CR4445FL: .db $00,$30
STEP_FL:  .db $01,$06,$24,$BC,$6A,0

; 100 Hz sets at 7 MHz, A=28, D=100, XTAL=25 MHz
;REGS2933_FL: .db $0C,$00,$F0,$00,$00,$00
;CR4445FL: .db $00,$30
;STEP_FL:  .db $00,$D1,$B6,$E9,$79,0

RESET:  ; init stack pointer
  ldi   temp1,  low(RAMEND)
  out   SPL,    temp1 ; Set stack pointer to last internal RAM location
  ldi   temp1,  high(RAMEND)
  out   SPH,    temp1
  
adc_init:
 ldi temp1,0b00100000 ; use ADC channel 0, left adjusted, vref = Vcc
 out ADMUX, temp1
 ldi temp1, 0b11100111 ;from left to right: ADC Enable, Start Conversion, Free-Running Mode, write zero to ADC Int flag
 out ADCSRA, temp1 ; disable int, prescaler: 111 for XTAL/128

led_init:
  sbi   PORTx,  led_bit   ; set led_bit to turn off LED
  sbi   DDRx,   led_bit   ; set led_bit to enable output for LED control

i2c_init:
	cbi   DDRx,   sda_bit ; make sda_bit an input - release Si5351A sda_bit i2c sda line - float high via pull up resistor
	cbi   DDRx,   scl_bit ; make scl_bit an input - release Si5351A scl_bit i2c scl line - float high via pull up resistor
	cbi   PORTx,  sda_bit ; set sda_bit to logic "0" (when DDRx(sda_bit) changes to an output)
	cbi   PORTx,  scl_bit ; set scl_bit to logic "0" (when DDRx(scl_bit) changes to an output)

; 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       ; else out instruction to CLKPR will not take effect
  ldi   temp1,  0b00000011  ; prescaler / 8 - factory default; set by Fuse Low Byte ( 8.0 MHz / 8) = 1.000 MHz = 1.000 microsecond
  out   CLKPR,  temp1

; with prescaler set to 8:
  ldi   temp1,  0b00000010  ; CLK 1/8 from prescaler (8.000 uS for ATtinyx5)
  out   TCCR0B, temp1	      ; set timer prescaler
  ldi   temp1,  0b00000010  ; overflow interrupt enable bit
  out   TIMSK,  temp1       ; enable TIMER0 overflow interrupts

	sbi		DDRx,lcd_e		; make lcd_e an output
	sbi		DDRx,lcd_drs  ; make lcd_drs an output

	cbi		PORTx,lcd_e		;set lcd_e low
 	cbi		PORTx,lcd_cp	;set lcd_cp low
 	
  ldi ZH, high(2*REGS2933_FL)
  ldi ZL, low(2*REGS2933_FL)
  lpm		temp29,Z+
  lpm		temp30,Z+
  lpm		temp31,Z+
  lpm		temp32,Z+
  lpm		temp33,Z+
  lpm		temp34,Z+ ; temp34 is a dummy for better INC/DEC resolution

  ldi ZH, high(2*STEP_FL)
  ldi ZL, low(2*STEP_FL)
  lpm		step0,Z+
  lpm		step1,Z+
  lpm		step2,Z+
  lpm		step3,Z+
    
  sei   ; global all interrupt enable
  
  rcall Si5351  ; init Si5351 chip to base frequency
  
  rcall lcd_init

main:   ; start of main program

  ldi ZH,high(2*MSG_1)
  ldi ZL,low(2*MSG_1)
  ldi temp2,$80				;display on line 1
  rcall LCDCMD
  rcall DISPLAY_LINE
  
  ;ldi   delay_1ms,  25  ; 25 mS
  ;rcall WAIT
  
  ldi   last_pot_value, $00 ; init last_pot_value
 
main20:
  rcall read_potentiometer
main21:
  cp    current_pot_value,  last_pot_value
  breq  main20
main22:
  brlo  DN_STEP
  rcall STEP_UP
  inc   last_pot_value
  rjmp  TEST_UPDATE
DN_STEP:
  rcall STEP_DN
  dec   last_pot_value
TEST_UPDATE:
  cp    current_pot_value,  last_pot_value
  brne  main22
  rcall UPDATE_2930313233
  rcall	SHOW_POT_HEX_BYTE  ; display current_pot_value at beginning of line 2
  rcall	SHOW_POT_DEC_BYTE  ; display current_pot_value at middle of line 2

  rjmp main21

read_potentiometer:
  push  temp1
  ldi   temp1,      0b00100011 ; select ADC 03 = Tunning
  out   ADMUX,      temp1 ; AVcc, left adjust( we need just ADCH only), ADC0
  pop   temp1
  sbi   ADCSRA,     ADSC  ; start ADC conversion
keep_pooling:
  sbis  ADCSRA,     ADIF  ; look for ADC conversion finish flag ADIF
  rjmp  keep_pooling
  sbi   ADCSRA,     ADIF   
  in    current_pot_value,  ADCH  ; get pot value = 0 to $FF
  ;lsr   current_pot_value ; current_pot_value = 0 to $7F
  ;lsr   current_pot_value ; current_pot_value = 0 to $3F
  ;lsr   current_pot_value ; current_pot_value = 0 to $1F
  ;lsr   current_pot_value ; current_pot_value = 0 to $0F
  ;lsr   current_pot_value ; current_pot_value = 0 to $07
  ret
  
STEP_UP:
  clr   temp1
  add   temp34, step3
  adc   temp33, step2
  adc   temp32, step1
  adc   temp31, step0
  adc   temp30, temp1
  adc   temp29, temp1
  ldi   temp1,  $F0
  or    temp31, temp1
  ret

STEP_DN:
  clr   temp1
  ldi   temp1,  $0F
  and   temp31, temp1
  clr   temp1
  sub   temp34, step3
  sbc   temp33, step2
  sbc   temp32, step1
  sbc   temp31, step0
  sbc   temp30, temp1
  sbc   temp29, temp1
  ldi   temp1,  $F0
  or    temp31, temp1
  ret

Si5351:  ; demo freq set for 7.000 MHz
  ldi si5351_regNum, 3
  ldi si5351_regVal, 0xFF
  rcall i2cSend   ; disable all outputs

  ldi   si5351_regNum, 16
  ldi   si5351_regVal, 0x80
  rcall i2cSend   ; power down clock0

  ldi   si5351_regNum, 17
  ldi   si5351_regVal, 0x80
  rcall i2cSend   ; power down clock1

  ldi   si5351_regNum, 18
  ldi   si5351_regVal, 0x80
  rcall i2cSend   ; power down clock2

  ;ldi   si5351_regNum, 15
  ;ldi   si5351_regVal, 0x00   ; default is 0x00  
  ;rcall i2cSend   ; select PLLa,b source and use xtal input

  ;ldi   si5351_regNum, 24
  ;ldi   si5351_regVal, 0x00   ; default is 0x00  
  ;rcall i2cSend   ; clock disable state

  ldi si5351_regNum, 149
  ldi si5351_regVal, 0    ; disable spread spectrum on PLLa
  rcall i2cSend   ; reset both PLLs
  
; Output Multisynth0, e=0, f=1, MS0_P2 and MS0_P3
  ldi   si5351_regNum, 42
  ldi   si5351_regVal, 0
  rcall i2cSend   ; set MS0_P3[15:8]

  ldi   si5351_regNum, 43
  ldi   si5351_regVal, 1
  rcall i2cSend   ; set MS0_P3[7:0]
  
  ldi   si5351_regNum, 47
  ldi   si5351_regVal, 0
  rcall i2cSend   ; set MS0_P3[19:16] | MS0_P2[19:16]

  ldi   si5351_regNum, 48
  ldi   si5351_regVal, 0
  rcall i2cSend   ; set MS0_P2[15:8]

  ldi   si5351_regNum, 49
  ldi   si5351_regVal, 0
  rcall i2cSend   ; set MS0_P2:[7:0]
  
  ldi   si5351_regNum, 16
  ;ldi   si5351_regVal, 0x4C ; 2 mA - 144 ohms output Z (default)
  ;ldi   si5351_regVal, 0x4D ; 4 mA - 61 ohms output Z
  ;ldi   si5351_regVal, 0x4E ; 6 mA - 56 ohms output Z
  ldi   si5351_regVal, 0x4F ; 8 mA - 44 ohms output Z
  rcall i2cSend   ; power up clock0, MS0 in integer mode,  PLLa at 8 mA

  ;ldi si5351_regNum, 183
  ;ldi si5351_regVal, 0x52 ;$D2=default 10pF, $92=8pF, $52=6pF
  ;rcall i2cSend   ; reset both PLLs

  ldi si5351_regNum, 177
  ldi si5351_regVal, 0xA0
  rcall i2cSend   ; reset both PLLs
  
  ldi si5351_regNum, 3
  ldi si5351_regVal, 0xFE
  rcall i2cSend   ; enable clock0 output only 
  
; Load PLLa Feedback Multisynth 26,27,28

  ldi   si5351_regNum,  26
  ldi   si5351_regVal,  0xff
  rcall i2cSend   ; set MSNA_P3[15:8]

  ldi   si5351_regNum,  27
  ldi   si5351_regVal,  0xff
  rcall i2cSend   ; set MSNA_P3[7:0]

  ldi   si5351_regNum,  28
  ldi   si5351_regVal,  0
  rcall i2cSend   ; set MSNA_P1[17:16]
  
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
  rcall UPDATE_2930313233
   
; Load Output Multysynth with d (e and f already set during init and never changes) 44,45,46

  ldi ZH, high(2*CR4445FL)
  ldi ZL, low(2*CR4445FL)

  ldi   si5351_regNum,  44
  lpm		si5351_regVal,  Z+
  rcall i2cSend   ; set MS0_P1[17:16]

  ldi   si5351_regNum,  45
  lpm		si5351_regVal,  Z+
  rcall i2cSend   ; set MS0_P1[15:8]  
 

  ;ldi   si5351_regNum,  44
  ;ldi   si5351_regVal,  0
  ;rcall i2cSend   ; set MS0_P1[17:16]

  ;ldi   si5351_regNum,  45
  ;ldi   si5351_regVal,  0x30
  ;rcall i2cSend   ; set MS0_P1[15:8]

  ldi   si5351_regNum,  46
  ldi   si5351_regVal,  0
  rcall i2cSend   ; set MS0_P1[7:0]

  ldi si5351_regNum, 177
  ldi si5351_regVal, 0x20
  rcall i2cSend   ; reset PLLa only
  ret
  
UPDATE_2930313233: ; Load PLLa Feedback Multisynth 29,30,31,32,33
  ldi   si5351_regNum,  29
  mov   si5351_regVal,  temp29
  rcall i2cSend   ; set MSNA_P1[15:8]
  
  ldi   si5351_regNum,  30
  mov   si5351_regVal,  temp30
  rcall i2cSend   ; set MSNA_P1[7:0]
  
  ldi   si5351_regNum,  31
  mov   si5351_regVal,  temp31
  rcall i2cSend   ; set MSNA_P3[19:16] | MSNA_P2[19:16]
  
  ldi   si5351_regNum,  32
  mov   si5351_regVal,  temp32
  rcall i2cSend   ; set MSNA_P2[15:8]
  
  ldi   si5351_regNum,  33
  mov   si5351_regVal,  temp33
  rcall i2cSend   ; set MSNA_P2[7:0]
  ret
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
 
i2cSend:  ; (uses si5351_regNum, si5351_regVal)
	rcall	i2c_start				  ; Send start condition and address
	MOV		i2cdata,  si5351_regNum	; Write word address (0x00)
	rcall	i2c_write_8bits 	  ; Execute transfer
	MOV		i2cdata,  si5351_regVal	; Set write data to 01010101b
	rcall	i2c_write_8bits 	  ; Execute transfer
	rcall	i2c_stop				  ; Send stop condition
	ret

i2c_start:
  ldi   i2cdata,  si5351_i2cAddr     ; load i2c device address to transmit register
  sbi   DDRx,     sda_bit   ; force data line low
  rcall i2cDelay_6
  sbi   DDRx,     scl_bit   ; force clock line low
  rcall i2cDelay_6
i2c_write_8bits:
  sec                       ; set carry flag
  rol   i2cdata             ; shift in carry bit and out bit into carry bit
i2c_write_bit:
  breq  i2c_get_ack
  brcc  i2c_bit_write_low
clock_it_high:
  cbi   DDRx,   sda_bit     ; release sda_bit - float sda high
  rjmp  clock_it
i2c_bit_write_low:
  sbi   DDRx,   sda_bit     ; force sda line low
clock_it:
  rcall i2cDelay_6
  cbi   DDRx,   scl_bit     ; release scl_bit - float scl high
  rcall i2cDelay_6
  sbi   DDRx,   scl_bit     ; force scl_bit low
  rcall i2cDelay_6
next_i2c_byte:
  lsl i2cdata
  rjmp  i2c_write_bit
  
i2c_get_ack:
  cbi   DDRx,   sda_bit     ; release sda_bit - float sda high
  rcall i2cDelay_6
  cbi   DDRx,   scl_bit     ; release scl_bit - float scl high
  rcall i2cDelay_6
i2c_get_ack_wait:
  sbis  PINx,   scl_bit     ; wait sda_bit high
  rjmp  i2c_get_ack_wait
  sbi   DDRx,   sda_bit     ; force sda_bit low
  rcall i2cDelay_6
  sbi   DDRx,   scl_bit     ; force scl_bit low
  rcall i2cDelay_6
  clc                       ; clear carry flag
  sbic  PINx,   sda_bit     ; if sda_bit is high
  sec                       ; set carry flag
  rcall i2cDelay_6
  ret  

i2c_stop:
  sbi   DDRx,   scl_bit     ; force scl_bit low
  sbi   DDRx,   sda_bit     ; force sda_bit low
  rcall i2cDelay_6
  cbi   DDRx,   scl_bit     ; release scl_bit
  rcall i2cDelay_6
  cbi   DDRx,   sda_bit     ; release sda_bit
  rcall i2cDelay_6
  ret
  
i2cDelay_6: ; 6 clock cycles or 6 uSeconds
; rcall instruction takes 2 clock cycles
; ret instruction takes 4 clock cycles
  ret

; Data transfer is initiated with a start condition (S) signaled by sda_bit being pulled low while SCL stays high.

;************************************
lcd_init:
;* uses temp2 to send LCD Command
;************************************
	ldi		delay_1ms,20	;wait 20 milliseconds for LCD to stabilize
	rcall	WAIT

	ldi		temp2,$38			;set for 8 bits, 2 lines, default font
	rcall LCDCMD
	ldi		delay_1ms,2		;wait 2 millisecond
  rcall	WAIT

	ldi		temp2,$0E			;Display on, CURSOR on, blink off
	rcall LCDCMD
	ldi		delay_1ms,2		;wait 2 millisecond
  rcall	WAIT

	ldi		temp2,$01			;Clear screen, CURSOR home
	rcall LCDCMD
	ldi		delay_1ms,2		;wait 2 millisecond
  rcall	WAIT
  
	ret

;************************************
;* LCDCMD - Send a command to the LCD
;* temp2 = cmd
;*****************************************
;* LCDCHR - Display a character on the LCD
;* temp1 = data
;************************************
LCDCMD:
  push temp1
  mov temp1,temp2
	rcall	SENDBYTE
	cbi		PORTx,lcd_drs			;set RS low
	rjmp	LCDEXEC
LCDCHR:
  push temp1
	rcall	SENDBYTE
	sbi		PORTx,lcd_drs			;set RS High
LCDEXEC:
	sbi		PORTx,lcd_e				;E clocks on rising edge
	ldi		delay_1ms,2				;wait 2 milliseconds
	cbi		PORTx,lcd_e				;set E low
	rcall	WAIT
	pop temp1
	ret

;**********************************
;* SENDBYTE clock byte into 74hc164
;* temp1 = data
;* temp2 = bitcounter
;***********************************
SENDBYTE:
  push temp1
	push	temp2
	ldi		temp2,8					;bit counter
ShiftBits:
	cbi		PORTx,lcd_drs   ;set LCD Data bit to 0
	lsl		temp1						;shift bits in AReg into carry
	brcc	ClockBit				;if zero, clock it out
	sbi		PORTx,lcd_drs   ;if 1, set LCD Data bit to 1
ClockBit: 
	sbi		DDRx,lcd_cp		  ;bit clocks on rising edge
	cbi		DDRx,lcd_cp		  ;bring clock back to 0
	dec		temp2						;shift out 8 bits
	brne	ShiftBits
	pop		temp2
	pop temp1
	ret

DISPLAY_LINE:
	lpm		temp1,Z+
	tst		temp1
	breq	DISPLAY_LINE_FINIS
	rcall	LCDCHR
	rjmp	DISPLAY_LINE
DISPLAY_LINE_FINIS:
 ldi XH,high(cursor_number_sram)
 ldi XL,low(cursor_number_sram)
 ld temp2,X
 cpi temp2,4
 brlo cursor9
 inc temp2
 cpi temp2,8
 brlo cursor9
 inc temp2
cursor9:
 ldi temp1,$8B
 sub temp1,temp2
 mov temp2,temp1
 rcall LCDCMD
 ret

SHOW_POT_HEX_BYTE: ; display temp1 as two (2) hex chars
  ldi   temp2,  $C0   ; set display to beginning of line 2
  rcall LCDCMD
  mov   temp1,  current_pot_value
	push	temp1
	swap	temp1
	rcall SHOW_NIBBLE ; process upper nibble
	pop		temp1
	rcall SHOW_NIBBLE ; process lower nibble
	ret
SHOW_NIBBLE: ; display lower 4 bits in temp1 as hex char
  push	temp2
	andi	temp1,  $0F
	ori		temp1,  $30
	cpi		temp1,  $3A
	brlo	SHOW_NIBBLE2
	ldi   temp2,  $07
	add 	temp1,  temp2
SHOW_NIBBLE2:
	rcall	LCDCHR  ; display temp1
	pop   temp2
	ret

SHOW_POT_DEC_BYTE: ; display temp1 as two (3) decimal chars 000-255
  ldi   temp2,  $C6   ; set display to middle of line 2
  rcall LCDCMD
  ldi   temp1,  '7'
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  '0'
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  $30
  mov   temp2,  current_pot_value
SHOW_POT_DEC_BYTE2:
  inc   temp1
  subi  temp2,  $64
  brcc  SHOW_POT_DEC_BYTE2
  subi  temp2,  $9C
  dec   temp1
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  $30
SHOW_POT_DEC_BYTE3:
  inc   temp1
  subi  temp2,  $0A
  brcc  SHOW_POT_DEC_BYTE3
  subi  temp2,  $F6
  dec   temp1
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  '.'
  rcall	LCDCHR  ; display temp1
  mov   temp1,  temp2
  subi  temp1,  $D0
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  ' '
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  'K'
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  'H'
  rcall	LCDCHR  ; display temp1
  ldi   temp1,  'z'
  rcall	LCDCHR  ; display temp1
  ret
	
;************************************
;* WAIT
;* temp1 = WAIT time in milliseconds
;************************************
WAIT:
	tst		delay_1ms
	brne	WAIT
	ret
	
TIMER0_OVF:
; with System Clock Prescaler set to /8
; and Timer/Counter Prescaler set to /8
; and TCNT0 loaded with 125 (see below)
  push  temp1
  push  temp2
  in    temp1,  SREG
  push  temp1
  ldi   temp1,  256-125 ;	1 mS for ATtinyx5 - 8.000 uS per count
  out   TCNT0,  temp1   ;	set for next overflow
  tst   delay_1ms
  breq  TIM0_exit
  dec   delay_1ms
TIM0_exit:
  pop   temp1
  out   SREG,   temp1
  pop   temp2
  pop   temp1
  reti

:
  push temp1
  in temp1, SREG
  sbi PINx, led_bit ; turn LED on/off - toggle
  out SREG, temp1
  pop temp1
  reti 

MSG_1:
;    1234567890123456789012345678901234567890
.db "  ASM Tutorial  ",0,0
MSG_2:
;    1234567890123456789012345678901234567890
.db "     Ready!     ",0,0
MSG_3:
;    1234567890123456789012345678901234567890
.db "       OK!      ",0,0
