--- a/Makefile Mon Jun 02 18:27:08 2014 +0300
+++ b/Makefile Sat Jun 07 13:05:33 2014 +0300
@@ -40,21 +40,10 @@
AS = avra
ASFLAGS =
-matrix.hex: spi.inc matrix.inc timer.inc delay.inc macros.inc font.inc font.def
-led7seg.hex: spi.inc led7seg.inc adc.inc timer.inc delay.inc macros.inc
-timer.hex: timer.inc macros.inc
-
%.hex: %.s
$(AS) $(ASFLAGS) $<
mv $<.hex $@
-# fonts
-font.inc: font.def
-
-font.def: font.txt font-compile.py
- python font-compile.py $< $@ > /dev/null
-
-
## Flashing
# Arduino Duemilanove
AD_PART = m328p
--- a/adc.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-;;
-;; Basic ADC operation
-;;
-
-; Reference select
-.set ADC_REF = 0b01 ; AVcc
-
-; Bit adjustment
-.set ADC_LAR = 1 ; Left-adjust
-
-; Input select
-.set ADC_MUX = 0b000 ; ADC0
-
-; Auto-trigger source
-.set ADC_ATS = 0b011 ; TC0 OCA
-
-; Auto-trigger enable
-.set ADC_ATE = 1
-
-; Prescaler
-.set ADC_PS = 0b111 ; 1/128
-
-; I/O pins
-.equ ADC_DDR = DDRC
-.equ ADC_PORT = PORTC
-.equ ADC_PIN = PORTC0
-
-;; Initialize the ADC for starting conversions
-ADC_Init:
- ; ADMUX
- ldi r16, (ADC_REF << REFS0) | (ADC_LAR << ADLAR) | (ADC_MUX << MUX0)
- sts ADMUX, r16
-
- ; ADCSRB
- ldi r16, (ADC_ATS << ADTS0)
- sts ADCSRB, r16
-
- ; ADCSRA
- ; ADSC: No need if using external auto-trigger ???
- ; Enable interrupt
- ldi r16, (1 << ADEN) | (1 << ADSC) | (ADC_ATE << ADATE) | (1 << ADIE) | (ADC_PS << ADPS0)
- sts ADCSRA, r16
-
- ; Disable digital circuit for pin
- ldi r16, (1 << ADC_PIN)
- sts DIDR0, r16
-
- ; Done
- ret
-
-;; Interrupt handler stub for ADC_HANDLER
-ADC_Interrupt:
- in r0, SREG
-
- rcall ADC_HANDLER
-
- out SREG, r0
- reti
-
-;; Read the current 8-bit ADC sample
-; Returns value in r16
-ADC_Read8:
- ; Copy
- lds r16, ADCH
-
- ; Done
- ret
-
--- a/console.s Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,270 +0,0 @@
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-.include "macros.inc"
-
-;; Load a 16-bit *word* address into the given register a a byte address
-.macro loadp_16_i
- ldi @0, high(2 * @2)
- ldi @1, low(2 * @2)
-.endm
-
-.macro load_16_i
- ldi @0, high(@2)
- ldi @1, low(@2)
-.endm
-
-;; Data
-.dseg
-buffer: .byte 0
-
-;; Interrupt Vector
-.cseg
-.org 0x0000
- rjmp Main
-
-;; Libraries
-.include "div.inc" ; Division routines
-
-;; Serial
-.set SERIAL_BAUD = 103 ; 9.6k @ 16Mhz
-
-;; Initialize the UART for
-Serial_Init:
- ; Set up control registers
- ; Single-speed
- poke [UCSR0A, r16, (0 << U2X0)]
-
- ; Async
- ; n parity
- ; 1 stop
- ; 8 bits
- poke [UCSR0C, r16, (0b00 << UMSEL00) | (0b00 << UPM00) | (0 << USBS0) | (0b11 << UCSZ00)]
-
- ; Baud rate
- poke [UBRR0L, r16:r17, SERIAL_BAUD]
-
- ; Enable RX
- ; Enable TX
- ; 8 bits
- poke [UCSR0B, r16, (1 << RXEN0) | (1 << TXEN0) | (0 << UCSZ02)]
-
- ; Done
- ret
-
-;; Send a single byte on serial port
-; Input byte in r16
-Serial_Send:
- ; Wait for idle
- lds r0, UCSR0A
- sbrs r0, UDRE0
- rjmp Serial_Send
-
- ; Copy byte to buffer
- sts UDR0, r16
-
- ; Done
- ret
-
-;; Read a single byte from serial port
-; Output byte in r16
-Serial_Recv:
- ; Wait for recv
- lds r0, UCSR0A
- sbrs r0, RXC0
- rjmp Serial_Recv
-
- ; Copy byte from buffer
- lds r16, UDR0
-
- ; Done
- ret
-
-;; Write nul-terminated string from program mem to serial port
-; Input string in Z
-Serial_pprint:
- ; Load byte to r16
- lpm r16, Z+
-
- ; Quit if nul
- tst r16
- breq _serial_pprint_end
-
- ; Write it
- rcall Serial_Send
-
- ; Continue
- rjmp Serial_pprint
-
-_serial_pprint_end:
- ret
-
-;; Write nul-terminated string from sram and \r\n to serial port
-; Input string in Z
-Serial_sprintln:
- ; Load byte to r16
- ld r16, Z+
-
- ; Quit if nul
- tst r16
- breq _serial_sprintln_end
-
- ; Write it
- rcall Serial_Send
-
- ; Continue
- rjmp Serial_sprintln
-
-_serial_sprintln_end:
- ; \r\n
- ldi r16, 13
- rcall Serial_Send
- ldi r16, 10
- rcall Serial_Send
-
- ; Done
- ret
-
-;; Write char to serial port
-; Input byte in r16
-Serial_bprint:
- ; ASCII offset for '0'
- ldi r17, 48
- mov r4, r17
-
- ; Convert
- ldi r17, 100
- call div8u
- add r16, r4
- rcall Serial_Send
- mov r16, r15
-
- ldi r17, 10
- call div8u
- add r16, r4
- rcall Serial_Send
- mov r16, r15
-
- add r16, r4
- rcall Serial_Send
-
- ret
-
-;; Program
-message: .db "Hello World", 13, 10, 0
-
-Main:
-; Initialization
- ; Stack
- poke [SPL, r16:r17, RAMEND]
-
- ; Enable interrupts
- sei
-
- ; Init
- rcall Serial_Init
-
-; Main program
- ldi ZH, high(message * 2)
- ldi ZL, low(message * 2)
-
- rcall Serial_pprint
-
-; Echo out
- sbi DDRB, PORTB5
- ldi r20, 0
- ldi r21, 0
- ldi r22, 0
-
- ; pointer to memory buffer
- ldi XH, high(buffer)
- ldi XL, low(buffer)
-
- st X, r22 ; '\0'
-
-Main_Echo:
- ; blink LED
- out PORTB, r20
-
- ; read
- rcall Serial_Recv
- push r16
-
- ; display
- rcall Serial_bprint
- ldi r16, 32
- rcall Serial_Send
-
- pop r16
-
- ; test for control chars
- cpi r16, 127 ; DEL
- breq backspace
-
- cpi r16, 13 ; '\r'
- breq cr
-
- cpi r16, 10 ; '\n'
- breq Main_Echo ; ignore
-
- rjmp char ; buffer char
-
-; Erase last char
-backspace:
- ; ignore if already at zero
- cpi XL, low(buffer)
- ldi r23, high(buffer)
- cpc XH, r23
- breq echo
-
- ; use pre-decrement to store nul
- st -X, r22 ; '\0'
-
- rjmp echo
-
-; Erase line
-cr:
- ; seek to start
- ldi XH, high(buffer)
- ldi XL, low(buffer)
-
- ; store nul
- st X, r22 ; '\0'
-
- rjmp echo
-
-char:
- ; buffer char
- st X+, r16
- st X, r22 ; '\0'
-
-echo:
- ; running counter
- inc r21
- mov r16, r21
- rcall Serial_bprint
-
- ; ' '
- ldi r16, 32
- rcall Serial_Send
-
- ; length
- mov r16, XL
- rcall Serial_bprint
-
- ; ' '
- ldi r16, 32
- rcall Serial_Send
-
- ; output buffer
- ldi ZH, high(buffer)
- ldi ZL, low(buffer)
- rcall Serial_sprintln
-
- ; toggle
- com r20
-
- ; continue
- rjmp Main_Echo
-
--- a/delay.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,37 +0,0 @@
-;; vim: set ft=avr:
-;;
-;; Busy-loop delays
-;;
-
-;; Delay for approx. one second
-Delay_1s:
- ; ~16M cycles
- ldi r20, 82
- rjmp delay_init
-
-;; Delay for a variable amount of time, adjusted by r20
-; Input: r20 controls number of delay loops
-VarDelay:
- tst r20
- breq delay_out
-
-delay_init:
- ldi r21, 255
-
-delay_loop:
- ; 254 * (1 + 2) + 1 * (1 + 1) = 764 cycles / loop
- dec r22
- brne delay_loop
-
- ; 254 * 764 + 764 = 194820 cycles / loop
- dec r21 ; 1 * r20 * r21
- brne delay_loop ; 2 * r20 * r21
-
- ; r20 * 194820 + r20 * 3 = 194823 cycles / loop (r20)
- dec r20 ; 1 * r20
- brne delay_loop ; 2 * r20
-
-delay_out:
- ret
-
-
--- a/dip.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,17 +0,0 @@
-;;
-;; Reading DIP switches from SPI
-;;
-
-.set DIP_BUFFER = spi_inbuf + 1
-
-;; Read state of dip switches
-;; Output: r16
-DIP_Read8:
- ; update
-; rcall SPI_SendRecv
-
- ; get bits
- lds r16, DIP_BUFFER
-
- ret
-
--- a/div.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,41 +0,0 @@
-;***************************************************************************
-;*
-;* "div8u" - 8/8 Bit Unsigned Division
-;*
-;* This subroutine divides the two register variables "dd8u" (dividend) and
-;* "dv8u" (divisor). The result is placed in "dres8u" and the remainder in
-;* "drem8u".
-;*
-;* Number of words :14
-;* Number of cycles :97
-;* Low registers used :1 (drem8u)
-;* High registers used :3 (dres8u/dd8u,dv8u,dcnt8u)
-;*
-;***************************************************************************
-
-;***** Subroutine Register Variables
-
-.def drem8u =r15 ;remainder
-.def dres8u =r16 ;result
-.def dd8u =r16 ;dividend
-.def dv8u =r17 ;divisor
-.def dcnt8u =r18 ;loop counter
-
-;***** Code
-
-div8u: sub drem8u,drem8u ;clear remainder and carry
- ldi dcnt8u,9 ;init loop counter
-d8u_1: rol dd8u ;shift left dividend
- dec dcnt8u ;decrement counter
- brne d8u_2 ;if done
- ret ; return
-d8u_2: rol drem8u ;shift dividend into remainder
- sub drem8u,dv8u ;remainder = remainder - divisor
- brcc d8u_3 ;if result negative
- add drem8u,dv8u ; restore remainder
- clc ; clear carry to be shifted into result
- rjmp d8u_1 ;else
-d8u_3: sec ; set carry to be shifted into result
- rjmp d8u_1
-
-
--- a/dmx.s Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,264 +0,0 @@
-;;; vim: set ft=avr:
-
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-.include "macros.inc"
-
-;; Interrupt Vector
-.cseg
-.org 0x0000
- rjmp Main
-
-
-;; CPU cycles / second: 16 Mhz
-.set CPU_CYCLES = 16 * 1000 * 1000
-
-;; Delays
-.include "delay.inc"
-
-;; DMX baud raite: 250k
-.set DMX_BAUD = 250 * 1000
-
-;; CPU cycles / bit: 64
-.set DMX_CYCLES = CPU_CYCLES / DMX_BAUD
-
-;; DMX output I/O
-.set DMX_DDR = DDRB
-.set DMX_PORT = PORTB
-.equ DMX_DATA = PORTB3
-
-;; DMX protocol timer
-; Registers
-.set DMX_TIMER_CRA = TCCR2A
-.set DMX_TIMER_CRB = TCCR2B
-.set DMX_TIMER_CNT = TCNT2
-.set DMX_TIMER_OCRA = OCR2A
-.set DMX_TIMER_OCRB = OCR2B
-.set DMX_TIMER_IMSK = TIMSK2
-.set DMX_TIMER_IFR = TIFR2
-
-; Compare output match isn't used
-.set DMX_TIMER_COMA = 0b00
-.set DMX_TIMER_COMB = 0b00
-
-; Control register, generation mode value
-.set DMX_TIMER_WGM_10 = 0b10 ; CTC
-.set DMX_TIMER_WGM_2 = 0b0
-
-; Clock select
-.set DMX_TIMER_CS_STOP = 0b000
-.set DMX_TIMER_CS = 0b001 ; 1/1
-;.set DMX_TIMER_CS = 0b111 ; 1/1024
-
-; Counted value
-.set DMX_TIMER_TOP = DMX_CYCLES ; number of cycles for baud
-
-;; Debug LED
-.set LED_DDR = DDRB
-.set LED_PORT = PORTB
-.set LED_PIN = PINB
-.set LED_BIT = PORTB0
-
-;; Set up DMX output
-DMX_Init:
- ; Setup output port
- ; out
- sbi DMX_DDR, DMX_DATA
-
- ; drive high
- sbi DMX_PORT, DMX_DATA
-
- ; Setup timer
- ; setup CTC mode with no output pins
- poke [DMX_TIMER_CRA, r16, (DMX_TIMER_COMA << COM2A0) | (DMX_TIMER_COMB << COM2B0) | (DMX_TIMER_WGM_10 << WGM20)]
- poke [DMX_TIMER_CRB, r16, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
-
- ; trigger threshold for CTC
- poke [DMX_TIMER_OCRA, r16, (DMX_TIMER_TOP)]
-
- ; OK
- ret
-
-;; Start Break signal
-;;
-;; 22 bits - 1s long; then DMX_Break_Mark
-;;
-DMX_Break_Start:
- ; Low
- cbi DMX_PORT, DMX_DATA
-
- ret
-
-;; Start Mark-after-break signal
-;;
-;; 2 bits - 1s long; then DMX_Break_End
-;;
-DMX_Break_Mark:
- ; High
- sbi DMX_PORT, DMX_DATA
-
- ret
-
-;; End break; prepare for DMX_Frame
-DMX_Frame_Start:
- ; Start timer
- poke [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS << CS20)]
-
- ret
-
-;; Do a full DMX break, using some random length
-;;
-DMX_Break:
- ; Break
- ; start
- rcall DMX_Break_Start
-
- ; wait; about 100ms?
- ldi r20, 82 / 10
- rcall VarDelay
-
- ; MAB
- ; mark
- rcall DMX_Break_Mark
-
- ; short wait
- ldi r20, 1
- rcall VarDelay
-
- ; Timed frames
- ; start frame
- rcall DMX_Frame_Start
-
- ; ok
- ret
-
-;; Bitbang one DMX bit out
-;; uses SREG/C to send
-;
-; Uses Timer2 as a bit sync clock, sending out the next bit once we've hit 64 cycles on the timer
-DMX_Bit:
- ; Wait for bit sync clock
-_dmx_bit_wait:
- ; test OCA hit
- sbic TIFR2, OCF2A
- rjmp _dmx_bit_wait
-
-;sbi LED_PORT, LED_BIT
-
- ; Output bit
- ; XXX: ugly bit-testing, can't we do this using something more nifty?
- brcs _dmx_bit_1
-
- ; bit 0
- cbi DMX_PORT, DMX_DATA
- rjmp _dmx_bit_done
-
-_dmx_bit_1:
- ; bit 1
- sbi DMX_PORT, DMX_DATA
- nop
-
- ; Bit sent
-_dmx_bit_done:
- ; reset OCA hit for next bit
- cbi TIFR2, OCF2A
-
- ; OK, bit sync clock keeps running for next bit
- ret
-
-;; Bitbang one DMX byte out, using DMX_Bit
-;; r16: byte value
-;
-; Uses Timer2 as a bit sync clock; must call DMX_Frame_Start before first DMX_Frame
-DMX_Frame:
- ; Start bit
- clc
- rcall DMX_Bit
-
- ; Data bits: 8
- ldi r21, 8
-
-_dmx_frame_loop:
- ; shift + send bit
- lsl r16
- rcall DMX_Bit
-
- ; loop
- dec r21
- brne _dmx_frame_loop
-
- ; Stop bits
- sec
- rcall DMX_Bit
- rcall DMX_Bit
-
- ; OK
- ret
-
-;; End of DMX frames
-DMX_Frame_End:
- ; Keep mark from end of last frame; DMX_Break_Start starts the break
- ; Stop the timer
- poke [DMX_TIMER_CRB, r20, (DMX_TIMER_WGM_2 << WGM22) | (DMX_TIMER_CS_STOP << CS20)]
-
- ; OK
- ret
-
-;; Send one value on all frames
-;; r17: byte value
-DMX_Flood:
- ; Break
- rcall DMX_Break
-
- ; Start code
- ldi r16, 0
- rcall DMX_Frame
-
- ; Channels
- ; number of channels to send
- ldi r22, 100
-
-_dmx_flood_channels:
- ; restore channel value
- mov r16, r17
-
- ; send channel value
- rcall DMX_Frame
-
- ; loop
- dec r22
- brne _dmx_flood_channels
-
- ; End packet
- rcall DMX_Frame_End
-
-
- ret
-
-;; Program main
-Main:
-; Initialization
- ; Debug
- sbi LED_DDR, LED_BIT
-sbi LED_PORT, LED_BIT
-
- ; Stack
- poke [SPL, r16:r17, RAMEND]
-
- ; Init
- rcall DMX_Init
-
-cbi LED_PORT, LED_BIT
-
- ; Send; value
-_main_loop:
- ldi r17, 255
- rcall DMX_Flood
-
-cbi LED_PORT, LED_BIT
-
- ; never returns..
- rjmp _main_loop
-
--- a/font-compile.py Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,193 +0,0 @@
-def read_block (fh) :
- """
- Yield a series of non-empty lines from the given file, ignoring any leading empty lines, and stopping after the first empty line
- """
-
- leading = True
-
- for line in fh :
- if line.strip() :
- leading = False
-
- # yield non-empty
- yield line
-
- elif leading :
- # skip leading empty
- continue
-
- else :
- # stop on empty
- return
-
- else :
- # EOF
- return
-
-def read_charblock (lines) :
- """
- Read in a char from the given lines, returning an
- (ascii, rows)
-
- tuple, or None, if there weren't any more blocks
- """
-
- # the ascii code as a char
- ascii = ''
-
- # row data as ints
- rows = []
-
- for line in lines :
- line = line.strip()
-
- if line.startswith(';') :
- # set ascii code
- ascii = line.replace(';', '').strip()
-
- if not ascii :
- print 'read_charblock', 'empty'
-
- # skip
- return None
-
- elif len(ascii) == 1 :
- print 'read_charblock', 'simplechar', ascii
-
- else :
- ascii = ascii.decode('string_escape')
-
- print 'read_charblock', 'decodechar', ascii
-
- assert len(ascii) == 1
-
- else :
- # convert
- row = line.replace('#', '1').replace('-', '0')
-
- print 'read_charblock', 'row', row
-
- # 6 columns
- assert len(row) == 6
-
- # from binary
- row = int(row, 2)
-
- rows.append(row)
-
- # got data?
- if ascii and rows :
- # 8 rows
- assert len(rows) == 8
-
- return ascii, rows
-
- else :
- # nope, empty block, EOF
- return None
-
-def read_charblocks (fh) :
- """
- Read in all char blocks as (ascii, rows) tuples from given file
- """
-
- while True :
- out = read_charblock(read_block(fh))
-
- if out :
- yield out
-
- else :
- break
-
-def decode_rows (inrows) :
- """
- Decode char def data from its 6x8 row format into the format we need (6x8 col format)
- """
-
- outcols = [0x00] * 6
-
- for rowidx, row in enumerate(inrows) :
-
- for colidx, col in enumerate(outcols) :
- # get bit from row
- bit = (row >> (5 - colidx)) & 1
-
- # set bit into column
- outcols[colidx] |= (bit << rowidx)
-
- # ok...
- return outcols
-
-def write_chardef (fh, ascii, cols) :
- """
- Write out character definition block to given .def file, using given char code and column data
- """
-
- fh.write(
- ("; %r\n" % ascii)
- + (".db %s\n" % (', '.join(bin(col) for col in cols)))
- + ("\n")
- )
-
-def compile_fonts (infh, outf) :
- """
- Compile char blocks from infh, writing out definitions to outf
- """
-
- charmap = dict()
-
- # decode in
- for charblock in read_charblocks(infh) :
- # unpack
- ascii, rows = charblock
-
- # convert
- cols = decode_rows(rows)
-
- # map
- charmap[ascii] = cols
-
- print 'compile_fonts', 'read', ascii
-
- # detect min/max syms
- syms = charmap.keys()
- font_start = min(syms)
- font_end = max(syms)
-
- assert(ord(font_start) < ord(font_end))
-
- # write out
- outf.write(
- ";; AUTOMATICALLY GENERATED - Do not edit!\n"
- ";; 8x6 font, '0' - '1', rows-by-col format\n"
- + (".equ FONT_8x6_START = %d ; %r\n" % (ord(font_start), font_start))
- + (".equ FONT_8x6_END = %d ; %r\n" % (ord(font_end), font_end))
- + (".equ FONT_8x6_COLS = %d\n" % (6, ))
- + (".equ FONT_8x6_ROWS = %d\n" % (8, ))
- + "FONT_8x6:\n"
- "\n"
- )
-
- # default symbol for unknown chars
- defsym = charmap['\0']
-
- for char in xrange(ord(font_start), ord(font_end) + 1) :
- ascii = chr(char)
- cols = charmap.get(ascii, defsym)
-
- write_chardef(outf, ascii, cols)
-
-def main () :
- import sys, getopt
-
- opts, args = getopt.getopt(sys.argv[1:], '')
-
- inpath, outpath = args
-
- # run
- compile_fonts(open(inpath, 'r'), open(outpath, 'w'))
-
-if __name__ == '__main__' :
- main()
-
--- a/font.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,73 +0,0 @@
-;; Basic LED matrix fonts
-;; vim: set ft=avr:
-
-.cseg
-
-;; Font definition
-; Defines FONT_8x6 symbol
-.include "font.def"
-
-; Font to use
-.set FONT_TABLE = FONT_8x6
-.set FONT_START = FONT_8x6_START
-.set FONT_END = FONT_8x6_END
-.set FONT_COLS = FONT_8x6_COLS
-.set FONT_ROWS = FONT_8x6_ROWS ; XXX: fixed to 8
-
-;; Render the given ASCII char into the given buffer
-; Input: r16 - ASCII char code
-; Y - dest buf (Wx8 column data)
-Font_Render:
- ; Test char index
-
- ; test under-range
- ldi r17, FONT_START
- cp r16, r17
- brlt font_r_invalid
-
- ; test over-range
- ldi r17, FONT_END
- cp r17, r16
- brlt font_r_invalid
-
- ; compute offset in chars (r16)
- subi r16, FONT_START
-
- ; ok
- rjmp font_r_render
-
-font_r_invalid:
- ; use first sym
- ldi r16, 0
-
- cbi PORTD, PIND7
-
-font_r_render:
- ; compute offset in bytes (r1:r0)
- ldi r17, FONT_COLS
- mul r16, r17
-
- ; font table start offset from words
- ldi ZL, low(FONT_TABLE * 2)
- ldi ZH, high(FONT_TABLE * 2)
-
- ; apply offset
- add ZL, r0
- adc ZH, r1
-
- ; Copy column pixel data
- ; count columns
- ldi r16, FONT_COLS
-font_r_cpy:
-
- ; copy via r17
- lpm r17, Z+
- st Y+, r17
-
- dec r16
- brne font_r_cpy
-
-
- ; Done
- ret
-
--- a/font.txt Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,210 +0,0 @@
-; \x00
-------
--####-
--#--#-
--#--#-
--#--#-
--#--#-
--####-
-------
-
-; \x20
-------
-------
-------
-------
-------
-------
-------
-------
-
-; !
---##--
---##--
---##--
---##--
---##--
-------
---##--
---##--
-
-; 0
--####-
-#----#
-#----#
-#----#
-#----#
-#----#
-#----#
--####-
-
-; 1
----#--
---##--
--#-#--
-#--#--
----#--
----#--
----#--
--#####
-
-; 2
---###-
--#---#
--#---#
-----#-
----#--
---#---
--#----
-######
-
-; 3
--###--
-#---#-
------#
-----#-
----##-
------#
-#---#-
--###--
-
-; 4
-----#-
--#--#-
-##--#-
-#---#-
-######
-----#-
-----#-
-----#-
-
-; 5
-######
-#-----
-#-----
-#####-
------#
------#
-#----#
--####-
-
-; 6
-------
--####-
-##---#
-#-----
-#####-
-#----#
-#----#
--####-
-
-; 7
--#####
-#----#
-----#-
----#--
---#---
--#----
-#-----
-------
-
-; 8
-------
--####-
-#----#
-#----#
--####-
-#----#
-#----#
--####-
-
-; 9
--####-
-#----#
-#----#
-#----#
--#####
------#
------#
-----#-
-
-; h
-#-----
-#-----
-#-----
-#-----
-#-###-
-##---#
-#----#
-#----#
-
-; e
---##--
--#--#-
-#----#
-######
-#-----
-#---#-
--###--
-------
-
-; l
---##--
----#--
----#--
----#--
----#--
----#--
----#--
---###-
-
-; o
-------
-------
-------
--####-
-#----#
-#----#
-#----#
--####-
-
-; w
-------
-------
-------
-#---#-
-#---#-
-#---#-
-#-#-#-
--#-#--
-
-; r
-------
-------
-#-----
-#-##--
-##----
-#-----
-#-----
-#-----
-
-; d
-----#-
-----#-
-----#-
--####-
-#---#-
-#---#-
-#---#-
--###--
-
-;
-------
-------
-------
-------
-------
-------
-------
-------
-
--- a/hw.S Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,72 +0,0 @@
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-; Interrupt vector
-.org 0x00
- rjmp main ; Reset
-
-.org OC1Aaddr
- rjmp timer ; Timer 1 Compare A
-
-; Program code
-main:
- ; Setup pins for output
- sbi DDRB, PORTB4 ; Out
- sbi DDRB, PORTB5 ; Out
-
- ; Flags for output
- ldi r16, (1 << PORTB4)
-
- ; Setup Timer 0
- ; Count to 64k
- ldi r18, HIGH(0xffff/2)
- ldi r19, LOW(0xffff/2)
- sts OCR1AH, r18
- sts OCR1AL, r19
-
- ; Normal port operation for both comperators
- ; Bits WGM10:1 zero
- ldi r18, 0x00
- sts TCCR1A, r18
-
- ; CTC mode, 1/64 prescaled
- ; the timer will start counting from now, but that shouldn't matter..
- ldi r18, (1 << WGM12) | (0b011 << CS10)
- sts TCCR1B, r18
-
- ; Enable timer interrupt
- ldi r18, (1 << OCIE1A)
- sts TIMSK1, r18
-
- ; Setup sleep for Idle mode
- ldi r18, (0b000 << SM0) | (1 << SE)
- sts SMCR, r18
-
- ; ...and enable interrupts
- sei
-
-loop:
- ; Flip
- com r16
-
- ; Output
- out PORTB, r16
-
- ; Wait
-wait: sleep
- cpi r20, 1
- brne wait
- ldi r20, 0
-
- ; continue
- rjmp loop
-
-; Counter overflow handler
-timer:
- ; Set flag
- ldi r20, 1
-
- ; Re-enable interrupts
- reti
-
--- a/led7seg.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,152 +0,0 @@
-;;
-;; Driving 7-segment LED displays over SPI
-;;
-
-; Output Enable control
-.equ LED7_DDR = DDRB
-.equ LED7_PORT = PORTB
-.equ LED7_OE = PORTB1 ; Output Enable (Low)
-
-; Font for 7-segment display
-; Includes decimal digits 0-9, hexadecimal digits A-F, and some special chars
-LED7_Font:
-.db 0b00111111, 0b00000110 ; 0, 1
-.db 0b01011011, 0b01001111 ; 2, 3
-.db 0b01100110, 0b01101101 ; 4, 5
-.db 0b01111101, 0b00000111 ; 6, 7
-.db 0b01111111, 0b01100111 ; 8, 9
-.db 0b01110111, 0b01111100 ; A, b
-.db 0b00111001, 0b01011110 ; C, d
-.db 0b01111001, 0b01110001 ; E, f
-.db 0b10000000, 0b00000000 ; .,
-
-.equ LED7_0 = 0
-.equ LED7_1 = 1
-.equ LED7_2 = 2
-.equ LED7_3 = 3
-.equ LED7_4 = 4
-.equ LED7_5 = 5
-.equ LED7_6 = 6
-.equ LED7_7 = 7
-.equ LED7_8 = 8
-.equ LED7_9 = 9
-.equ LED7_A = 10
-.equ LED7_B = 11
-.equ LED7_C = 12
-.equ LED7_D = 13
-.equ LED7_E = 14
-.equ LED7_F = 15
-.equ LED7_DOT = 16
-.equ LED7_EMPTY = 17
-
-; LEDs are on beginning of SPI universe
-.set led7_buffer = spi_outbuf + 0
-
-;; Initialize LCD to empty, and enable
-LED7_Init:
- ; Setup ENable port
- sbi LED7_PORT, LED7_OE ; Disabled (Low)
- sbi LED7_DDR, LED7_OE ; Out
-
- ; Initialize buffer
- ldi r16, 0b01000000
- sts led7_buffer + 0, r16
- sts led7_buffer + 1, r16
-
- ; Update display
- rcall SPI_SendRecv
-
- ; Enable output once the initial display has been shifted out
- cbi LED7_PORT, LED7_OE
-
- ; Done
- ret
-
-LED7_LoadChar:
- clr r0, 0
-
- ; Prep address
- ; base addr for font table
- ldi ZH, high(2 * LED7_Font)
- ldi ZL, low(2 * LED7_Font)
-
- ; offset
- add ZL, r8
- adc ZH, r0
-
- ; Load char
- lpm r8, Z
-
- ; Done
- ret
-
-;; Display an 8-bit hexadecimal value on the display
-;; Input: r16
-LED7_ShowHex:
- ; base16
- ldi r17, 16
-
- ; 1's
- call div8u
-
- ; r16 = result, r15 = remainder
- mov r17, r15
-
- ; Continue
- rjmp LED7_Show
-
-;; Display an 8-bit decimal value on the display
-;; Input: r16
-LED7_ShowDec:
- ; base10
- ldi r17, 10
-
- ; 1's
- call div8u
- mov r8, r15
-
- ; 10's
- call div8u
- mov r9, r16 ; 100's
-
- ; 1's from r8
- rcall LED7_LoadChar
- mov r17, r8
-
- ; 10's from r15
- mov r8, r15
- rcall LED7_LoadChar
- mov r16, r8
-
- ; Set dots for 100's
- sbrc r9, 0
- ori r17, 0b10000000 ; +100
- sbrc r9, 1
- ori r16, 0b10000000 ; +200
-
- ; Continue
- rjmp LED7_ShowRaw
-
-;; Display a single digit on the display
-;; Input: r16, r17
-LED7_Show:
- mov r8, r16
- rcall LED7_LoadChar
- mov r16, r8
-
- mov r8, r17
- rcall LED7_LoadChar
- mov r17, r8
-
- ;; Continue
-
-;; Display a raw segment mask
-;; Input: r16, r17
-LED7_ShowRaw:
- ; Store buffer
- sts led7_buffer + 0, r16
- sts led7_buffer + 1, r17
-
- ; Update display
- rjmp SPI_Update
-
--- a/led7seg.s Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,246 +0,0 @@
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-
-;; Interrupt Vector
-.org 0x00
- rjmp init
-
-.org OC1Aaddr
- ; Timer/Counter1 Compare Output A
- rjmp Timer_OC1A
-
-.org OC0Aaddr
- ; Timer/Counter0 Compare Output A
- rjmp Timer_OC0A
-
-.org SPIaddr
- rjmp SPI_Interrupt
-
-.org ADCCaddr
- rjmp ADC_Interrupt
-
-.org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; SPI
-.include "spi.inc"
-
-;; LCD
-.include "led7seg.inc"
-
-;; DIPs
-.include "dip.inc"
-
-;; ADC
-
-; ADC Interrupt handler
-On_ADC:
- ; DEBUG
- sbi PIND, PORTD7
-
- ; Check timer, from r16
- rcall ADC_Read8
-
- ldi r17, 64
- mul r16, r17
- mov XL, r0
- mov XH, r1
-
- rjmp Timer_Update
-
-.set ADC_Handler = On_ADC
-
-.include "adc.inc"
-
-;; Timer
-.set TIMER0_CB_A = SPI_Update
-
-.include "timer.inc"
-
-;; Utils
-.include "delay.inc"
-.include "div.inc"
-
-Sleep_ADC:
- ; delay
- rcall ADC_Read8
- ; rcall DIP_Read8
-
- ; Sleep for 64 * var timer cycles
- ldi r17, 64
- mul r16, r17
- mov XL, r0
- mov XH, r1
-
- rjmp Timer_Sleep
-
-;; Show value
-Main_ShowValue:
- ; load value to r16
- ; rcall DIP_Read8
- rcall ADC_Read8
- ; rcall Timer0_Read8
-
- ; display from r16
- rcall LED7_ShowHex
-
- ; wait
- rcall Sleep_ADC
-
- ; ldi XL, 0
- ; ldi XH, 16
- ; rcall Timer_Sleep
-
- ; rcall ADC_Read8
- ; mov r20, r16
- ; rcall VarDelay
-
- ; continue
- rjmp Main_ShowValue
-
-;; Count down from F
-; Returns once we've hit zero
-Main_Countdown:
- ; init from F
- ldi r24, LED7_F
-
-_count_loop:
- ; display
- mov r16, r24
- mov r16, r24
- rcall LED7_Show
-
- ; exit if zero
- tst r24
- breq _count_end
-
- ; count down
- dec r24
-
- ; wait...
- rcall Sleep_ADC
-
- ; next
- rjmp _count_loop
-
-_count_end:
- ; done
- ret
-
-;; Count up from 00 -> 255
-; Returns once done
-Main_CountUp:
- ; init from 0
- ldi r24, 0
-
-_countup_loop:
- ; display
- mov r16, r24
- rcall LED7_ShowDec
-
- ; wait...
- rcall Sleep_ADC
-
- ; exit if zero
- cpi r24, 255
- breq _countup_end
-
- ; count up
- inc r24
-
- ; continue
- rjmp _countup_loop
-
-_countup_end:
- ; done
- ret
-
-;; Blink between dot and empty
-Main_Blink:
-_blink_loop:
- ; dot
- ldi r16, LED7_DOT
- ldi r17, LED7_EMPTY
- rcall LED7_Show
-
- ; wait...
- rcall Sleep_ADC
-
- ; empty
- ldi r16, LED7_EMPTY
- ldi r17, LED7_DOT
- rcall LED7_Show
-
- ; wait...
- rcall Sleep_ADC
-
- ; loop
- rjmp _blink_loop
-
-;; Chase segments
-Main_Spin:
-_spin_init:
- ; init from top
- ldi r24, 0b00000001
-
-_spin_next:
- ; display
- mov r16, r24
- mov r17, r24
- com r17
- andi r17, 0b00111111
- rcall LED7_ShowRaw
-
- ; delay
- rcall Sleep_ADC
-
- ; next segment
- lsl r24
-
- ; go back to A if we hit G
- sbrc r24, 6
- rjmp _spin_init
-
- rjmp _spin_next
-
-Main:
-init:
- ; Stack
- ldi r16, high(RAMEND)
- ldi r17, low(RAMEND)
- out SPH, r16
- out SPL, r17
-
- ; Enable interrupts
- sei
-
- ; ADC (slowest to start up)
- rcall ADC_Init
-
- ; Timer
- rcall Timer_Init
-
- ; SPI
- rcall SPI_Init
-
- ; LCD (requires interrupts, blocks)
- rcall LED7_Init
-
- ; DEBUG
- sbi DDRD, PORTD7
- cbi PORTD, PORTD7
-
- ; Run
- rcall Main_Countup
- ; rcall Main_Countdown
- ; rcall Main_ShowValue
- ; rcall Main_Spin
- rcall Main_Blink
-
-end:
- rjmp end
-
--- a/m168def.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,958 +0,0 @@
-;***** THIS IS A MACHINE GENERATED FILE - DO NOT EDIT ********************
-;***** Created: 2005-01-11 10:30 ******* Source: ATmega168.xml ***********
-;*************************************************************************
-;* A P P L I C A T I O N N O T E F O R T H E A V R F A M I L Y
-;*
-;* Number : AVR000
-;* File Name : "m168def.inc"
-;* Title : Register/Bit Definitions for the ATmega168
-;* Date : 2005-01-11
-;* Version : 2.14
-;* Support E-mail : avr@atmel.com
-;* Target MCU : ATmega168
-;*
-;* DESCRIPTION
-;* When including this file in the assembly program file, all I/O register
-;* names and I/O register bit names appearing in the data book can be used.
-;* In addition, the six registers forming the three data pointers X, Y and
-;* Z have been assigned names XL - ZH. Highest RAM address for Internal
-;* SRAM is also defined
-;*
-;* The Register names are represented by their hexadecimal address.
-;*
-;* The Register Bit names are represented by their bit number (0-7).
-;*
-;* Please observe the difference in using the bit names with instructions
-;* such as "sbr"/"cbr" (set/clear bit in register) and "sbrs"/"sbrc"
-;* (skip if bit in register set/cleared). The following example illustrates
-;* this:
-;*
-;* in r16,PORTB ;read PORTB latch
-;* sbr r16,(1<<PB6)+(1<<PB5) ;set PB6 and PB5 (use masks, not bit#)
-;* out PORTB,r16 ;output to PORTB
-;*
-;* in r16,TIFR ;read the Timer Interrupt Flag Register
-;* sbrc r16,TOV0 ;test the overflow flag (use bit#)
-;* rjmp TOV0_is_set ;jump if set
-;* ... ;otherwise do something else
-;*************************************************************************
-
-; #ifndef _M168DEF_INC_
-; #define _M168DEF_INC_
-
-
-; #pragma partinc 0
-
-; ***** SPECIFY DEVICE ***************************************************
-.device ATmega168
-; #pragma AVRPART ADMIN PART_NAME ATmega168
-.equ SIGNATURE_000 = 0x1e
-.equ SIGNATURE_001 = 0x94
-.equ SIGNATURE_002 = 0x06
-
-; #pragma AVRPART CORE CORE_VERSION V2E
-
-
-; ***** I/O REGISTER DEFINITIONS *****************************************
-; NOTE:
-; Definitions marked "MEMORY MAPPED"are extended I/O ports
-; and cannot be used with IN/OUT instructions
-.equ UDR0 = 0xc6 ; MEMORY MAPPED
-.equ UBRR0H = 0xc5 ; MEMORY MAPPED
-.equ UBRR0L = 0xc4 ; MEMORY MAPPED
-.equ UCSR0C = 0xc2 ; MEMORY MAPPED
-.equ UCSR0B = 0xc1 ; MEMORY MAPPED
-.equ UCSR0A = 0xc0 ; MEMORY MAPPED
-.equ TWAMR = 0xbd ; MEMORY MAPPED
-.equ TWCR = 0xbc ; MEMORY MAPPED
-.equ TWDR = 0xbb ; MEMORY MAPPED
-.equ TWAR = 0xba ; MEMORY MAPPED
-.equ TWSR = 0xb9 ; MEMORY MAPPED
-.equ TWBR = 0xb8 ; MEMORY MAPPED
-.equ ASSR = 0xb6 ; MEMORY MAPPED
-.equ OCR2B = 0xb4 ; MEMORY MAPPED
-.equ OCR2A = 0xb3 ; MEMORY MAPPED
-.equ TCNT2 = 0xb2 ; MEMORY MAPPED
-.equ TCCR2B = 0xb1 ; MEMORY MAPPED
-.equ TCCR2A = 0xb0 ; MEMORY MAPPED
-.equ OCR1BH = 0x8b ; MEMORY MAPPED
-.equ OCR1BL = 0x8a ; MEMORY MAPPED
-.equ OCR1AH = 0x89 ; MEMORY MAPPED
-.equ OCR1AL = 0x88 ; MEMORY MAPPED
-.equ ICR1H = 0x87 ; MEMORY MAPPED
-.equ ICR1L = 0x86 ; MEMORY MAPPED
-.equ TCNT1H = 0x85 ; MEMORY MAPPED
-.equ TCNT1L = 0x84 ; MEMORY MAPPED
-.equ TCCR1C = 0x82 ; MEMORY MAPPED
-.equ TCCR1B = 0x81 ; MEMORY MAPPED
-.equ TCCR1A = 0x80 ; MEMORY MAPPED
-.equ DIDR1 = 0x7f ; MEMORY MAPPED
-.equ DIDR0 = 0x7e ; MEMORY MAPPED
-.equ ADMUX = 0x7c ; MEMORY MAPPED
-.equ ADCSRB = 0x7b ; MEMORY MAPPED
-.equ ADCSRA = 0x7a ; MEMORY MAPPED
-.equ ADCH = 0x79 ; MEMORY MAPPED
-.equ ADCL = 0x78 ; MEMORY MAPPED
-.equ TIMSK2 = 0x70 ; MEMORY MAPPED
-.equ TIMSK1 = 0x6f ; MEMORY MAPPED
-.equ TIMSK0 = 0x6e ; MEMORY MAPPED
-.equ PCMSK2 = 0x6d ; MEMORY MAPPED
-.equ PCMSK1 = 0x6c ; MEMORY MAPPED
-.equ PCMSK0 = 0x6b ; MEMORY MAPPED
-.equ EICRA = 0x69 ; MEMORY MAPPED
-.equ PCICR = 0x68 ; MEMORY MAPPED
-.equ OSCCAL = 0x66 ; MEMORY MAPPED
-.equ PRR = 0x64 ; MEMORY MAPPED
-.equ CLKPR = 0x61 ; MEMORY MAPPED
-.equ WDTCSR = 0x60 ; MEMORY MAPPED
-.equ SREG = 0x3f
-.equ SPH = 0x3e
-.equ SPL = 0x3d
-.equ SPMCSR = 0x37
-.equ MCUCR = 0x35
-.equ MCUSR = 0x34
-.equ SMCR = 0x33
-.equ ACSR = 0x30
-.equ SPDR = 0x2e
-.equ SPSR = 0x2d
-.equ SPCR = 0x2c
-.equ GPIOR2 = 0x2b
-.equ GPIOR1 = 0x2a
-.equ OCR0B = 0x28
-.equ OCR0A = 0x27
-.equ TCNT0 = 0x26
-.equ TCCR0B = 0x25
-.equ TCCR0A = 0x24
-.equ GTCCR = 0x23
-.equ EEARH = 0x22
-.equ EEARL = 0x21
-.equ EEDR = 0x20
-.equ EECR = 0x1f
-.equ GPIOR0 = 0x1e
-.equ EIMSK = 0x1d
-.equ EIFR = 0x1c
-.equ PCIFR = 0x1b
-.equ TIFR2 = 0x17
-.equ TIFR1 = 0x16
-.equ TIFR0 = 0x15
-.equ PORTD = 0x0b
-.equ DDRD = 0x0a
-.equ PIND = 0x09
-.equ PORTC = 0x08
-.equ DDRC = 0x07
-.equ PINC = 0x06
-.equ PORTB = 0x05
-.equ DDRB = 0x04
-.equ PINB = 0x03
-
-
-; ***** BIT DEFINITIONS **************************************************
-
-; ***** USART0 ***********************
-; UDR0 - USART I/O Data Register
-.equ UDR0_0 = 0 ; USART I/O Data Register bit 0
-.equ UDR0_1 = 1 ; USART I/O Data Register bit 1
-.equ UDR0_2 = 2 ; USART I/O Data Register bit 2
-.equ UDR0_3 = 3 ; USART I/O Data Register bit 3
-.equ UDR0_4 = 4 ; USART I/O Data Register bit 4
-.equ UDR0_5 = 5 ; USART I/O Data Register bit 5
-.equ UDR0_6 = 6 ; USART I/O Data Register bit 6
-.equ UDR0_7 = 7 ; USART I/O Data Register bit 7
-
-; UCSR0A - USART Control and Status Register A
-.equ MPCM0 = 0 ; Multi-processor Communication Mode
-.equ U2X0 = 1 ; Double the USART transmission speed
-.equ UPE0 = 2 ; Parity Error
-.equ DOR0 = 3 ; Data overRun
-.equ FE0 = 4 ; Framing Error
-.equ UDRE0 = 5 ; USART Data Register Empty
-.equ TXC0 = 6 ; USART Transmitt Complete
-.equ RXC0 = 7 ; USART Receive Complete
-
-; UCSR0B - USART Control and Status Register B
-.equ TXB80 = 0 ; Transmit Data Bit 8
-.equ RXB80 = 1 ; Receive Data Bit 8
-.equ UCSZ02 = 2 ; Character Size
-.equ TXEN0 = 3 ; Transmitter Enable
-.equ RXEN0 = 4 ; Receiver Enable
-.equ UDRIE0 = 5 ; USART Data register Empty Interrupt Enable
-.equ TXCIE0 = 6 ; TX Complete Interrupt Enable
-.equ RXCIE0 = 7 ; RX Complete Interrupt Enable
-
-; UCSR0C - USART Control and Status Register C
-.equ UCPOL0 = 0 ; Clock Polarity
-.equ UCSZ00 = 1 ; Character Size
-.equ UCPHA0 = UCSZ00 ; For compatibility
-.equ UCSZ01 = 2 ; Character Size
-.equ UDORD0 = UCSZ01 ; For compatibility
-.equ USBS0 = 3 ; Stop Bit Select
-.equ UPM00 = 4 ; Parity Mode Bit 0
-.equ UPM01 = 5 ; Parity Mode Bit 1
-.equ UMSEL00 = 6 ; USART Mode Select
-.equ UMSEL0 = UMSEL00 ; For compatibility
-.equ UMSEL01 = 7 ; USART Mode Select
-.equ UMSEL1 = UMSEL01 ; For compatibility
-
-
-; ***** TWI **************************
-; TWAMR - TWI (Slave) Address Mask Register
-.equ TWAM0 = 1 ;
-.equ TWAMR0 = TWAM0 ; For compatibility
-.equ TWAM1 = 2 ;
-.equ TWAMR1 = TWAM1 ; For compatibility
-.equ TWAM2 = 3 ;
-.equ TWAMR2 = TWAM2 ; For compatibility
-.equ TWAM3 = 4 ;
-.equ TWAMR3 = TWAM3 ; For compatibility
-.equ TWAM4 = 5 ;
-.equ TWAMR4 = TWAM4 ; For compatibility
-.equ TWAM5 = 6 ;
-.equ TWAMR5 = TWAM5 ; For compatibility
-.equ TWAM6 = 7 ;
-.equ TWAMR6 = TWAM6 ; For compatibility
-
-; TWBR - TWI Bit Rate register
-.equ TWBR0 = 0 ;
-.equ TWBR1 = 1 ;
-.equ TWBR2 = 2 ;
-.equ TWBR3 = 3 ;
-.equ TWBR4 = 4 ;
-.equ TWBR5 = 5 ;
-.equ TWBR6 = 6 ;
-.equ TWBR7 = 7 ;
-
-; TWCR - TWI Control Register
-.equ TWIE = 0 ; TWI Interrupt Enable
-.equ TWEN = 2 ; TWI Enable Bit
-.equ TWWC = 3 ; TWI Write Collition Flag
-.equ TWSTO = 4 ; TWI Stop Condition Bit
-.equ TWSTA = 5 ; TWI Start Condition Bit
-.equ TWEA = 6 ; TWI Enable Acknowledge Bit
-.equ TWINT = 7 ; TWI Interrupt Flag
-
-; TWSR - TWI Status Register
-.equ TWPS0 = 0 ; TWI Prescaler
-.equ TWPS1 = 1 ; TWI Prescaler
-.equ TWS3 = 3 ; TWI Status
-.equ TWS4 = 4 ; TWI Status
-.equ TWS5 = 5 ; TWI Status
-.equ TWS6 = 6 ; TWI Status
-.equ TWS7 = 7 ; TWI Status
-
-; TWDR - TWI Data register
-.equ TWD0 = 0 ; TWI Data Register Bit 0
-.equ TWD1 = 1 ; TWI Data Register Bit 1
-.equ TWD2 = 2 ; TWI Data Register Bit 2
-.equ TWD3 = 3 ; TWI Data Register Bit 3
-.equ TWD4 = 4 ; TWI Data Register Bit 4
-.equ TWD5 = 5 ; TWI Data Register Bit 5
-.equ TWD6 = 6 ; TWI Data Register Bit 6
-.equ TWD7 = 7 ; TWI Data Register Bit 7
-
-; TWAR - TWI (Slave) Address register
-.equ TWGCE = 0 ; TWI General Call Recognition Enable Bit
-.equ TWA0 = 1 ; TWI (Slave) Address register Bit 0
-.equ TWA1 = 2 ; TWI (Slave) Address register Bit 1
-.equ TWA2 = 3 ; TWI (Slave) Address register Bit 2
-.equ TWA3 = 4 ; TWI (Slave) Address register Bit 3
-.equ TWA4 = 5 ; TWI (Slave) Address register Bit 4
-.equ TWA5 = 6 ; TWI (Slave) Address register Bit 5
-.equ TWA6 = 7 ; TWI (Slave) Address register Bit 6
-
-
-; ***** TIMER_COUNTER_1 **************
-; TIMSK1 - Timer/Counter Interrupt Mask Register
-.equ TOIE1 = 0 ; Timer/Counter1 Overflow Interrupt Enable
-.equ OCIE1A = 1 ; Timer/Counter1 Output CompareA Match Interrupt Enable
-.equ OCIE1B = 2 ; Timer/Counter1 Output CompareB Match Interrupt Enable
-.equ ICIE1 = 5 ; Timer/Counter1 Input Capture Interrupt Enable
-
-; TIFR1 - Timer/Counter Interrupt Flag register
-.equ TOV1 = 0 ; Timer/Counter1 Overflow Flag
-.equ OCF1A = 1 ; Output Compare Flag 1A
-.equ OCF1B = 2 ; Output Compare Flag 1B
-.equ ICF1 = 5 ; Input Capture Flag 1
-
-; TCCR1A - Timer/Counter1 Control Register A
-.equ WGM10 = 0 ; Waveform Generation Mode
-.equ WGM11 = 1 ; Waveform Generation Mode
-.equ COM1B0 = 4 ; Compare Output Mode 1B, bit 0
-.equ COM1B1 = 5 ; Compare Output Mode 1B, bit 1
-.equ COM1A0 = 6 ; Comparet Ouput Mode 1A, bit 0
-.equ COM1A1 = 7 ; Compare Output Mode 1A, bit 1
-
-; TCCR1B - Timer/Counter1 Control Register B
-.equ CS10 = 0 ; Prescaler source of Timer/Counter 1
-.equ CS11 = 1 ; Prescaler source of Timer/Counter 1
-.equ CS12 = 2 ; Prescaler source of Timer/Counter 1
-.equ WGM12 = 3 ; Waveform Generation Mode
-.equ WGM13 = 4 ; Waveform Generation Mode
-.equ ICES1 = 6 ; Input Capture 1 Edge Select
-.equ ICNC1 = 7 ; Input Capture 1 Noise Canceler
-
-; TCCR1C - Timer/Counter1 Control Register C
-.equ FOC1B = 6 ;
-.equ FOC1A = 7 ;
-
-; GTCCR - General Timer/Counter Control Register
-.equ PSRSYNC = 0 ; Prescaler Reset Timer/Counter1 and Timer/Counter0
-.equ TSM = 7 ; Timer/Counter Synchronization Mode
-
-
-; ***** TIMER_COUNTER_2 **************
-; TIMSK2 - Timer/Counter Interrupt Mask register
-.equ TOIE2 = 0 ; Timer/Counter2 Overflow Interrupt Enable
-.equ TOIE2A = TOIE2 ; For compatibility
-.equ OCIE2A = 1 ; Timer/Counter2 Output Compare Match A Interrupt Enable
-.equ OCIE2B = 2 ; Timer/Counter2 Output Compare Match B Interrupt Enable
-
-; TIFR2 - Timer/Counter Interrupt Flag Register
-.equ TOV2 = 0 ; Timer/Counter2 Overflow Flag
-.equ OCF2A = 1 ; Output Compare Flag 2A
-.equ OCF2B = 2 ; Output Compare Flag 2B
-
-; TCCR2A - Timer/Counter2 Control Register A
-.equ WGM20 = 0 ; Waveform Genration Mode
-.equ WGM21 = 1 ; Waveform Genration Mode
-.equ COM2B0 = 4 ; Compare Output Mode bit 0
-.equ COM2B1 = 5 ; Compare Output Mode bit 1
-.equ COM2A0 = 6 ; Compare Output Mode bit 1
-.equ COM2A1 = 7 ; Compare Output Mode bit 1
-
-; TCCR2B - Timer/Counter2 Control Register B
-.equ CS20 = 0 ; Clock Select bit 0
-.equ CS21 = 1 ; Clock Select bit 1
-.equ CS22 = 2 ; Clock Select bit 2
-.equ WGM22 = 3 ; Waveform Generation Mode
-.equ FOC2B = 6 ; Force Output Compare B
-.equ FOC2A = 7 ; Force Output Compare A
-
-; TCNT2 - Timer/Counter2
-.equ TCNT2_0 = 0 ; Timer/Counter 2 bit 0
-.equ TCNT2_1 = 1 ; Timer/Counter 2 bit 1
-.equ TCNT2_2 = 2 ; Timer/Counter 2 bit 2
-.equ TCNT2_3 = 3 ; Timer/Counter 2 bit 3
-.equ TCNT2_4 = 4 ; Timer/Counter 2 bit 4
-.equ TCNT2_5 = 5 ; Timer/Counter 2 bit 5
-.equ TCNT2_6 = 6 ; Timer/Counter 2 bit 6
-.equ TCNT2_7 = 7 ; Timer/Counter 2 bit 7
-
-; OCR2A - Timer/Counter2 Output Compare Register A
-.equ OCR2_0 = 0 ; Timer/Counter2 Output Compare Register Bit 0
-.equ OCR2_1 = 1 ; Timer/Counter2 Output Compare Register Bit 1
-.equ OCR2_2 = 2 ; Timer/Counter2 Output Compare Register Bit 2
-.equ OCR2_3 = 3 ; Timer/Counter2 Output Compare Register Bit 3
-.equ OCR2_4 = 4 ; Timer/Counter2 Output Compare Register Bit 4
-.equ OCR2_5 = 5 ; Timer/Counter2 Output Compare Register Bit 5
-.equ OCR2_6 = 6 ; Timer/Counter2 Output Compare Register Bit 6
-.equ OCR2_7 = 7 ; Timer/Counter2 Output Compare Register Bit 7
-
-; OCR2B - Timer/Counter2 Output Compare Register B
-;.equ OCR2_0 = 0 ; Timer/Counter2 Output Compare Register Bit 0
-;.equ OCR2_1 = 1 ; Timer/Counter2 Output Compare Register Bit 1
-;.equ OCR2_2 = 2 ; Timer/Counter2 Output Compare Register Bit 2
-;.equ OCR2_3 = 3 ; Timer/Counter2 Output Compare Register Bit 3
-;.equ OCR2_4 = 4 ; Timer/Counter2 Output Compare Register Bit 4
-;.equ OCR2_5 = 5 ; Timer/Counter2 Output Compare Register Bit 5
-;.equ OCR2_6 = 6 ; Timer/Counter2 Output Compare Register Bit 6
-;.equ OCR2_7 = 7 ; Timer/Counter2 Output Compare Register Bit 7
-
-; ASSR - Asynchronous Status Register
-.equ TCR2BUB = 0 ; Timer/Counter Control Register2 Update Busy
-.equ TCR2AUB = 1 ; Timer/Counter Control Register2 Update Busy
-.equ OCR2BUB = 2 ; Output Compare Register 2 Update Busy
-.equ OCR2AUB = 3 ; Output Compare Register2 Update Busy
-.equ TCN2UB = 4 ; Timer/Counter2 Update Busy
-.equ AS2 = 5 ; Asynchronous Timer/Counter2
-.equ EXCLK = 6 ; Enable External Clock Input
-
-; GTCCR - General Timer Counter Control register
-.equ PSRASY = 1 ; Prescaler Reset Timer/Counter2
-.equ PSR2 = PSRASY ; For compatibility
-;.equ TSM = 7 ; Timer/Counter Synchronization Mode
-
-
-; ***** AD_CONVERTER *****************
-; ADMUX - The ADC multiplexer Selection Register
-.equ MUX0 = 0 ; Analog Channel and Gain Selection Bits
-.equ MUX1 = 1 ; Analog Channel and Gain Selection Bits
-.equ MUX2 = 2 ; Analog Channel and Gain Selection Bits
-.equ MUX3 = 3 ; Analog Channel and Gain Selection Bits
-.equ ADLAR = 5 ; Left Adjust Result
-.equ REFS0 = 6 ; Reference Selection Bit 0
-.equ REFS1 = 7 ; Reference Selection Bit 1
-
-; ADCSRA - The ADC Control and Status register A
-.equ ADPS0 = 0 ; ADC Prescaler Select Bits
-.equ ADPS1 = 1 ; ADC Prescaler Select Bits
-.equ ADPS2 = 2 ; ADC Prescaler Select Bits
-.equ ADIE = 3 ; ADC Interrupt Enable
-.equ ADIF = 4 ; ADC Interrupt Flag
-.equ ADATE = 5 ; ADC Auto Trigger Enable
-.equ ADSC = 6 ; ADC Start Conversion
-.equ ADEN = 7 ; ADC Enable
-
-; ADCSRB - The ADC Control and Status register B
-.equ ADTS0 = 0 ; ADC Auto Trigger Source bit 0
-.equ ADTS1 = 1 ; ADC Auto Trigger Source bit 1
-.equ ADTS2 = 2 ; ADC Auto Trigger Source bit 2
-.equ ACME = 6 ;
-
-; ADCH - ADC Data Register High Byte
-.equ ADCH0 = 0 ; ADC Data Register High Byte Bit 0
-.equ ADCH1 = 1 ; ADC Data Register High Byte Bit 1
-.equ ADCH2 = 2 ; ADC Data Register High Byte Bit 2
-.equ ADCH3 = 3 ; ADC Data Register High Byte Bit 3
-.equ ADCH4 = 4 ; ADC Data Register High Byte Bit 4
-.equ ADCH5 = 5 ; ADC Data Register High Byte Bit 5
-.equ ADCH6 = 6 ; ADC Data Register High Byte Bit 6
-.equ ADCH7 = 7 ; ADC Data Register High Byte Bit 7
-
-; ADCL - ADC Data Register Low Byte
-.equ ADCL0 = 0 ; ADC Data Register Low Byte Bit 0
-.equ ADCL1 = 1 ; ADC Data Register Low Byte Bit 1
-.equ ADCL2 = 2 ; ADC Data Register Low Byte Bit 2
-.equ ADCL3 = 3 ; ADC Data Register Low Byte Bit 3
-.equ ADCL4 = 4 ; ADC Data Register Low Byte Bit 4
-.equ ADCL5 = 5 ; ADC Data Register Low Byte Bit 5
-.equ ADCL6 = 6 ; ADC Data Register Low Byte Bit 6
-.equ ADCL7 = 7 ; ADC Data Register Low Byte Bit 7
-
-; DIDR0 - Digital Input Disable Register
-.equ ADC0D = 0 ;
-.equ ADC1D = 1 ;
-.equ ADC2D = 2 ;
-.equ ADC3D = 3 ;
-.equ ADC4D = 4 ;
-.equ ADC5D = 5 ;
-
-
-; ***** ANALOG_COMPARATOR ************
-; ACSR - Analog Comparator Control And Status Register
-.equ ACIS0 = 0 ; Analog Comparator Interrupt Mode Select bit 0
-.equ ACIS1 = 1 ; Analog Comparator Interrupt Mode Select bit 1
-.equ ACIC = 2 ;
-.equ ACIE = 3 ; Analog Comparator Interrupt Enable
-.equ ACI = 4 ; Analog Comparator Interrupt Flag
-.equ ACO = 5 ; Analog Compare Output
-.equ ACBG = 6 ; Analog Comparator Bandgap Select
-.equ ACD = 7 ; Analog Comparator Disable
-
-; DIDR1 - Digital Input Disable Register 1
-.equ AIN0D = 0 ; AIN0 Digital Input Disable
-.equ AIN1D = 1 ; AIN1 Digital Input Disable
-
-
-; ***** PORTB ************************
-; PORTB - Port B Data Register
-.equ PORTB0 = 0 ; Port B Data Register bit 0
-.equ PB0 = 0 ; For compatibility
-.equ PORTB1 = 1 ; Port B Data Register bit 1
-.equ PB1 = 1 ; For compatibility
-.equ PORTB2 = 2 ; Port B Data Register bit 2
-.equ PB2 = 2 ; For compatibility
-.equ PORTB3 = 3 ; Port B Data Register bit 3
-.equ PB3 = 3 ; For compatibility
-.equ PORTB4 = 4 ; Port B Data Register bit 4
-.equ PB4 = 4 ; For compatibility
-.equ PORTB5 = 5 ; Port B Data Register bit 5
-.equ PB5 = 5 ; For compatibility
-.equ PORTB6 = 6 ; Port B Data Register bit 6
-.equ PB6 = 6 ; For compatibility
-.equ PORTB7 = 7 ; Port B Data Register bit 7
-.equ PB7 = 7 ; For compatibility
-
-; DDRB - Port B Data Direction Register
-.equ DDB0 = 0 ; Port B Data Direction Register bit 0
-.equ DDB1 = 1 ; Port B Data Direction Register bit 1
-.equ DDB2 = 2 ; Port B Data Direction Register bit 2
-.equ DDB3 = 3 ; Port B Data Direction Register bit 3
-.equ DDB4 = 4 ; Port B Data Direction Register bit 4
-.equ DDB5 = 5 ; Port B Data Direction Register bit 5
-.equ DDB6 = 6 ; Port B Data Direction Register bit 6
-.equ DDB7 = 7 ; Port B Data Direction Register bit 7
-
-; PINB - Port B Input Pins
-.equ PINB0 = 0 ; Port B Input Pins bit 0
-.equ PINB1 = 1 ; Port B Input Pins bit 1
-.equ PINB2 = 2 ; Port B Input Pins bit 2
-.equ PINB3 = 3 ; Port B Input Pins bit 3
-.equ PINB4 = 4 ; Port B Input Pins bit 4
-.equ PINB5 = 5 ; Port B Input Pins bit 5
-.equ PINB6 = 6 ; Port B Input Pins bit 6
-.equ PINB7 = 7 ; Port B Input Pins bit 7
-
-
-; ***** PORTC ************************
-; PORTC - Port C Data Register
-.equ PORTC0 = 0 ; Port C Data Register bit 0
-.equ PC0 = 0 ; For compatibility
-.equ PORTC1 = 1 ; Port C Data Register bit 1
-.equ PC1 = 1 ; For compatibility
-.equ PORTC2 = 2 ; Port C Data Register bit 2
-.equ PC2 = 2 ; For compatibility
-.equ PORTC3 = 3 ; Port C Data Register bit 3
-.equ PC3 = 3 ; For compatibility
-.equ PORTC4 = 4 ; Port C Data Register bit 4
-.equ PC4 = 4 ; For compatibility
-.equ PORTC5 = 5 ; Port C Data Register bit 5
-.equ PC5 = 5 ; For compatibility
-.equ PORTC6 = 6 ; Port C Data Register bit 6
-.equ PC6 = 6 ; For compatibility
-
-; DDRC - Port C Data Direction Register
-.equ DDC0 = 0 ; Port C Data Direction Register bit 0
-.equ DDC1 = 1 ; Port C Data Direction Register bit 1
-.equ DDC2 = 2 ; Port C Data Direction Register bit 2
-.equ DDC3 = 3 ; Port C Data Direction Register bit 3
-.equ DDC4 = 4 ; Port C Data Direction Register bit 4
-.equ DDC5 = 5 ; Port C Data Direction Register bit 5
-.equ DDC6 = 6 ; Port C Data Direction Register bit 6
-
-; PINC - Port C Input Pins
-.equ PINC0 = 0 ; Port C Input Pins bit 0
-.equ PINC1 = 1 ; Port C Input Pins bit 1
-.equ PINC2 = 2 ; Port C Input Pins bit 2
-.equ PINC3 = 3 ; Port C Input Pins bit 3
-.equ PINC4 = 4 ; Port C Input Pins bit 4
-.equ PINC5 = 5 ; Port C Input Pins bit 5
-.equ PINC6 = 6 ; Port C Input Pins bit 6
-
-
-; ***** PORTD ************************
-; PORTD - Port D Data Register
-.equ PORTD0 = 0 ; Port D Data Register bit 0
-.equ PD0 = 0 ; For compatibility
-.equ PORTD1 = 1 ; Port D Data Register bit 1
-.equ PD1 = 1 ; For compatibility
-.equ PORTD2 = 2 ; Port D Data Register bit 2
-.equ PD2 = 2 ; For compatibility
-.equ PORTD3 = 3 ; Port D Data Register bit 3
-.equ PD3 = 3 ; For compatibility
-.equ PORTD4 = 4 ; Port D Data Register bit 4
-.equ PD4 = 4 ; For compatibility
-.equ PORTD5 = 5 ; Port D Data Register bit 5
-.equ PD5 = 5 ; For compatibility
-.equ PORTD6 = 6 ; Port D Data Register bit 6
-.equ PD6 = 6 ; For compatibility
-.equ PORTD7 = 7 ; Port D Data Register bit 7
-.equ PD7 = 7 ; For compatibility
-
-; DDRD - Port D Data Direction Register
-.equ DDD0 = 0 ; Port D Data Direction Register bit 0
-.equ DDD1 = 1 ; Port D Data Direction Register bit 1
-.equ DDD2 = 2 ; Port D Data Direction Register bit 2
-.equ DDD3 = 3 ; Port D Data Direction Register bit 3
-.equ DDD4 = 4 ; Port D Data Direction Register bit 4
-.equ DDD5 = 5 ; Port D Data Direction Register bit 5
-.equ DDD6 = 6 ; Port D Data Direction Register bit 6
-.equ DDD7 = 7 ; Port D Data Direction Register bit 7
-
-; PIND - Port D Input Pins
-.equ PIND0 = 0 ; Port D Input Pins bit 0
-.equ PIND1 = 1 ; Port D Input Pins bit 1
-.equ PIND2 = 2 ; Port D Input Pins bit 2
-.equ PIND3 = 3 ; Port D Input Pins bit 3
-.equ PIND4 = 4 ; Port D Input Pins bit 4
-.equ PIND5 = 5 ; Port D Input Pins bit 5
-.equ PIND6 = 6 ; Port D Input Pins bit 6
-.equ PIND7 = 7 ; Port D Input Pins bit 7
-
-
-; ***** TIMER_COUNTER_0 **************
-; TIMSK0 - Timer/Counter0 Interrupt Mask Register
-.equ TOIE0 = 0 ; Timer/Counter0 Overflow Interrupt Enable
-.equ OCIE0A = 1 ; Timer/Counter0 Output Compare Match A Interrupt Enable
-.equ OCIE0B = 2 ; Timer/Counter0 Output Compare Match B Interrupt Enable
-
-; TIFR0 - Timer/Counter0 Interrupt Flag register
-.equ TOV0 = 0 ; Timer/Counter0 Overflow Flag
-.equ OCF0A = 1 ; Timer/Counter0 Output Compare Flag 0A
-.equ OCF0B = 2 ; Timer/Counter0 Output Compare Flag 0B
-
-; TCCR0A - Timer/Counter Control Register A
-.equ WGM00 = 0 ; Waveform Generation Mode
-.equ WGM01 = 1 ; Waveform Generation Mode
-.equ COM0B0 = 4 ; Compare Output Mode, Fast PWm
-.equ COM0B1 = 5 ; Compare Output Mode, Fast PWm
-.equ COM0A0 = 6 ; Compare Output Mode, Phase Correct PWM Mode
-.equ COM0A1 = 7 ; Compare Output Mode, Phase Correct PWM Mode
-
-; TCCR0B - Timer/Counter Control Register B
-.equ CS00 = 0 ; Clock Select
-.equ CS01 = 1 ; Clock Select
-.equ CS02 = 2 ; Clock Select
-.equ WGM02 = 3 ;
-.equ FOC0B = 6 ; Force Output Compare B
-.equ FOC0A = 7 ; Force Output Compare A
-
-; TCNT0 - Timer/Counter0
-.equ TCNT0_0 = 0 ;
-.equ TCNT0_1 = 1 ;
-.equ TCNT0_2 = 2 ;
-.equ TCNT0_3 = 3 ;
-.equ TCNT0_4 = 4 ;
-.equ TCNT0_5 = 5 ;
-.equ TCNT0_6 = 6 ;
-.equ TCNT0_7 = 7 ;
-
-; OCR0A - Timer/Counter0 Output Compare Register
-.equ OCROA_0 = 0 ;
-.equ OCROA_1 = 1 ;
-.equ OCROA_2 = 2 ;
-.equ OCROA_3 = 3 ;
-.equ OCROA_4 = 4 ;
-.equ OCROA_5 = 5 ;
-.equ OCROA_6 = 6 ;
-.equ OCROA_7 = 7 ;
-
-; OCR0B - Timer/Counter0 Output Compare Register
-.equ OCR0B_0 = 0 ;
-.equ OCR0B_1 = 1 ;
-.equ OCR0B_2 = 2 ;
-.equ OCR0B_3 = 3 ;
-.equ OCR0B_4 = 4 ;
-.equ OCR0B_5 = 5 ;
-.equ OCR0B_6 = 6 ;
-.equ OCR0B_7 = 7 ;
-
-; GTCCR - General Timer/Counter Control Register
-;.equ PSRSYNC = 0 ; Prescaler Reset Timer/Counter1 and Timer/Counter0
-.equ PSR10 = PSRSYNC ; For compatibility
-;.equ TSM = 7 ; Timer/Counter Synchronization Mode
-
-
-; ***** EXTERNAL_INTERRUPT ***********
-; EICRA - External Interrupt Control Register
-.equ ISC00 = 0 ; External Interrupt Sense Control 0 Bit 0
-.equ ISC01 = 1 ; External Interrupt Sense Control 0 Bit 1
-.equ ISC10 = 2 ; External Interrupt Sense Control 1 Bit 0
-.equ ISC11 = 3 ; External Interrupt Sense Control 1 Bit 1
-
-; EIMSK - External Interrupt Mask Register
-.equ INT0 = 0 ; External Interrupt Request 0 Enable
-.equ INT1 = 1 ; External Interrupt Request 1 Enable
-
-; EIFR - External Interrupt Flag Register
-.equ INTF0 = 0 ; External Interrupt Flag 0
-.equ INTF1 = 1 ; External Interrupt Flag 1
-
-; PCMSK2 - Pin Change Mask Register 2
-.equ PCINT16 = 0 ; Pin Change Enable Mask 16
-.equ PCINT17 = 1 ; Pin Change Enable Mask 17
-.equ PCINT18 = 2 ; Pin Change Enable Mask 18
-.equ PCINT19 = 3 ; Pin Change Enable Mask 19
-.equ PCINT20 = 4 ; Pin Change Enable Mask 20
-.equ PCINT21 = 5 ; Pin Change Enable Mask 21
-.equ PCINT22 = 6 ; Pin Change Enable Mask 22
-.equ PCINT23 = 7 ; Pin Change Enable Mask 23
-
-; PCMSK1 - Pin Change Mask Register 1
-.equ PCINT8 = 0 ; Pin Change Enable Mask 8
-.equ PCINT9 = 1 ; Pin Change Enable Mask 9
-.equ PCINT10 = 2 ; Pin Change Enable Mask 10
-.equ PCINT11 = 3 ; Pin Change Enable Mask 11
-.equ PCINT12 = 4 ; Pin Change Enable Mask 12
-.equ PCINT13 = 5 ; Pin Change Enable Mask 13
-.equ PCINT14 = 6 ; Pin Change Enable Mask 14
-
-; PCMSK0 - Pin Change Mask Register 0
-.equ PCINT0 = 0 ; Pin Change Enable Mask 0
-.equ PCINT1 = 1 ; Pin Change Enable Mask 1
-.equ PCINT2 = 2 ; Pin Change Enable Mask 2
-.equ PCINT3 = 3 ; Pin Change Enable Mask 3
-.equ PCINT4 = 4 ; Pin Change Enable Mask 4
-.equ PCINT5 = 5 ; Pin Change Enable Mask 5
-.equ PCINT6 = 6 ; Pin Change Enable Mask 6
-.equ PCINT7 = 7 ; Pin Change Enable Mask 7
-
-; PCIFR - Pin Change Interrupt Flag Register
-.equ PCIF0 = 0 ; Pin Change Interrupt Flag 0
-.equ PCIF1 = 1 ; Pin Change Interrupt Flag 1
-.equ PCIF2 = 2 ; Pin Change Interrupt Flag 2
-
-
-; ***** SPI **************************
-; SPDR - SPI Data Register
-.equ SPDR0 = 0 ; SPI Data Register bit 0
-.equ SPDR1 = 1 ; SPI Data Register bit 1
-.equ SPDR2 = 2 ; SPI Data Register bit 2
-.equ SPDR3 = 3 ; SPI Data Register bit 3
-.equ SPDR4 = 4 ; SPI Data Register bit 4
-.equ SPDR5 = 5 ; SPI Data Register bit 5
-.equ SPDR6 = 6 ; SPI Data Register bit 6
-.equ SPDR7 = 7 ; SPI Data Register bit 7
-
-; SPSR - SPI Status Register
-.equ SPI2X = 0 ; Double SPI Speed Bit
-.equ WCOL = 6 ; Write Collision Flag
-.equ SPIF = 7 ; SPI Interrupt Flag
-
-; SPCR - SPI Control Register
-.equ SPR0 = 0 ; SPI Clock Rate Select 0
-.equ SPR1 = 1 ; SPI Clock Rate Select 1
-.equ CPHA = 2 ; Clock Phase
-.equ CPOL = 3 ; Clock polarity
-.equ MSTR = 4 ; Master/Slave Select
-.equ DORD = 5 ; Data Order
-.equ SPE = 6 ; SPI Enable
-.equ SPIE = 7 ; SPI Interrupt Enable
-
-
-; ***** CPU **************************
-; SREG - Status Register
-.equ SREG_C = 0 ; Carry Flag
-.equ SREG_Z = 1 ; Zero Flag
-.equ SREG_N = 2 ; Negative Flag
-.equ SREG_V = 3 ; Two's Complement Overflow Flag
-.equ SREG_S = 4 ; Sign Bit
-.equ SREG_H = 5 ; Half Carry Flag
-.equ SREG_T = 6 ; Bit Copy Storage
-.equ SREG_I = 7 ; Global Interrupt Enable
-
-; OSCCAL - Oscillator Calibration Value
-.equ CAL0 = 0 ; Oscillator Calibration Value Bit0
-.equ CAL1 = 1 ; Oscillator Calibration Value Bit1
-.equ CAL2 = 2 ; Oscillator Calibration Value Bit2
-.equ CAL3 = 3 ; Oscillator Calibration Value Bit3
-.equ CAL4 = 4 ; Oscillator Calibration Value Bit4
-.equ CAL5 = 5 ; Oscillator Calibration Value Bit5
-.equ CAL6 = 6 ; Oscillator Calibration Value Bit6
-.equ CAL7 = 7 ; Oscillator Calibration Value Bit7
-
-; CLKPR - Clock Prescale Register
-.equ CLKPS0 = 0 ; Clock Prescaler Select Bit 0
-.equ CLKPS1 = 1 ; Clock Prescaler Select Bit 1
-.equ CLKPS2 = 2 ; Clock Prescaler Select Bit 2
-.equ CLKPS3 = 3 ; Clock Prescaler Select Bit 3
-.equ CLKPCE = 7 ; Clock Prescaler Change Enable
-
-; SPMCSR - Store Program Memory Control Register
-.equ SELFPRGEN = 0 ; Self Programming Enable
-.equ PGERS = 1 ; Page Erase
-.equ PGWRT = 2 ; Page Write
-.equ BLBSET = 3 ; Boot Lock Bit Set
-.equ RWWSRE = 4 ; Read-While-Write section read enable
-.equ RWWSB = 6 ; Read-While-Write Section Busy
-.equ SPMIE = 7 ; SPM Interrupt Enable
-
-; MCUCR - MCU Control Register
-.equ IVCE = 0 ;
-.equ IVSEL = 1 ;
-.equ PUD = 4 ;
-
-; MCUSR - MCU Status Register
-.equ PORF = 0 ; Power-on reset flag
-.equ EXTRF = 1 ; External Reset Flag
-.equ EXTREF = EXTRF ; For compatibility
-.equ BORF = 2 ; Brown-out Reset Flag
-.equ WDRF = 3 ; Watchdog Reset Flag
-
-; SMCR -
-.equ SE = 0 ;
-.equ SM0 = 1 ;
-.equ SM1 = 2 ;
-.equ SM2 = 3 ;
-
-; GPIOR2 - General Purpose I/O Register 2
-.equ GPIOR20 = 0 ;
-.equ GPIOR21 = 1 ;
-.equ GPIOR22 = 2 ;
-.equ GPIOR23 = 3 ;
-.equ GPIOR24 = 4 ;
-.equ GPIOR25 = 5 ;
-.equ GPIOR26 = 6 ;
-.equ GPIOR27 = 7 ;
-
-; GPIOR1 - General Purpose I/O Register 1
-.equ GPIOR10 = 0 ;
-.equ GPIOR11 = 1 ;
-.equ GPIOR12 = 2 ;
-.equ GPIOR13 = 3 ;
-.equ GPIOR14 = 4 ;
-.equ GPIOR15 = 5 ;
-.equ GPIOR16 = 6 ;
-.equ GPIOR17 = 7 ;
-
-; GPIOR0 - General Purpose I/O Register 0
-.equ GPIOR00 = 0 ;
-.equ GPIOR01 = 1 ;
-.equ GPIOR02 = 2 ;
-.equ GPIOR03 = 3 ;
-.equ GPIOR04 = 4 ;
-.equ GPIOR05 = 5 ;
-.equ GPIOR06 = 6 ;
-.equ GPIOR07 = 7 ;
-
-; PRR - Power Reduction Register
-.equ PRADC = 0 ; Power Reduction ADC
-.equ PRUSART0 = 1 ; Power Reduction USART
-.equ PRSPI = 2 ; Power Reduction Serial Peripheral Interface
-.equ PRTIM1 = 3 ; Power Reduction Timer/Counter1
-.equ PRTIM0 = 5 ; Power Reduction Timer/Counter0
-.equ PRTIM2 = 6 ; Power Reduction Timer/Counter2
-.equ PRTWI = 7 ; Power Reduction TWI
-
-; PCICR -
-.equ PCIE0 = 0 ;
-.equ PCIE1 = 1 ;
-.equ PCIE2 = 2 ;
-
-
-; ***** WATCHDOG *********************
-; WDTCSR - Watchdog Timer Control Register
-.equ WDP0 = 0 ; Watch Dog Timer Prescaler bit 0
-.equ WDP1 = 1 ; Watch Dog Timer Prescaler bit 1
-.equ WDP2 = 2 ; Watch Dog Timer Prescaler bit 2
-.equ WDE = 3 ; Watch Dog Enable
-.equ WDCE = 4 ; Watchdog Change Enable
-.equ WDP3 = 5 ; Watchdog Timer Prescaler Bit 3
-.equ WDIE = 6 ; Watchdog Timeout Interrupt Enable
-.equ WDIF = 7 ; Watchdog Timeout Interrupt Flag
-
-
-; ***** EEPROM ***********************
-; EEARL - EEPROM Address Register Low Byte
-.equ EEAR0 = 0 ; EEPROM Read/Write Access Bit 0
-.equ EEAR1 = 1 ; EEPROM Read/Write Access Bit 1
-.equ EEAR2 = 2 ; EEPROM Read/Write Access Bit 2
-.equ EEAR3 = 3 ; EEPROM Read/Write Access Bit 3
-.equ EEAR4 = 4 ; EEPROM Read/Write Access Bit 4
-.equ EEAR5 = 5 ; EEPROM Read/Write Access Bit 5
-.equ EEAR6 = 6 ; EEPROM Read/Write Access Bit 6
-.equ EEAR7 = 7 ; EEPROM Read/Write Access Bit 7
-
-; EEARH - EEPROM Address Register High Byte
-.equ EEAR8 = 0 ; EEPROM Read/Write Access Bit 0
-
-; EEDR - EEPROM Data Register
-.equ EEDR0 = 0 ; EEPROM Data Register bit 0
-.equ EEDR1 = 1 ; EEPROM Data Register bit 1
-.equ EEDR2 = 2 ; EEPROM Data Register bit 2
-.equ EEDR3 = 3 ; EEPROM Data Register bit 3
-.equ EEDR4 = 4 ; EEPROM Data Register bit 4
-.equ EEDR5 = 5 ; EEPROM Data Register bit 5
-.equ EEDR6 = 6 ; EEPROM Data Register bit 6
-.equ EEDR7 = 7 ; EEPROM Data Register bit 7
-
-; EECR - EEPROM Control Register
-.equ EERE = 0 ; EEPROM Read Enable
-.equ EEPE = 1 ; EEPROM Write Enable
-.equ EEMPE = 2 ; EEPROM Master Write Enable
-.equ EERIE = 3 ; EEPROM Ready Interrupt Enable
-.equ EEPM0 = 4 ; EEPROM Programming Mode Bit 0
-.equ EEPM1 = 5 ; EEPROM Programming Mode Bit 1
-
-
-
-; ***** LOCKSBITS ********************************************************
-.equ LB1 = 0 ; Lock bit
-.equ LB2 = 1 ; Lock bit
-.equ BLB01 = 2 ; Boot Lock bit
-.equ BLB02 = 3 ; Boot Lock bit
-.equ BLB11 = 4 ; Boot lock bit
-.equ BLB12 = 5 ; Boot lock bit
-
-
-; ***** FUSES ************************************************************
-; LOW fuse bits
-.equ CKSEL0 = 0 ; Select Clock Source
-.equ CKSEL1 = 1 ; Select Clock Source
-.equ CKSEL2 = 2 ; Select Clock Source
-.equ CKSEL3 = 3 ; Select Clock Source
-.equ SUT0 = 4 ; Select start-up time
-.equ SUT1 = 5 ; Select start-up time
-.equ CKOUT = 6 ; Clock output
-.equ CKDIV8 = 7 ; Divide clock by 8
-
-; HIGH fuse bits
-.equ BODLEVEL0 = 0 ; Brown-out Detector trigger level
-.equ BODLEVEL1 = 1 ; Brown-out Detector trigger level
-.equ BODLEVEL2 = 2 ; Brown-out Detector trigger level
-.equ EESAVE = 3 ; EEPROM memory is preserved through chip erase
-.equ WDTON = 4 ; Watchdog Timer Always On
-.equ SPIEN = 5 ; Enable Serial programming and Data Downloading
-.equ DWEN = 6 ; debugWIRE Enable
-.equ RSTDISBL = 7 ; External reset disable
-
-; EXTENDED fuse bits
-.equ BOOTRST = 0 ; Select reset vector
-.equ BOOTSZ0 = 1 ; Select boot size
-.equ BOOTSZ1 = 2 ; Select boot size
-
-
-
-; ***** CPU REGISTER DEFINITIONS *****************************************
-.def XH = r27
-.def XL = r26
-.def YH = r29
-.def YL = r28
-.def ZH = r31
-.def ZL = r30
-
-
-
-; ***** DATA MEMORY DECLARATIONS *****************************************
-.equ FLASHEND = 0x1fff ; Note: Word address
-.equ IOEND = 0x00ff
-.equ SRAM_START = 0x0100
-.equ SRAM_SIZE = 1024
-.equ RAMEND = 0x04ff
-.equ XRAMEND = 0x0000
-.equ E2END = 0x01ff
-.equ EEPROMEND = 0x01ff
-.equ EEADRBITS = 9
-; #pragma AVRPART MEMORY PROG_FLASH 16384
-; #pragma AVRPART MEMORY EEPROM 512
-; #pragma AVRPART MEMORY INT_SRAM SIZE 1024
-; #pragma AVRPART MEMORY INT_SRAM START_ADDR 0x100
-
-
-
-; ***** BOOTLOADER DECLARATIONS ******************************************
-.equ NRWW_START_ADDR = 0x1c00
-.equ NRWW_STOP_ADDR = 0x1fff
-.equ RWW_START_ADDR = 0x0
-.equ RWW_STOP_ADDR = 0x1bff
-.equ PAGESIZE = 64
-.equ FIRSTBOOTSTART = 0x1f80
-.equ SECONDBOOTSTART = 0x1f00
-.equ THIRDBOOTSTART = 0x1e00
-.equ FOURTHBOOTSTART = 0x1c00
-.equ SMALLBOOTSTART = FIRSTBOOTSTART
-.equ LARGEBOOTSTART = FOURTHBOOTSTART
-
-
-
-; ***** INTERRUPT VECTORS ************************************************
-.equ INT0addr = 0x0002 ; External Interrupt Request 0
-.equ INT1addr = 0x0004 ; External Interrupt Request 1
-.equ PCI0addr = 0x0006 ; Pin Change Interrupt Request 0
-.equ PCI1addr = 0x0008 ; Pin Change Interrupt Request 0
-.equ PCI2addr = 0x000a ; Pin Change Interrupt Request 1
-.equ WDTaddr = 0x000c ; Watchdog Time-out Interrupt
-.equ OC2Aaddr = 0x000e ; Timer/Counter2 Compare Match A
-.equ OC2Baddr = 0x0010 ; Timer/Counter2 Compare Match A
-.equ OVF2addr = 0x0012 ; Timer/Counter2 Overflow
-.equ ICP1addr = 0x0014 ; Timer/Counter1 Capture Event
-.equ OC1Aaddr = 0x0016 ; Timer/Counter1 Compare Match A
-.equ OC1Baddr = 0x0018 ; Timer/Counter1 Compare Match B
-.equ OVF1addr = 0x001a ; Timer/Counter1 Overflow
-.equ OC0Aaddr = 0x001c ; TimerCounter0 Compare Match A
-.equ OC0Baddr = 0x001e ; TimerCounter0 Compare Match B
-.equ OVF0addr = 0x0020 ; Timer/Couner0 Overflow
-.equ SPIaddr = 0x0022 ; SPI Serial Transfer Complete
-.equ URXCaddr = 0x0024 ; USART Rx Complete
-.equ UDREaddr = 0x0026 ; USART, Data Register Empty
-.equ UTXCaddr = 0x0028 ; USART Tx Complete
-.equ ADCCaddr = 0x002a ; ADC Conversion Complete
-.equ ERDYaddr = 0x002c ; EEPROM Ready
-.equ ACIaddr = 0x002e ; Analog Comparator
-.equ TWIaddr = 0x0030 ; Two-wire Serial Interface
-.equ SPMRaddr = 0x0032 ; Store Program Memory Read
-
-.equ INT_VECTORS_SIZE = 52 ; size in words
-
-; #endif /* _M168DEF_INC_ */
-
-; ***** END OF FILE ******************************************************
--- a/macros.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,23 +0,0 @@
-; XXX: stupid thing won't parse, and it's right from the README example...
-; .ifndef _MACROS_INC_
-; .define _MACROS_INC_
-
-;; Store to memory address
-.macro poke
- .message "No parameters"
-.endm
-
-.macro poke_i_8_i
- ldi @1, @2
- sts @0, @1
-.endm
-
-.macro poke_i_16_i
- ldi @1, low(@3)
- sts @0+0, @1
-
- ldi @2, high(@3)
- sts @0+1, @2
-.endm
-
-; .endif
--- a/matrix.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,461 +0,0 @@
-;; LED Matrix driver
-;; vim: set ft=avr:
-
-.dseg
-;; I/O addresses
-; Control port
-.set MATRIX_DDR = DDRB
-.set MATRIX_PORT = PORTB
-
-; Pin for matrix driver Output Enable
-.set MATRIX_OE = PORTB1 ; Output Enable, active low, externally pulled high
-
-;; Matrix properties
-; Matrix width in columns
-.set MATRIX_COLS = 8 ; physical columns
-
-; Framebuffer width in columns
-.set MATRIX_BUF_COLS = 16 ; framebuffer columns
-
-;; SPI addresses
-; row drivers (8 bits)
-.set MATRIX_SPI_ROW = 0 ; row mask source
-
-; column sinks (8 bits)
-.set MATRIX_SPI_COL = 1 ; column scan sink
-
-;; Matrix state
-; Matrix framebuffer
-; this holds the columns data as a 1 byte bitmask of row data per column (8 bits -> 8 rows)
-matrix_colbuf: .byte MATRIX_BUF_COLS ; framebuffer (row data by column)
-
-; Column scan bit
-; in the matrix refresh loop, we push out each column's row data in turn
-; this bit tracks the currently refreshing column
-matrix_colbit: .byte 1 ; column scan bit
-
-; Matrix viewport offset
-; the visible matrix data is taken directly from the framebuffer, but it can be taken at an arbitrary offset
-; this determines the starting offset for the visible viewport's left edge from the start of the framebuffer in columns
-matrix_colshift: .byte 1 ; viewport left column offset
-
-;; Text
-; Maximum length of message
-.set TEXT_MAXLENGTH = 64
-
-; Scrolling speed (kiloticks per frame)
-.set TEXT_SPEED = 1
-
-text_buffer: .byte TEXT_MAXLENGTH ; display message buffer
-text_offset: .byte 1 ; current offset in text
-
-.cseg
-
-;; Normalize the outputs, enable the matrix, and set up buffers
-Matrix_Init:
- ; Setup ENable port
- sbi MATRIX_PORT, MATRIX_OE ; high -> disabled
- sbi MATRIX_DDR, MATRIX_OE ; out
-
- ; blank hardware
- ldi r16, 0
-
- sts spi_outbuf + 0, r16 ; column sinks
- sts spi_outbuf + 1, r16 ; row drivers
-
- ; write out
- rcall SPI_SendRecv
-
- ; enable
- cbi MATRIX_PORT, MATRIX_OE ; low -> enabled
-
- ; init buffers
- ldi r16, 0b1
- sts matrix_colbit, r16
-
- ldi r16, 0
- sts matrix_colshift, r16
-
- ldi r16, 0
- ldi r17, MATRIX_BUF_COLS
- ldi YL, low(matrix_colbuf)
- ldi YH, high(matrix_colbuf)
-
-m_init_mzero:
- st Y+, r16
-
- ; loop until zero
- dec r17
- brne m_init_mzero
-
- ; Use Timer0, 32k cycles -> 500Hz scan rate
- ldi r16, 32
- rcall Timer0_Start
-
- ; done
- ret
-
-;; Scan the matrix's next column from the viewport
-;; Interrupt-driven
-Matrix_ScanCol:
- ; Save registers
- push r16
- push r17
-
- ; Column bit
- ; load
- lds r16, matrix_colbit
-
- ; start packet
- cbi SPI_PORT, SPI_SS
-
- ; output single column-enable bit
- out SPDR, r16
-
- ; Compute col index
- ldi r17, 0
-
-m_sc_colidx:
- ; shift
- lsr r16
-
- ; done if we shifted the bit out
- brcs m_sc_row
-
- ; count shifts
- inc r17
- rjmp m_sc_colidx
-
-m_sc_row:
- ; Column shift
- ; load
- lds r16, matrix_colshift
-
- ; add to col index
- add r17, r16
-
- ; Row mask
- ; base
- ldi XL, low(matrix_colbuf)
- ldi XH, high(matrix_colbuf)
-
- ; offset
- ldi r16, 0
-
- add XL, r17
- adc XH, r16
-
- ; load
- ld r16, X
-
- ; output full row-enable bitmask
- rcall SPI_Wait
- out SPDR, r16
-
- ; Update col bit
- lds r16, matrix_colbit
-
- ; shift left
- lsl r16
- brcc m_sc_colout
-
- ; overflow, take bit from C
- rol r16
-
-m_sc_colout:
- ; store
- sts matrix_colbit, r16
-
- ; End of packet
- rcall SPI_Wait
- sbi SPI_PORT, SPI_SS
-
- ; Done
- pop r17
- pop r16
-
- ret
-
-;; Scan the matrix once in one go
-;; XXX: doesn't support colshift
-Matrix_ScanFull:
- ; Row index
- ldi ZL, low(matrix_colbuf)
- ldi ZH, high(matrix_colbuf)
-
- ; Column bit
- ldi r25, 0
- sec ; set C
-
-m_pulse_col:
- ; rotate bit left from C
- rol r25
-
- ; overflow
- brcs m_pulse_end
-
- ; store in output buffer
- sts spi_outbuf + 1, r25
-
- ; Row mask
- ld r16, Z+
-
- sts spi_outbuf + 0, r16
-
- ; Display
- rcall SPI_SendRecv
-
- ; Next column
- rjmp m_pulse_col
-
-m_pulse_end:
- ; Done
- ret
-
-;; Reset the viewport to the start (left edge) of the framebuffer
-Matrix_ShiftZero:
- ; Constant offset
- ldi r16, 0
-
- ; Set
- rjmp Matrix_ShiftSet
-
-;; Shift the viewport one column to the left in the framebuffer, looping around to the end of the framebuffer
-; This moves the visible output one column to the right
-Matrix_ShiftLeft:
- ; Decrement-loop current value
- ; current value
- lds r16, matrix_colshift
-
- ; shift window left
- dec r16
-
- ; test for underflow (MSB/N set) -> don't skip reset
- brpl Matrix_ShiftSet
-
- ; reset window to right edge
- ldi r16, MATRIX_BUF_COLS - MATRIX_COLS
-
- ; Set
- rjmp Matrix_ShiftSet
-
-;; Shift the viewport one column to the right in the framebuffer, looping around to the start of the FB
-; This moves the visible output one column to the left
-Matrix_ShiftRight:
- ; Increment-loop current value
- ; current value
- lds r16, matrix_colshift
-
- ; shift window right
- inc r16
-
- ; test for overflow -> don't skip reset
- cpi r16, MATRIX_BUF_COLS - MATRIX_COLS
- brlt Matrix_ShiftSet
-
- ; reset window to left edge
- ldi r16, 0
-
- ; Set
- rjmp Matrix_ShiftSet
-
-;; Set the matrix viewport offset
-;; Input: r16
-Matrix_ShiftSet:
- ; store new value
- sts matrix_colshift, r16
-
- ; done
- ret
-
-;; Rewinds the currently visible viewport to the beginning of the framebuffer
-; This copies the currently visible viewport data to the beginning of the framebuffer and resets the offset
-Matrix_ShiftRewind:
- ; current view offset
- ldi XL, low(matrix_colbuf)
- ldi XH, high(matrix_colbuf)
-
- ; offset
- lds r16, matrix_colshift
-
- ; add
- ldi r17, 0
- add XL, r16
- adc XH, r17
-
- ; start of framebuffer
- ldi YL, low(matrix_colbuf + 0)
- ldi YH, high(matrix_colbuf + 0)
-
- ; viewport width
- ldi r17, MATRIX_COLS
-
-matrix_shiftrew_loop:
- ; copy
- ld r16, X+
- st Y+, r16
-
- ; count
- dec r17
- brne matrix_shiftrew_loop
-
- ; done, reset offset
- rjmp MAtrix_ShiftZero
-
-
-;; Load a NUL-terminated ASCII string from PGM into the text buffer
-; Input: Z - Address of NUL-terminated ASCII string in PGM
-Text_LoadString:
- ; Setup
- ; storage buffer
- ldi YL, low(text_buffer)
- ldi YH, high(text_buffer)
-
- ; max. length
- ldi r18, TEXT_MAXLENGTH
-
-text_loads_loop:
- ; Test max length
- ; count and check for overflow
- dec r18
- brne text_loads_char
-
- ; Load char
- ; force NUL
- ldi r16, 0x00
-
-text_loads_char:
- ; load next char
- lpm r16, Z+
-
-text_loads_store:
- ; Store and test NUL
- ; store it
- st Y+, r16
-
- ; test for NUL
- tst r16
- brne text_loads_loop
-
- ; Update scroll offset
- ; reset offset
- ldi r17, 0
- sts text_offset, r17
-
- ; done
- ret
-
-;; Shows the loaded string of ASCII text on the display, scrolling it horizontally
-; Uses font.inc for rendering
-; XXX: uses blocking timer sleeps and doesn't return until done
-Text_ShowString:
- ; Load initial char
- ldi XL, low(text_buffer + 0)
- ldi XH, high(text_buffer + 0)
-
- ; load char
- ld r16, X+
- push XL
- push XH
-
- ; one column spacing
- ldi YL, low(matrix_colbuf + 1)
- ldi YH, high(matrix_colbuf + 1)
-
- ; render to framebuffer
- rcall Font_Render
-
- ; reset viewport
- rcall Matrix_ShiftZero
-
- ; Load next char
-text_shows_next:
- ; next char
- pop XH
- pop XL
- ld r16, X+
- push XL
- push XH
-
- ; test NUL
- tst r16
- breq text_shows_end
-
- ; offscreen
- ldi YL, low(matrix_colbuf + 1 + 6 + 1)
- ldi YH, high(matrix_colbuf + 1 + 6 + 1)
-
- ; render
- rcall Font_Render
-
- ; Animate to next char
- ldi r20, 7
-
-text_shows_animloop:
- ; sleep
- ldi XH, high(TEXT_SPEED * 1024)
- ldi XL, low(TEXT_SPEED * 1024)
-
- rcall Timer_Sleep
-
- ; shift
- rcall Matrix_ShiftRight
-
- ; count
- dec r20
- brne text_shows_animloop
-
- ; Rewind to next char
- rcall Matrix_ShiftRewind
-
- sbi PIND, PIND7
-
- ; load next char and animate it in
- rjmp text_shows_next
-
-text_shows_end:
- ; Done
- pop XH
- pop XL
-
-
- ; Clear second frame
- ldi YL, low(matrix_colbuf + 16)
- ldi YH, high(matrix_colbuf + 16)
- ldi r16, MATRIX_COLS
- ldi r17, 0
-
-text_shows_end2:
- st -Y, r17
-
- dec r16
- brne text_shows_end2
-
- ; Blink
-text_shows_end3:
- ; on
- ldi r16, 0
- rcall Matrix_ShiftSet
-
- ; sleep
- ldi XH, high(TEXT_SPEED * 6 * 1024)
- ldi XL, low(TEXT_SPEED * 6 * 1024)
-
- rcall Timer_Sleep
-
- ; off
- ldi r16, 8
- rcall Matrix_ShiftSet
-
- ; sleep
- ldi XH, high(TEXT_SPEED * 6 * 1024)
- ldi XL, low(TEXT_SPEED * 6 * 1024)
-
- rcall Timer_Sleep
-
- ; loop
- rjmp text_shows_end3
-
- ; XXX: end
- ret
-
--- a/matrix.s Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,255 +0,0 @@
-;; vim: set ft=avr:
-
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-
-;; Interrupt Vector
-.org 0x00
- rjmp init
-
-.org OC1Aaddr
- ; Timer/Counter1 Compare Output A
- rjmp Timer_OC1A
-
-.org OC0Aaddr
- ; Timer/Counter0 Compare Output A
- rjmp Timer_OC0A
-
-.org SPIaddr
- rjmp SPI_Interrupt
-
-
-cseg0: .org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; SPI
-.include "spi.inc"
-
-;; Matrix
-.include "matrix.inc"
-
-;; Timer
-.set TIMER0_CB_A = Matrix_ScanCol
-
-.include "timer.inc"
-
-;; Utils
-.include "delay.inc"
-
-;; Font rendering
-.include "font.inc"
-
-;; Scan through each pixel
-Main_ScanRaw:
- ; init
- ldi r18, 1
- ldi r19, 1
-
-scan_loop:
- ; write out to SPI
- sts spi_outbuf + 0, r18 ; rows
- sts spi_outbuf + 1, r19 ; columns
-
- rcall SPI_SendRecv
-
- ; delay
- ldi r20, 5 ; ~4M cycles
- rcall VarDelay
-
- ; cols
- lsl r19 ; next col
- brcc scan_loop ; refresh if we didn't overflow
-
- rol r19 ; shift back from C into r21.0
-
- ; rows
- lsl r18 ; next row
- brcc scan_loop ; refresh if we didn't overflow
-
- rol r18 ; shift back from C into r20.0
-
- ; one scan completed
- ret
-
-;; Scan with test pattern
-Main_ScanTest:
- ; Generate pattern
- ; end of buffer
- ldi r17, MATRIX_BUF_COLS
- ldi XL, low(matrix_colbuf + MATRIX_BUF_COLS)
- ldi XH, high(matrix_colbuf + MATRIX_BUF_COLS)
-
- ; bit pattern
- ldi r16, 0b11
-
-st_loop:
- ; put, pre-decrement
- st -X, r16
-
- ; flip
- rol r16
-
- ; loop until zero
- dec r17
- brne st_loop
-
-st_animate:
- ; Animate
- ; shift right
- rcall Matrix_ShiftLeft
-
- ; wait for X/16th of a second
- ldi XH, high(8 * 1024)
- ldi XL, low(8 * 1024)
-
- rcall Timer_Sleep
-
- ; loop
- rjmp st_animate
-
-
-;; Display device code memory
-Main_ScanCode:
- ; Code start
- ldi ZL, low(cseg0 * 2) ; word addr
- ldi ZH, high(cseg0 * 2) ; word addr
-
- ; Pause refresh
- cli
-
- ; Load initial frame
- ; to first frame, starting from right edge
- ldi r17, 8
- ldi XL, low(matrix_colbuf + 16)
- ldi XH, high(matrix_colbuf + 16)
-
-sc_load_initial:
- ; one byte
- lpm r16, Z+
- st -X, r16
-
- ; loop until zero
- dec r17
- brne sc_load_initial
-
- ; the first ShiftLeft below will jump to the end of the framebuffer
-
-sc_next:
- ; Show this frame
- rcall Matrix_ShiftLeft
-
- ; Load next frame
- ldi r17, 8
- ldi XL, low(matrix_colbuf + 8)
- ldi XH, high(matrix_colbuf + 8)
-
-sc_load_next:
- ; one byte
- lpm r16, Z+
- st -X, r16
-
- ; loop until zero
- dec r17
- brne sc_load_next
-
- ; Enable refresh
- sei
-
- ; Animate from this -> next frame
- ldi r17, 8 ; 8 columns
-
-sc_anim:
- ; wait for X/16th of a second
- ldi XH, high(2 * 1024)
- ldi XL, low(2 * 1024)
-
- rcall Timer_Sleep
-
- ; shift
- rcall Matrix_ShiftLeft
-
- ; loop until zero
- dec r17
- brne sc_anim
-
- ; Pause refresh
- cli
-
- ; Move next -> this
- ldi r17, 8
- ldi XL, low(matrix_colbuf + 16)
- ldi XH, high(matrix_colbuf + 16)
- ldi YL, low(matrix_colbuf + 8)
- ldi YH, high(matrix_colbuf + 8)
-
-sc_move_this:
- ; one byte
- ld r16, -Y
- st -X, r16
-
- ; loop until zero
- dec r17
- brne sc_move_this
-
-sbi PIND, PIND7
-
- ; Load next frame, and animate
- rjmp sc_next
-
-Main_ScanText:
-
- ; Constants
-stxt_message: ; text to render
- .db 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x20, 0x77, 0x6f, 0x72, 0x6c, 0x64, 0x21, 0x0 ; 'hello world!'
-
- ; Load into buffer
- ldi ZL, low(stxt_message * 2)
- ldi ZH, high(stxt_message * 2)
-
- rcall Text_LoadString
-
-sbi PORTD, PIND7
-
- ; Display
- rcall Text_ShowString
-
- ; Done
- ret
-
-Main:
-init:
- ; Stack
- ldi r16, high(RAMEND)
- ldi r17, low(RAMEND)
- out SPH, r16
- out SPL, r17
-
- ; Enable interrupts
- sei
-
-; DEBUG
-sbi DDRD, PORTD7
-cbi PORTD, PORTD7
-
- ; Timer
- rcall Timer_Init
-
- ; SPI
- rcall SPI_Init
-
- ; Matrix
- rcall Matrix_Init
-
- ; Run
- ; rcall Main_ScanRaw
- ; rcall Main_ScanTest
- ; rcall Main_ScanCode
- rcall Main_ScanText
-
-end:
- rjmp end
-
--- a/spi.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,144 +0,0 @@
-;; vim: filetype=avr
-;;
-;; SPI interface control and use
-;;
-
-;; I/O Port
-.equ SPI_DDR = DDRB
-.equ SPI_PORT = PORTB
-.equ SPI_SCK = PORTB5
-.equ SPI_MISO = PORTB4
-.equ SPI_MOSI = PORTB3
-.equ SPI_SS = PORTB2
-
-;; Internal status flags
-.equ SPI_FLAGS = GPIOR0
-.equ SPI_BUSY = 0
-
-;; Settings
-.set SPI_DORD = 0 ; word order
-.set SPI_CPOL = 0 ; clock polarity
-.set SPI_CPHA = 0 ; clock phase
-.set SPI_CLOCK = 0b01 ; clock speed
-
-;; Internal state
-; Number of in/out bytes
-.set SPI_BUFLEN = 2
-
-.dseg
-; Buffer for incoming frames
-spi_inbuf: .byte SPI_BUFLEN
-
-; Buffer for outgoing frames
-spi_outbuf: .byte SPI_BUFLEN
-
-.cseg
-
-;; Initialize SPI subsystem for master operation
-SPI_Init:
- ; Set modes
- sbi SPI_DDR, SPI_SCK ; Out
- sbi SPI_DDR, SPI_MOSI ; Out
- sbi SPI_DDR, SPI_SS ; Out
-
- ; Drive SS high (off)
- sbi SPI_PORT, SPI_SS
-
- ; Set control mode
- ; XXX: Enable interrupt
- ; Enable SPI
- ; MSB first
- ; Master mode
- ; Polarity/phase: Mode 0 (sample on rising edge)
- ; Clock rate 1/16
- ldi r16, (0 << SPIE) | (1 << SPE) | (SPI_DORD << DORD) | (1 << MSTR) | (SPI_CPOL << CPOL) | (SPI_CPHA << CPHA) | (SPI_CLOCK << SPR0)
- out SPCR, r16
-
- ; Flags
- clr r0
- out SPI_FLAGS, r0
-
- ; Start update timer
- ; XXX: also used for ADC
-; ldi r16, 64 ; every 64k cycles
-; rcall Timer0_Start
-
- ; Done
- ret
-
-;; Triggered by Timer0, updates the spi_bufs
-;; Run from timer interrupt context
-SPI_Update:
- ; skip if updating
- sbic SPI_FLAGS, SPI_BUSY
- ret
-
- ;; Continue
- ; XXX: blocks too much?
-
-;; Send/Recv from/to SPI buffers
-SPI_SendRecv:
- ; Flag
- sbi SPI_FLAGS, SPI_BUSY
-
- ; Start of packet
- cbi SPI_PORT, SPI_SS
-
- ; Init buffers
- ldi r16, SPI_BUFLEN
-
- ; send/recv in reverse order
- ldi XL, low(spi_inbuf + SPI_BUFLEN)
- ldi XH, high(spi_inbuf + SPI_BUFLEN)
- ldi YL, low(spi_outbuf + SPI_BUFLEN)
- ldi YH, high(spi_outbuf + SPI_BUFLEN)
-
- ; Write
-spi_sr_next:
- ; load+send tail byte
- ld r1, -Y
- out SPDR, r1
-
- ; Wait
-spi_sr_wait:
- in r1, SPSR
- sbrs r1, SPIF
- rjmp spi_sr_wait
-
- ; Read
- ; XXX: wrong, should be head byte?
- ; read+store tail byte
- in r1, SPDR
- st -X, r1
-
- ; Done?
- dec r16
- brne spi_sr_next ; if nonzero
-
- ; End of packet
- sbi SPI_PORT, SPI_SS
-
- cbi SPI_FLAGS, SPI_BUSY
-
- ; Done
- ret
-
-;; Wait for SPI to be ready for send
-SPI_Wait:
- ; Test
- in r1, SPSR
- sbrs r1, SPIF
- rjmp SPI_Wait
-
- ; Read SPDR to clear SPIF
- in r10, SPDR
-
- ; Done
- ret
-
-;; Service SPI interrupt
-SPI_Interrupt:
- ; XXX: disabled
- reti
-
-
--- a/src/hello-lkm.c Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,484 +0,0 @@
-/*
- * Control the JY-LKM1638 LED display module.
- */
-
-#include <avr/io.h>
-#include <util/delay.h>
-
-#include "stdlib.h"
-
-// XXX
-#include "timer.c"
-
-#define LKM_DDR DDRC
-#define LKM_PORT PORTC
-#define LKM_PIN PINC
-#define LKM_CLK 0
-#define LKM_DIO 1
-#define LKM_STB 2
-
-enum lkm_cmd {
- LKM_CMD_DATA = 0b01000000,
- LKM_CMD_CONTROL = 0b10000000,
- LKM_CMD_ADDRESS = 0b11000000,
-
- LKM_DATA_WRITE = 0b00000000,
- LKM_DATA_READ = 0b00000010,
-
- LKM_DATA_ADDR_AUTO = 0b00000000,
- LKM_DATA_ADDR_FIXED = 0b00000100,
-
- LKM_DATA_TEST_NORMAL = 0b00000000,
- LKM_DATA_TEST_TEST = 0b00001000,
-
- LKM_ADDRESS = 0b00001111,
-
- LKM_CONTROL_INTENSITY = 0b00000111,
- LKM_CONTROL_INTENSITY_MIN = 0b00000000,
- LKM_CONTROL_INTENSITY_MAX = 0b00000111,
-
- LKM_CONTROL_DISPLAY_OFF = 0b00000000,
- LKM_CONTROL_DISPLAY_ON = 0b00001000,
-};
-
-static const uint8_t LKM_DISPLAY_FONT[] = {
- 0b00111111, // 0
- 0b00000110, // 1
- 0b01011011, // 2
- 0b01001111, // 3
- 0b01100110, // 4
- 0b01101101, // 5
- 0b01111101, // 6
- 0b00000111, // 7
- 0b01111111, // 8
- 0b01100111, // 9
- 0b01110111, // A
- 0b01111100, // B
- 0b00111001, // C
- 0b01011110, // D
- 0b01111001, // E
- 0b01110001, // F
-};
-
-enum {
- LKM_DISPLAY_DECIMAL = 0b10000000,
-};
-
-/*
- * XXX: RED/GREEN somehow swapped vs reference; bug in our write code?
- */
-enum {
- LKM_LED_OFF = 0b00,
- LKM_LED_GREEN = 0b01,
- LKM_LED_RED = 0b10,
- LKM_LED_ORANGE = 0b11,
-};
-
-/*
- * Button bitfields.
- *
- * The JY-LKM1638 uses K3
- */
-enum {
- LKM_BUTTON_K1L = 0b00000100,
- LKM_BUTTON_K2L = 0b00000010,
- LKM_BUTTON_K3L = 0b00000001,
-
- LKM_BUTTON_K1H = 0b01000000,
- LKM_BUTTON_K2H = 0b00100000,
- LKM_BUTTON_K3H = 0b00010000,
-};
-
-void lkm_init ()
-{
- // strobe off: high output
- // XXX: should use an external pull-up resistor?
- sbi(&LKM_PORT, LKM_STB);
- sbi(&LKM_DDR, LKM_STB);
-
- // clock low
- sbi(&LKM_DDR, LKM_CLK);
- cbi(&LKM_PORT, LKM_CLK);
-
- // data tri-state
- cbi(&LKM_DDR, LKM_DIO);
- cbi(&LKM_DDR, LKM_DIO);
-}
-
-/*
- * Select the LKM for write.
- */
-void lkm_out ()
-{
- // clock low
- cbi(&LKM_PORT, LKM_CLK);
-
- // data out
- sbi(&LKM_DDR, LKM_DIO);
-
- // select on: low
- cbi(&LKM_PORT, LKM_STB);
-}
-
-/*
- * Select the LKM for read.
- */
-void lkm_in ()
-{
- // data in
- cbi(&LKM_DDR, LKM_DIO);
- cbi(&LKM_PORT, LKM_DIO);
-
- // select on: low
- cbi(&LKM_PORT, LKM_STB);
-
- // clock high
- sbi(&LKM_PORT, LKM_CLK);
-
- // pause
- _delay_us(1);
-}
-
-/*
- * Write out one byte
- */
-void lkm_write (byte b)
-{
- char i;
-
- for (i = 0; i < 8; i++) {
- // clock read: low
- cbi(&LKM_PORT, LKM_CLK);
-
- // set output
- if (b & 1)
- sbi(&LKM_PORT, LKM_DIO);
- else
- cbi(&LKM_PORT, LKM_DIO);
-
- // clock write: high
- sbi(&LKM_PORT, LKM_CLK);
-
- // next bit
- b >>= 1;
- }
-}
-
-/*
- * Read in one byte.
- */
-byte lkm_read ()
-{
- byte b = 0;
- char i;
-
- // XXX: this loop is timing-critical; we must allow the signal to settle betwen clocks
- for (i = 0; i < 8; i++) {
- // next bit
- b >>= 1;
-
- // clock read: low
- cbi(&LKM_PORT, LKM_CLK);
-
- // pause
- _delay_us(1);
-
- // read input
- if (tbi(&LKM_PIN, LKM_DIO))
- b |= 0x80;
-
- // pause
- _delay_us(1);
-
- // clock write: high
- sbi(&LKM_PORT, LKM_CLK);
-
- // pause
- _delay_us(1);
- }
-
- return b;
-}
-
-/*
- * End command.
- */
-void lkm_end ()
-{
- // select off: high
- sbi(&LKM_PORT, LKM_STB);
-
- // tristate data
- cbi(&LKM_DDR, LKM_DIO);
-}
-
-void lkm_cmd (byte cmd)
-{
- lkm_out();
- lkm_write(cmd);
- lkm_end();
-}
-
-void lkm_cmd1 (byte cmd, byte arg)
-{
- lkm_out();
- lkm_write(cmd);
- lkm_write(arg);
- lkm_end();
-}
-
-static inline void lkm_control (byte display, byte intensity)
-{
- lkm_cmd(LKM_CMD_CONTROL
- | (display ? LKM_CONTROL_DISPLAY_ON : LKM_CONTROL_DISPLAY_OFF)
- | (intensity & LKM_CONTROL_INTENSITY)
- );
-}
-
-/*
- * Blank display/LEDs
- */
-static void lkm_clear ()
-{
- char i;
-
- lkm_cmd(LKM_CMD_DATA
- | LKM_DATA_TEST_NORMAL
- | LKM_DATA_ADDR_AUTO
- | LKM_DATA_WRITE
- );
-
- // write out all 16 bytes of 0x00
- lkm_out();
- lkm_write(LKM_CMD_ADDRESS | (0x0) & LKM_ADDRESS);
- for (i = 0; i < 16; i++) {
- lkm_write(0x00);
- }
- lkm_end();
-
-}
-
-/*
- * Set raw output mask for given display 0..7
- */
-static inline void lkm_display (byte display, byte value)
-{
- lkm_cmd(LKM_CMD_DATA
- | LKM_DATA_TEST_NORMAL
- | LKM_DATA_ADDR_AUTO
- | LKM_DATA_WRITE
- );
- lkm_cmd1(LKM_CMD_ADDRESS | ((display * 2 + 0) & LKM_ADDRESS),
- value
- );
-}
-
-/*
- * Set raw output mask for given led 0..7
- */
-static inline void lkm_led (byte led, byte value)
-{
- lkm_cmd(LKM_CMD_DATA
- | LKM_DATA_TEST_NORMAL
- | LKM_DATA_ADDR_AUTO
- | LKM_DATA_WRITE
- );
- lkm_cmd1(LKM_CMD_ADDRESS | ((led * 2 + 1) & LKM_ADDRESS),
- value
- );
-}
-
-/*
- * Set 4-bit hexadecimal output for given display 0..7
- */
-static inline void lkm_display_hex (byte display, byte hex)
-{
- lkm_display(display, LKM_DISPLAY_FONT[hex]);
-}
-
-static inline void lkm_display_dec (byte display, byte dec, byte decimal)
-{
- byte raw;
-
- if (dec < 10)
- raw = LKM_DISPLAY_FONT[dec];
- else
- raw = 0x00;
-
- if (decimal)
- raw |= LKM_DISPLAY_DECIMAL;
-
- lkm_display(display, raw);
-}
-
-/*
- * Read the 8-bit key states
- */
-byte lkm_buttons ()
-{
- byte k3 = 0;
- char i;
-
- lkm_out();
- lkm_write(LKM_CMD_DATA
- | LKM_DATA_TEST_NORMAL
- | LKM_DATA_ADDR_AUTO
- | LKM_DATA_READ
- );
- lkm_in();
- for (i = 0; i < 4; i++) {
- /*
- * The ordering of keys used is weird; it seems to go 04 15 26 37
- */
- k3 |= lkm_read() << i;
-
- /*
- k3 >>= 1;
-
- byte b = lkm_read();
-
- if (b & LKM_BUTTON_K3L)
- k3 |= 0b00001000;
-
- if (b & LKM_BUTTON_K3H)
- k3 |= 0b10000000;
- */
- }
- lkm_end();
-
- return k3;
-}
-
-/*
- * Set 8-bit hexadecimal output on displays n..n+1
- */
-void lkm_display_hh (byte display, byte hex)
-{
- lkm_display_hex(display + 0, ((hex >> 4) & 0xF));
- lkm_display_hex(display + 1, ((hex >> 0) & 0xF));
-}
-
-/*
- * Set 16-bit hexadecimal output on displays 4..7
- */
-void lkm_display_hhhh (short hex)
-{
- lkm_display_hex(7, ((hex >> 0) & 0xF));
- lkm_display_hex(6, ((hex >> 4) & 0xF));
- lkm_display_hex(5, ((hex >> 8) & 0xF));
- lkm_display_hex(4, ((hex >> 12) & 0xF));
-}
-
-/*
- * Set 2-digit decimal output on displays n..n+1
- */
-void lkm_display_dd (byte display, byte dec)
-{
- byte d = dec / 10;
- byte u = dec % 10;
-
- byte c = d / 10;
- d = d % 10;
-
- lkm_display_dec(display + 0, d, c > 1);
- lkm_display_dec(display + 1, u, c > 0);
-}
-
-// debug
-#define DEBUG_DDR DDRB
-#define DEBUG_PORT PORTB
-#define DEBUG_LED 0
-
-int main (void)
-{
- // led_init();
- sbi(&DEBUG_DDR, DEBUG_LED);
-
- timer_init();
- lkm_init();
-
- sei();
-
- // setup display
- lkm_clear();
- lkm_control(LKM_CONTROL_DISPLAY_ON, LKM_CONTROL_INTENSITY_MAX);
-
-/*
- // test
- lkm_led(0, LKM_LED_OFF);
- lkm_led(1, LKM_LED_RED);
- lkm_led(2, LKM_LED_GREEN);
- lkm_led(3, LKM_LED_ORANGE);
-
- return 0;
-*/
-
- // start
- byte channels[4] = { };
- enum channel_state {
- CHANNEL_IDLE = 0,
- CHANNEL_INC,
- CHANNEL_DEC,
- } channel_state[4] = { };
- byte channel_count[4] = { };
- char c;
-
- while (true) {
- // scan input
- byte buttons = lkm_buttons();
-
- for (c = 0; c < 4; c++) {
- enum channel_state state = channel_state[c], next;
- byte count = channel_count[c];
-
- // decode buttons -> state
- if (buttons & 0b1) {
- next = CHANNEL_INC;
- } else if (buttons & 0b10) {
- next = CHANNEL_DEC;
- } else {
- next = CHANNEL_IDLE;
- }
-
- buttons >>= 2;
-
- // feedback
- if (state == CHANNEL_INC || next == CHANNEL_INC)
- lkm_led(c * 2 + 0, LKM_LED_GREEN);
- else if (state == CHANNEL_DEC && next == CHANNEL_DEC)
- lkm_led(c * 2 + 0, LKM_LED_RED);
- else
- lkm_led(c * 2 + 0, LKM_LED_OFF);
-
- if (state == CHANNEL_DEC || next == CHANNEL_DEC)
- lkm_led(c * 2 + 1, LKM_LED_RED);
- else if (state == CHANNEL_INC && next == CHANNEL_INC)
- lkm_led(c * 2 + 1, LKM_LED_GREEN);
- else
- lkm_led(c * 2 + 1, LKM_LED_OFF);
-
- // counts
- if ((channel_state[c] = next) != state)
- channel_count[c] = 0;
- else
- count = ++channel_count[c];
-
- // state transitions
- if (next == CHANNEL_INC && count > 0) {
- channels[c] += count;
- } else if (next == CHANNEL_DEC && count > 0) {
- channels[c] -= count;
- } else if (state == CHANNEL_INC && !count) {
- channels[c] = 0xff;
- } else if (state == CHANNEL_DEC && !count) {
- channels[c] = 0x00;
- }
-
- lkm_display_hh(c * 2, channels[c]);
-
- xbi(&DEBUG_PORT, DEBUG_LED);
- }
-
- timer_sleep(8000);
- }
-}
--- a/src/hello.c Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,213 +0,0 @@
-#include <avr/io.h>
-
-#include "stdlib.h"
-
-// XXX
-#include "timer.c"
-#include "serial.c"
-#include "spi.c"
-#include "led7.c"
-
-static enum state {
- START = '\n',
- CMD_SET = 's',
- CMD_INC = '+',
- CMD_DEC = '-',
- CMD_READ = 'r',
- ARG_CHAR = '0',
- ERROR = '!',
-} state = START, cmd = 0;
-
-static enum {
- CMD_LED_1 = 0,
-} cmd_led = 0;
-
-static char arg_char;
-
-static unsigned char led_state = 0;
-
-int command (enum state cmd)
-{
- switch (cmd) {
- case CMD_SET:
- led_state = arg_char;
-
- return 0;
-
- case CMD_INC:
- if (led_state == 0xff)
- return 1;
-
- led_state++;
- return 0;
-
- case CMD_DEC:
- if (!led_state)
- return 1;
-
- led_state--;
- return 0;
-
- case CMD_READ:
- led_state = spi_rx[1]; // XXX
- return 0;
-
- default:
- return 1;
- }
-}
-
-char input (char c)
-{
- if (c == '\r') {
- char ret = '?';
-
- // command state
- switch (state) {
- case START:
- cmd = 0;
- break;
-
- case CMD_SET:
- case CMD_INC:
- case CMD_DEC:
- break;
-
- case ARG_CHAR:
- break;
-
- case ERROR:
- cmd = 0;
- break;
- }
-
- // command
- if (!cmd) {
- ret = ' ';
- } else if (command(cmd)) {
- ret = '!';
- } else {
- ret = '\n';
- }
-
- // return to START with response
- state = START;
- return ret;
-
- } else if (31 < c && c < 128) {
- // process input char
- switch (state) {
- case START:
- if (c == 's') {
- cmd = CMD_SET;
- state = ARG_CHAR;
- arg_char = 0;
- } else if (c == 'S') {
- cmd = state = CMD_SET;
- arg_char = 255;
- } else if (c == '+') {
- cmd = state = CMD_INC;
- } else if (c == '-') {
- cmd = state = CMD_DEC;
- } else if (c == 'r') {
- cmd = state = CMD_READ;
- } else {
- break;
- }
-
- return state;
- break;
-
- /*
- case CMD_SET:
- if (c == '1') {
- cmd_led = CMD_LED_1;
- state = ARG_CHAR;
- arg_char = 0;
- } else {
- state = ERROR;
- }
-
- break;
- */
- case ARG_CHAR:
- if (c >= '0' && c <= '9') {
- arg_char *= 10;
- arg_char += (c - '0');
- } else {
- break;
- }
-
- return c;
- break;
- }
-
- // reject
- state = ERROR;
- return ERROR;
-
- } else {
- // ignore
- return ' ';
- }
-}
-
-
-#define DEBUG_DDR DDRB
-#define DEBUG_PORT PORTB
-#define DEBUG_LED 0
-
-int main (void)
-{
- led7_init();
- timer_init();
- serial_init();
- spi_init();
-
- // led_init();
- sbi(&DEBUG_DDR, DEBUG_LED);
-
- sei();
-
- // start
- char c;
- unsigned short timeout = 0;
-
- serial_write(state);
-
- while (true) {
- // TODO: SPI timer
- led7_update(led_state);
- spi_update();
-
- // toggle
- if (led_state == 0) {
- timeout = 0;
- cbi(&DEBUG_PORT, DEBUG_LED);
-
- } else if (led_state == 255) {
- timeout = 0;
- sbi(&DEBUG_PORT, DEBUG_LED);
-
- } else {
- // as Hz
- timeout = (16000 / led_state);
- xbi(&DEBUG_PORT, DEBUG_LED);
- }
-
- // sleep
- if (timer_sleep(timeout)) {
- c = '.';
-
- } else if ((c = serial_read())) {
- // got serial data
- c = input(c);
-
- } else {
- c = '?';
- }
-
- // output...
- serial_write(c);
- }
-}
--- a/timer.inc Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,196 +0,0 @@
-;; vim: filetype=avr
-;;
-;; Timer unit control and use
-;;
-
-.equ TIMER_FLAGS = GPIOR0
-
-;; Timer0
-; Compare output mode
-.set TIMER0_COMA = 0b00 ; null
-.set TIMER0_COMB = 0b00 ; null
-
-; Waveform Generation Mode (triplet low/high)
-.set TIMER0_WGML = 0b10 ; CTC
-.set TIMER0_WGMH = 0b0 ; CTC
-
-; Clock Source
-.set TIMER0_CS = 0b101 ; 1/1024
-
-;; Timer1
-; Waveform Generation Mode (nibble low/high)
-.set TIMER1_WGML = 0b00 ; CTC
-.set TIMER1_WGMH = 0b01 ; CTC
-
-; Clock Source
-.set TIMER1_CS = 0b101 ; 1/1024
-
-; Flags
-.equ TIMER1_BUSY = 1
-
-.set SLEEP_MODE = 0b000 ; Idle
-
-Timer_Init:
-Timer0_Init:
- ; OC0A/B disconnected from output
- ; No PWM mode
- ldi r16, (TIMER0_COMA << COM0A0) | (TIMER0_COMB << COM0B0) | (TIMER0_WGML << WGM00)
- out TCCR0A, r16
-
- ; Clear
- ldi r16, 0
- out OCR0A, r16
- out OCR0B, r16
- out TCCR0B, r16
-
- ; Enable compare interrupt
- ldi r16, (1 << OCIE0A)
- sts TIMSK0, r16
-
-Timer1_Init:
- ; OC1A/B disconnected from output
- ; No PWM mode
- poke [TCCR1A, r16, (0b00 << COM1A0) | (0b00 << COM1B0) | (TIMER1_WGML << WGM10)]
-
- ; Clear
- poke [TCCR1B, r16, 0]
- poke [TCCR1C, r16, 0]
-
- ; Enable compare interrupt
- poke [TIMSK1, r16, (1 << OCIE1A)]
-
-Sleep_init:
- ; Select sleep mode
- ; Enable `sleep`
- poke [SMCR, r16, (SLEEP_MODE << SM0) | (1 << SE)]
-
- ; Disable ADC
- poke [SMCR, r16, (1 << PRTWI) | (1 << PRUSART0) | (1 << PRADC)]
-
- ret
-
-;; Timer0 is recurring; this starts it running, and it keeps hitting OC0A periodically
-;; Input: r16 (period, in 1k-cycles)
-Timer0_Start:
- ; Initialize timer
- ; set CTC trigger from r16
- out OCR0A, r16
-
- ; clear counter
- ldi r16, 0
- out TCNT0, r16
-
- ; Start
- ; WGM
- ; Clock Source
- ldi r16, (TIMER0_WGMH << WGM02) | (TIMER0_CS << CS00)
- out TCCR0B, r16
-
- ret
-
-Timer0_Read8:
- in r16, TCNT0
-
- ret
-
-;; Timer0 Compare A interrupt handler
-Timer_OC0A:
- in r0, SREG
-
- ; Run callback
- rcall TIMER0_CB_A
-
- out SREG, r0
- reti
-
-;; Timer1 is one-shot; this starts it running, and it is then stopped once it hits OC1A
-Timer1_Start:
- ; Initialize timer
- poke [TCNT1H, r16, high(0)]
- poke [TCNT1L, r16, low(0)]
-
- ; Set flag
- sbi TIMER_FLAGS, TIMER1_BUSY
-
- ; Start
- ; WGM
- ; Clock Source
- poke [TCCR1B, r16, (TIMER1_WGMH << WGM12) | (TIMER1_CS << CS10)]
-
- ret
-
-Timer1_Stop:
- ; WGM
- ; Clock off
- poke [TCCR1B, r16, (TIMER1_WGMH << WGM12) | (0b00 << CS10)]
-
- ; Clear flag
- cbi TIMER_FLAGS, TIMER1_BUSY
-
- ret
-
-;; Timer1 Compare A interrupt handler
-Timer_OC1A:
- in r0, SREG
-
- ; Stop timer
- rcall Timer1_Stop
-
- out SREG, r0
- reti
-
-;; Prime the timer and sleep for 1s
-Timer_Sleep_1s:
- ; Initialize counter to 16k cycles
- ldi XH, high(16 * 1024)
- ldi XL, low(16 * 1024)
-
- ;; Continue
-
-;; Count to X
-Timer_Sleep:
- ; Set TOP
- sts OCR1AH, XH
- sts OCR1AL, XL
-
- ; Start timer
- rcall Timer1_Start
-
- ; Wait for timer to complete
-_timer1_sleep:
- sleep
-
- sbic TIMER_FLAGS, TIMER1_BUSY
- rjmp _timer1_sleep
-
- ; Done
- ret
-
-;; Update timer for given timeout
-Timer_Update:
- ; Set TOP
- sts OCR1AH, XH
- sts OCR1AL, XL
-
- ; Check timer
- lds YL, TCNT1L
- lds YH, TCNT1H
-
- cp YL, XL
- cpc YH, XH
-
- brlo timer_up_out
-
- ; Update
- ; XXX: figure out a better way to do this...
- ldi r16, 0
- subi XL, 2
- sbc XH, r16
-
- sts TCNT1L, XL
- sts TCNT1H, XH
-
-timer_up_out:
- ; Done
- ret
-
--- a/timer.s Mon Jun 02 18:27:08 2014 +0300
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,68 +0,0 @@
-.nolist
-.include "m168def.inc" ; Same family as 328P
-.list
-
-;; Interrupt Vector
-.org 0x00
- rjmp init
-
-.org OC1Aaddr
- ; Timer/Counter1 Compare Output A
- rjmp Timer_OC1A
-
-.org OC0Aaddr
- ; Timer/Counter0 Compare Output A
- rjmp Timer_OC0A
-
-.org 0x40
-
-;; Syntax
-.include "macros.inc"
-
-;; Timer0 Compare A handler
-Tick:
- ; Toggle
- sbi PIND, PORTD7
-
- ret
-
-;; Timer
-.set TIMER0_CB_A = Tick
-.include "timer.inc"
-
-Main:
-init:
- ; Stack
- ldi r16, high(RAMEND)
- ldi r17, low(RAMEND)
- out SPH, r16
- out SPL, r17
-
- ; Enable interrupts
- sei
-
- ; Turn off LED7
- sbi DDRB, PORTB1
- sbi PORTB, PORTB1
-
-
- ; DEBUG
- sbi DDRD, PORTD7
- cbi PORTD, PORTD7
-
- sbi DDRD, PORTD6
- sbi DDRD, PORTD5
-
-
- ; Timer
- ; setup
- rcall Timer0_Init
-
- ; run with 255k cycles
- ldi r16, 255
- rcall Timer0_Start
-
-loop:
- ; Run timer
- rjmp loop
-