AVRA Ver. 1.3.0 mega8.asm Mon May 10 21:54:46 2021 ; ; coolsystem v0.1 ; ; visit https://hackaday.io ; ; filename: mega8.asm ; ; Author wants this file to be public domain, you can use it as you wish ; ; use this command to compile ; avra -l mega8_asm_list.txt mega8.asm ; .LIST ; let us assign handy names to registers .DEF rinterrupt = R2 ; SREG backup, no nested interrupts .DEF rret = R3 ; return value .DEF rkeys = R4 ; small keyboard readout .DEF rcounter = R5 .DEF rkeysspi = R6 ; spi readout .DEF rkeysspi2 = R7 .DEF rspierror = R8 .DEF rspirecv = R9 .DEF rspirecv2 = R10 .DEF rmp = R16 ; register multi-purpose .DEF rarg = R17 .DEF rarg2 = R18 .DEF rarg3 = R19 .DEF rarg4 = R20 .DEF rflags = R21 .DEF rspi = R22 .DEF rspimore = R23 ; assign bitmask for pins .EQU SMALL_KBD_D = 0b00000001 .EQU SMALL_KBD_L = 0b00000010 .EQU SMALL_KBD_C = 0b00000100 .EQU SMALL_KBD_IN = 0b00001000 ; OK, let us put some variables .DSEG .ORG SRAM_START v: ; table with variables D:000060 keysmod: .BYTE 1 D:000061 keys3: .BYTE 1 D:000062 keys2: .BYTE 1 D:000063 keys1: .BYTE 1 D:000064 keys0: .BYTE 1 D:000065 keys_timer1: .BYTE 1 D:000066 keys_timer2: .BYTE 1 D:000067 leds: .BYTE 1 D:000068 leds_timer: .BYTE 1 ; OK, let us put interrupt table here at flash begin .CSEG .ORG $0000 C:000000 c012 rjmp init_routine C:000001 9518 reti C:000002 9518 reti C:000003 9518 reti C:000004 9518 reti C:000005 9518 reti C:000006 9518 reti C:000007 9518 reti C:000008 9518 reti C:000009 c04e rjmp keyboard_timer C:00000a c03b rjmp spi_complete C:00000b 9518 reti C:00000c 9518 reti C:00000d 9518 reti C:00000e 9518 reti C:00000f 9518 reti C:000010 9518 reti C:000011 9518 reti C:000012 9518 reti ; OK, here will be various routines. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; init_routine (reset) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; init_routine: C:000013 ef0f ldi rmp, 0b11111111 ; all pull-up resistors enable C:000014 bb08 out PORTB, rmp C:000015 bb05 out PORTC, rmp C:000016 bb02 out PORTD, rmp C:000017 e50f ldi rmp, LOW(RAMEND) ; Init stack C:000018 bf0d out SPL, rmp C:000019 e004 ldi rmp, HIGH(RAMEND) C:00001a bf0e out SPH, rmp C:00001b ec00 ldi rmp, 0b11000000 ; enable SPI interrupt C:00001c b90d out SPCR, rmp C:00001d e100 ldi rmp, 0b00010000 ; MISO output C:00001e bb07 out DDRB, rmp C:00001f e005 ldi rmp, 5 C:000020 2e80 mov rspierror, rmp C:000021 2766 clr rspi C:000022 2777 clr rspimore C:000023 2444 clr rkeys C:000024 e400 ldi rmp, 0b01000000 C:000025 2e60 mov rkeysspi, rmp C:000026 e100 ldi rmp, 0b00010000 C:000027 2e70 mov rkeysspi2, rmp C:000028 d01d rcall spi_complete ; send padding C:000029 e004 ldi rmp, 0b00000100 ; timer0 clock/256 (see mega8 datasheet on page 72) C:00002a bf03 out TCCR0, rmp C:00002b e001 ldi rmp, 1 << TOIE0 ; timer 8-bit overflow interrupt enable C:00002c bf09 out TIMSK, rmp C:00002d e800 ldi rmp, 1 << SE ; Enable sleep instruction C:00002e bf05 out MCUCR, rmp C:00002f 2755 clr rflags C:000030 9478 sei C:000031 0000 nop C:000032 e007 ldi rmp, SMALL_KBD_C | SMALL_KBD_D | SMALL_KBD_L ; small keyboard pins C:000033 bb01 out DDRD, rmp C:000034 e6c0 ldi YL, LOW(v) C:000035 e0d0 ldi YH, HIGH(v) C:000036 2700 clr rmp C:000037 830c std Y+keys0-v, rmp C:000038 830b std Y+keys1-v, rmp C:000039 830a std Y+keys2-v, rmp C:00003a 8309 std Y+keys3-v, rmp sleep_loop: C:00003b 2f05 mov rmp, rflags C:00003c 7001 andi rmp, 0b00000001 ; check kbd flag C:00003d f011 breq sleep_nokbd C:00003e d01d rcall keyboard_scan C:00003f 7f5e andi rflags, 0b11111110 ; clear kbd flag sleep_nokbd: C:000040 d0fa rcall spi_recv_read C:000041 2355 tst rflags C:000042 f7c1 brne sleep_loop C:000043 9588 sleep C:000044 0000 nop C:000045 cff5 rjmp sleep_loop ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; spi_complete (interrupt) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; spi_complete: C:000046 b62f in rinterrupt, SREG C:000047 930f push rmp C:000048 2366 tst rspi C:000049 f429 brne spi_rspi C:00004a b86f out SPDR, rkeysspi C:00004b 2d06 mov rmp, rkeysspi C:00004c 2c67 mov rkeysspi, rkeysspi2 C:00004d 2e70 mov rkeysspi2, rmp C:00004e c003 rjmp spi_input spi_rspi: C:00004f b96f out SPDR, rspi ; send custom byte C:000050 2f67 mov rspi, rspimore C:000051 2777 clr rspimore spi_input: C:000052 2ca9 mov rspirecv2, rspirecv C:000053 b09f in rspirecv, SPDR C:000054 6058 ori rflags, 0b00001000 ; set spirecv flag ;lds rmp, leds ;inc rmp ;sts leds, rmp C:000055 910f pop rmp C:000056 be2f out SREG, rinterrupt C:000057 9518 reti ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; keyboard_timer (interrupt) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; keyboard_timer: C:000058 b62f in rinterrupt, SREG C:000059 6051 ori rflags, 0b00000001 ; set kbd flag C:00005a be2f out SREG, rinterrupt C:00005b 9518 reti ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; keyboard_scan (it can be used as interrupt) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; keyboard_scan: C:00005c b62f in rinterrupt, SREG C:00005d 930f push rmp C:00005e 931f push rarg C:00005f 932f push rarg2 C:000060 933f push rarg3 C:000061 934f push rarg4 C:000062 923f push rret C:000063 93cf push YL C:000064 93df push YH ; let us scan small keyboard C:000065 b301 in rmp, DDRD C:000066 6007 ori rmp, SMALL_KBD_D | SMALL_KBD_L | SMALL_KBD_C ; outputs C:000067 7f07 andi rmp, ~SMALL_KBD_IN ; input C:000068 bb01 out DDRD, rmp C:000069 b302 in rmp, PORTD C:00006a 7f01 andi rmp, ~(SMALL_KBD_C | SMALL_KBD_L | SMALL_KBD_IN) ; 595 LEDs latch low, clock low C:00006b bb02 out PORTD, rmp C:00006c e011 ldi rarg, SMALL_KBD_D ; load bitmask C:00006d e024 ldi rarg2, SMALL_KBD_C C:00006e e030 ldi rarg3, 0 ; no input pin yet C:00006f e041 ldi rarg4, 0b00000001 C:000070 d068 rcall transfer_be C:000071 b302 in rmp, PORTD C:000072 7f0e andi rmp, ~SMALL_KBD_D ; data low C:000073 bb02 out PORTD, rmp C:000074 d0c6 rcall spi_recv_read C:000075 e008 ldi rmp, 8 C:000076 2e30 mov rret, rmp ; use rret as a counter C:000077 2444 clr rkeys rotate_loop: C:000078 e021 ldi rarg2, SMALL_KBD_D ; pulse data wire high to latch second 595 C:000079 d077 rcall pulse_pin C:00007a e024 ldi rarg2, SMALL_KBD_C ; pulse clock high to shift the pointer one C:00007b d075 rcall pulse_pin C:00007c b300 in rmp, PIND C:00007d 7008 andi rmp, SMALL_KBD_IN C:00007e 9488 clc ; clear carry C:00007f f009 breq rotate_nosec C:000080 9408 sec ; set carry rotate_nosec: C:000081 9447 ror rkeys ; rotate right through carry C:000082 943a dec rret C:000083 f7a1 brne rotate_loop ; rkeys contains fresh readout ; let us process keyboard state C:000084 e6c0 ldi YL, LOW(v) C:000085 e0d0 ldi YH, HIGH(v) ; pointer to variables C:000086 810a ldd rmp, Y+keys2-v ; load with displacement C:000087 2904 or rmp, rkeys C:000088 8309 std Y+keys3-v, rmp C:000089 810b ldd rmp, Y+keys1-v C:00008a 2904 or rmp, rkeys C:00008b 830a std Y+keys2-v, rmp C:00008c 810c ldd rmp, Y+keys0-v C:00008d 2904 or rmp, rkeys C:00008e 830b std Y+keys1-v, rmp C:00008f 824c std Y+keys0-v, rkeys C:000090 e410 ldi rarg, 0b01000000 C:000091 e520 ldi rarg2, 0b01010000 ; spi template C:000092 2d04 mov rmp, rkeys C:000093 700f andi rmp, 0b00001111 C:000094 2b10 or rarg, rmp C:000095 2d04 mov rmp, rkeys ; prepare spi msg C:000096 9506 lsr rmp C:000097 9506 lsr rmp C:000098 9506 lsr rmp C:000099 9506 lsr rmp C:00009a 2b20 or rarg2, rmp C:00009b 2e31 mov rret, rarg ; make parity bit C:00009c 2d03 mov rmp, rret C:00009d 9437 ror rret C:00009e 2503 eor rmp, rret C:00009f 9437 ror rret C:0000a0 2503 eor rmp, rret C:0000a1 9437 ror rret C:0000a2 2503 eor rmp, rret C:0000a3 9437 ror rret C:0000a4 2503 eor rmp, rret C:0000a5 9437 ror rret C:0000a6 2503 eor rmp, rret ; XOR 6 bits C:0000a7 2433 clr rret C:0000a8 9433 inc rret C:0000a9 2503 eor rmp, rret ; flip parity bit C:0000aa fb00 bst rmp, 0 ; bit store T C:0000ab f916 bld rarg, 6 ; bit load from T C:0000ac 2e32 mov rret, rarg2 ; make another parity bit C:0000ad 2d03 mov rmp, rret C:0000ae 9437 ror rret C:0000af 2503 eor rmp, rret C:0000b0 9437 ror rret C:0000b1 2503 eor rmp, rret C:0000b2 9437 ror rret C:0000b3 2503 eor rmp, rret C:0000b4 9437 ror rret C:0000b5 2503 eor rmp, rret C:0000b6 9437 ror rret C:0000b7 2503 eor rmp, rret ; XOR 6 bits C:0000b8 2433 clr rret C:0000b9 9433 inc rret C:0000ba 2503 eor rmp, rret ; flip parity bit C:0000bb fb00 bst rmp, 0 ; bit store T C:0000bc f926 bld rarg2, 6 ; bit load from T C:0000bd 94f8 cli C:0000be 2d06 mov rmp, rkeysspi C:0000bf fb04 bst rmp, 4 C:0000c0 f026 brts keyboard_swap C:0000c1 2e61 mov rkeysspi, rarg C:0000c2 2e72 mov rkeysspi2, rarg2 C:0000c3 9478 sei C:0000c4 c003 rjmp keyboard_reti keyboard_swap: C:0000c5 2e71 mov rkeysspi2, rarg C:0000c6 2e62 mov rkeysspi, rarg2 C:0000c7 9478 sei keyboard_reti: C:0000c8 e024 ldi rarg2, SMALL_KBD_C C:0000c9 e011 ldi rarg , SMALL_KBD_D C:0000ca 814f ldd rarg4, Y+leds-v C:0000cb d066 rcall reverse_byte C:0000cc d00c rcall transfer_be ; output LEDs C:0000cd e022 ldi rarg2, SMALL_KBD_L ; latch LEDs C:0000ce d022 rcall pulse_pin C:0000cf 91df pop YH C:0000d0 91cf pop YL C:0000d1 903f pop rret C:0000d2 914f pop rarg4 C:0000d3 913f pop rarg3 C:0000d4 912f pop rarg2 C:0000d5 911f pop rarg C:0000d6 910f pop rmp C:0000d7 be2f out SREG, rinterrupt C:0000d8 9518 reti ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; transfer_be (feed data to the shift register, MSB first, clock must be already low) ; args: ; rarg - bitmask for shift register MOSI data pin for PORTD ; rarg2 - bitmask for shift clock pin ; rarg3 - bitmask for MISO data pin ; rarg4 - data do be shifted out ; ; returns: ; rret - data received (MSB first) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; transfer_be: C:0000d9 e008 ldi rmp, 8 C:0000da 2e50 mov rcounter, rmp transfer_loop: C:0000db b302 in rmp, PORTD C:0000dc 9510 com rarg C:0000dd 2301 and rmp, rarg C:0000de 9510 com rarg C:0000df 1f44 rol rarg4 ; rotate left through carry C:0000e0 f408 brcc transfer_zero C:0000e1 2b01 or rmp, rarg transfer_zero: C:0000e2 bb02 out PORTD, rmp C:0000e3 0000 nop C:0000e4 0000 nop C:0000e5 0000 nop C:0000e6 0000 nop C:0000e7 0000 nop C:0000e8 0000 nop C:0000e9 0000 nop C:0000ea 0000 nop C:0000eb 0000 nop C:0000ec 0000 nop C:0000ed d003 rcall pulse_pin C:0000ee 945a dec rcounter C:0000ef f759 brne transfer_loop C:0000f0 9508 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; pulse_pin (note: pin must be already low) ; args: ; rarg2 - PORTD pin bitmask ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; pulse_pin: C:0000f1 0000 nop C:0000f2 0000 nop C:0000f3 0000 nop C:0000f4 0000 nop C:0000f5 b302 in rmp, PORTD C:0000f6 2b02 or rmp, rarg2 C:0000f7 bb02 out PORTD, rmp C:0000f8 0000 nop C:0000f9 0000 nop C:0000fa 0000 nop C:0000fb 0000 nop C:0000fc 0000 nop C:0000fd 0000 nop C:0000fe 0000 nop C:0000ff 0000 nop C:000100 0000 nop C:000101 0000 nop C:000102 0000 nop C:000103 0000 nop C:000104 b302 in rmp, PORTD C:000105 9520 com rarg2 C:000106 2302 and rmp, rarg2 C:000107 bb02 out PORTD, rmp C:000108 9520 com rarg2 C:000109 0000 nop C:00010a 0000 nop C:00010b 0000 nop C:00010c 0000 nop C:00010d 9508 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; debug_wait (large delay) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; debug_wait: C:00010e 930f push rmp C:00010f 931f push rarg C:000110 932f push rarg2 C:000111 2711 clr rarg C:000112 2700 clr rmp debug_wait_loop: C:000113 0000 nop C:000114 0000 nop C:000115 0000 nop C:000116 0000 nop C:000117 950a dec rmp C:000118 f7d1 brne debug_wait_loop C:000119 951a dec rarg C:00011a f7c1 brne debug_wait_loop C:00011b 912f pop rarg2 C:00011c 911f pop rarg C:00011d 910f pop rmp C:00011e 9508 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; debug_light ; args: ; rarg4 - LEDs pattern ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; debug_light: C:00011f 931f push rarg C:000120 932f push rarg2 C:000121 e011 ldi rarg, SMALL_KBD_D C:000122 e024 ldi rarg2, SMALL_KBD_C C:000123 e030 ldi rarg3, 0 ; rarg4 is set C:000124 6840 ori rarg4, 0b10000000 C:000125 dfb3 rcall transfer_be C:000126 e022 ldi rarg2, SMALL_KBD_L ; latch LEDs C:000127 dfc9 rcall pulse_pin C:000128 dfe5 rcall debug_wait C:000129 e024 ldi rarg2, SMALL_KBD_C C:00012a 2744 clr rarg4 C:00012b dfad rcall transfer_be C:00012c e022 ldi rarg2, SMALL_KBD_L ; latch LEDs C:00012d dfc3 rcall pulse_pin C:00012e dfdf rcall debug_wait C:00012f 912f pop rarg2 C:000130 911f pop rarg C:000131 9508 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; reverse_byte (from big-endian to low-endian) ; args: ; rarg4 - byte to be reversed ; ret: ; rarg4 - reversed byte ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; reverse_byte: C:000132 923f push rret C:000133 2e34 mov rret, rarg4 C:000134 e008 ldi rmp, 8 reverse_byte_loop: C:000135 9437 ror rret C:000136 1f44 rol rarg4 C:000137 950a dec rmp C:000138 f7e1 brne reverse_byte_loop C:000139 903f pop rret C:00013a 9508 ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; spi_recv_read (call this function more often) ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; spi_recv_read: C:00013b b70f in rmp, SREG C:00013c 930f push rmp C:00013d 94f8 cli C:00013e 2099 tst rspirecv C:00013f f021 breq spi_recv_nothing C:000140 9290 0067 sts leds, rspirecv C:000142 2499 clr rspirecv C:000143 24aa clr rspirecv2 spi_recv_nothing: C:000144 910f pop rmp C:000145 bf0f out SREG, rmp ; sei C:000146 9508 ret Segment usage: Code : 327 words (654 bytes) Data : 9 bytes EEPROM : 0 bytes Assembly completed with no errors.