;=========================================================================== ; ; File Name: h2o_ion.asm ; ; Original Author: Sean Quinn ; ; Project: H2O Ion Experiment ; ; Description: Project for - ; ATMEL ATTiny2313 Processor: ; FLASH: 2K ; SRAM: 128 Bytes ; EEPROM:128 Bytes ; Signature Bytes: 0x1E 0x91 0x0A ; ; ; ; Atmel AT-Tiny 2313 ; .----------------------------------, ; | | ; --( 1)| PA2 (RESET/dW) VCC |(20)-- ; | | ; ELECTRODE_1 --( 2)| PD0 (RxD) (SCK) PB7 |(19)-- ; | | ; ELECTRODE_3 --( 3)| PD1 (TxD) (MISO) PB6 |(18)-- ; | | ; --( 4)| PA1 (XTAL2) (MOSI) PB5 |(17)-- ; | | ; --( 5)| PA0 (XTAL1) (OC1B/PCINT4) PB4 |(16)-- ; | | ; ELECTRODE_2 --( 6)| PD2 (INT0) (OC1A/PCINT3) PB3 |(15)-- ; | | ; ELECTRODE_4 --( 7)| PD3 (INT1) (OC0A/PCINT2) PB2 |(14)-- ; | | ; --( 8)| PD4 (T0) (AIN1/PCINT1) PB1 |(13)-- ; | | ; SYNC_OUT --( 9)| PD5 (OC0B/T1) (AIN0/PCINT0) PB0 |(12)-- ; | | ; --(10)| GND (ICP) PD6 |(11)-- LED ; | | ; '----------------------------------' ; ; 10 Pin AVR ISP Programmer (MK 1) Header ; ,-----------, ; MOSI --| ( 1) ( 2) |-- VCC ; SS --| ( 3) ( 4) |-- GND ; RESET -- ]( 5) ( 6) |-- GND ; SCK --| ( 7) ( 8) |-- GND ; MISO --| ( 9) (10) |-- GND ; '-----------' ; ; 5 Pin AVR ISP Programmer (MK 2) Header ; (and Debug Wire debugger interface) ; ,-----------, ; MISO --| ( 1) ( 2) |-- VCC ; SCK -- ]( 3) ( 4) |-- MOSI ; RESET --| ( 5) ( 6) |-- GND ; '-----------' ; ; Revision History: ; ; 0.1 - Sean Quinn - 28 July 2012 - Initial Release ; (forked from h2o_piezo.asm) ; ; Device Signature: $1E910A ; ; Fuses: [X] Brown-out detection level at VCC=2.7V [BODLEVEL=101] ; [X] Internal RC Osc. 4MHz; 14 CK + 65ms; [CKSEL=0010 SUT=10] ; ; avrdude efuse = $FF ; XXXX XXX1 = SELFPROGEN ; ; avrdude hfuse = $DB ; 1XXX XXXX = DWEN (debugWIRE) ; X1XX XXXX = EESAVE ; XX0X XXXX = SPIEN (SPI Prog Enabled) ; XXX1 XXXX = WDTON ; XXXX 1XXX = BODLEVEL2 ; XXXX X0XX = BODLEVEL1 ; XXXX XX1X = BODLEVEL0 ; XXXX XXX1 = RSTDISBL ; ; avrdude lfuse = $E2 ; 1XXX XXXX = CKDIV8 ; X1XX XXXX = CKOUT ; XX1X XXXX = SUT1 ; XXX0 XXXX = SUT0 ; XXXX 0XXX = CKSEL3 ; XXXX X0XX = CKSEL2 ; XXXX XX1X = CKSEL1 ; XXXX XXX0 = CKSEL0 ; ; Lock Bits [X] Mode 1: No memory lock feature enabled ; ; avrdude lock = $FF ; XXXX XX00 = Mode 3 - Flash & EEprom verify blocked ; XXXX XX10 = Mode 2 - Flash & EEprom re-prog blocked ; XXXX XX11 = Mode 1 - No memory locks ; ; AVRDUDE Commands avrdude -p t2313 -c stk500v2 -t ; quit ; avrdude -p t2313 -c stk500v2 -e -U flash:w:hermes.hex -v ; avrdude -p t2313 -c stk500v2 -U eeprom:w:hermes_eeprom.hex -v ; avrdude -p t2313 -c stk500v2 -U efuse:w:0xFF:m -v ; avrdude -p t2313 -c stk500v2 -U hfuse:w:0xDB:m -v ; avrdude -p t2313 -c stk500v2 -U lfuse:w:0xE2:m -v ; avrdude -p t2313 -c stk500v2 -U lock:w:0xFF:m -v ; ; ; ;************************************************************************ .nolist .include "tn2313def.inc" .list ;************************************************************************ ;* ;* Macros ;* ;************************************************************************ .MACRO Delay_1us nop .ENDMACRO ;************************************************************************ ;* ;* Equates ;* ;************************************************************************ .EQU LAST_RAM_MARK = $55 ; ,------------------------------------------------------------------------------, ; | AT-Tiny 2313 Port Pin Programming | ; |------------------------------------------------------------------------------| ; | Write to DDR 0 = INPUT | ; | 1 = OUTPUT | ; | Write to PORT 0 = OUTPUT_L (when DDR = 1) / PULL-UP DISABLED (when DDR = 0) | ; | 1 = OUTPUT_H (when DDR = 1) / PULL-UP ENABLED (when DDR = 0) | ; | Write to PIN 0 = NO CHANGE TO PORT | ; | 1 = TOGGLE PORT (ignores value written to DDR) | ; | | ; | Read from PIN 0 = INPUT_L | ; | 1 = INPUT_H | ; '------------------------------------------------------------------------------' ; ; ,-----------------------------------------------------------, ; | NOT_USED | ; |-----------,-----,-----,-----,-----,-----,-----,-----,-----| ; | | PA7 | PA6 | PA5 | PA4 | PA3 | PA2 | PA1 | PA0 | ; |-----------|-----|-----|-----|-----|-----|-----|-----|-----| ; | FUNCTION | --- | --- | --- | --- | --- |RESET| N/A | N/A | ; |-----------|-----|-----|-----|-----|-----|-----|-----|-----| ; | DIRECTION | --- | --- | --- | --- | --- | IN | OUT | OUT | ; |-----------|-----|-----|-----|-----|-----|-----|-----|-----| ; | DDR | --- | --- | --- | --- | --- | 0 | 1 | 1 | ; |-----------|-----|-----|-----|-----|-----|-----|-----|-----| ; | PORT (WR) | --- | --- | --- | --- | --- | 1 | 1 | 1 | ; |-----------|-----|-----|-----|-----|-----|-----|-----|-----| ; | PIN (RD) | --- | --- | --- | --- | --- | X | X | X | ; '-----------'-----'-----'-----'-----'-----'-----'-----'-----' ; .EQU PORTA_DIR = $03 ; Port A0, A1 Outputs, A2 (Reset) Input .EQU PA_OFF = $07 ; Pull up Reset Input PIN, PA_0, PA_1 = 1 ; ; ,----------------------------------------------------------------, ; | SPI | ; |-----------,-----,------,------,--------,-----,-----,-----,-----| ; | | PB7 | PB6 | PB5 | PB4 | PB3 | PB2 | PB1 | PB0 | ; |-----------|-----|------|------|--------|-----|-----|-----|-----| ; | FUNCTION | SCK | MISO | MOSI | SPI_SS | PB3 | PB2 | PB1 | PB0 | ; |-----------|-----|------|------|--------|-----|-----|-----|-----| ; | DIRECTION | IN | OUT | IN | OUT | OUT | OUT | OUT | OUT | ; |-----------|-----|------|------|--------|-----|-----|-----|-----| ; | DDR | 0 | 1 | 0 | 1 | 1 | 1 | 1 | 1 | ; |-----------|-----|------|------|--------|-----|-----|-----|-----| ; | PORT (WR) | 1 | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ; |-----------|-----|------|------|--------|-----|-----|-----|-----| ; | PIN (RD) | SCK | X | MOSI | X | X | X | X | X | ; '-----------'-----'------'------'--------'-----'-----'-----'-----' ; .EQU PORTB_DIR = $5F ; SPI SETUP .EQU PORTB_PINS = $FF ; SCK Pullup Enabled, ; MISO = HIGH ; MOSI Pullup Enabled ; SPI_SS = HIGH ; ; ,-------------------------------------------------------------------------------------------, ; | PIEZOS | ; |-----------,-----,-----,----------,--------,-----------,-----------,-----------,-----------| ; | | PD7 | PD6 | PD5 | PD4 | PD3 | PD2 | PD1 | PD0 | ; |-----------|-----|-----|----------|--------|-----------|-----------|-----------|-----------| ; | FUNCTION | X | LED | SYNC_OUT | PD4 |ELECTRODE_4|ELECTRODE_2|ELECTRODE_3|ELECTRODE_1| ; |-----------|-----|-----|----------|--------|-----------|-----------|-----------|-----------| ; | DIRECTION | --- | OUT | OUT | OUT | OUT | OUT | OUT | OUT | ; |-----------|-----|-----|----------|--------|-----------|-----------|-----------|-----------| ; | DDR | --- | 1 | 1 | 1 | 1 | 1 | 1 | 1 | ; |-----------|-----|-----|----------|--------|-----------|-----------|-----------|-----------| ; | PORT (WR) | --- | 1 | 1 | 1 | 0 | 1 | 0 | 1 | ; |-----------|-----|-----|----------|--------|-----------|-----------|-----------|-----------| ; | PIN (RD) | --- | X | X | X | X | X | X | X | ; '-----------'-----'-----'----------'--------'-----------'-----------'-----------'-----------' ; .EQU PORTD_DIR = $FF .EQU ELECTRODE_1 = PD0 .EQU ELECTRODE_3 = PD1 .EQU ELECTRODE_2 = PD2 .EQU ELECTRODE_4 = PD3 .EQU SYNC_OUT = PD5 .EQU LED = PD6 ; ; ,-----------------------------------, ; | TIMER 0 (8 Bit) 4ms system timer | ; |-----------------------------------| ; Internal RC Oscillator @ 4MHz / 1 => 4MHz [i.e. CKDIV8=1] ; ;/* 4MHz / (256 * 64) = 244Hz => 4.096ms*/ ; .EQU TIMER_0_MODE = $00 ; Mode 0 (TOV set on 0xFF) .EQU TIMER_0_PRESCALER = $04 ; Prescaler = Divide by 256 .EQU TIMER_0_4_MILLISECONDS = $BF ; (255 - 64) = 191 ; .EQU TWENTY_MILLISECONDS = 5 ; 5 x 4.096ms = 20.48ms .EQU FORTY_MILLISECONDS = 10 ; 10 x 4.096ms = 40.96ms .EQU SIXTY_FOUR_MILLISECONDS = 16 ; 16 x 4.096ms = 66ms .EQU EIGHTY_MILLISECONDS = 20 ; 20 x 4.096ms = 82ms .EQU ONE_HUNDRED_MILLISECONDS = 25 ; 25 x 4.096ms = 103ms .EQU ONE_THIRTY_MILLISECONDS = 32 ; 32 x 4.096ms = 131ms .EQU ONE_SIXTY_MILLISECONDS = 40 ; 40 x 4.096ms = 164ms .EQU TWO_HUNDRED_MILLISECONDS = 50 ; 50 x 4.096ms = 205ms .EQU NINE_HUNDRED_MILLISECONDS = 220 ; 220 x 4.096ms = 901ms .EQU ONE_THOUSAND_MILLISECONDS = 245 ; 245 x 4.096ms = 1004ms ; ,-------------------------------------, ; | TIMER 1 (16 Bit) waveform generator | ; |-------------------------------------| ; Internal RC Oscillator @ 4MHz / 1 => 4MHz [i.e. CKDIV8=1] ; .EQU TIMER_1_MODE = $00 ; Mode 4 CTC, TOP=OCR1A .EQU TIMER_1_PRESCALER = $0B ; CTC mode, Prescaler = Divide by 64 .EQU TIMER_1_1_HERTZ_H = $3D ; 4MHz / 64 / 15625 / 4 = 1Hz .EQU TIMER_1_1_HERTZ_L = $09 ; 15625 = 0x3D09 ;************************************************************************ ;* ;* Register Files (0x00 to 0x1F) ;* ;************************************************************************ ; LDI and other Immedite instructions not supported for R0 to R15 .def lpm_r0_reg = r0 ; Reserve for LPM usage .def reg_r01 = r1 ; spare .def reg_r02 = r2 ; spare .def reg_r03 = r3 ; spare .def reg_r04 = r4 ; spare .def reg_r05 = r5 ; spare .def reg_r06 = r6 ; spare .def reg_r07 = r7 ; spare .def reg_r08 = r8 ; spare .def pattern_index = r9 ; pattern_index .def reg_r10 = r10 ; spare .def reg_r11 = r11 ; spare .def reg_r12 = r12 ; spare .def led_timer = r13 ; led_timer .def led_task_state = r14 ; led_task_state .def sreg_save = r15 ; SREG save ; LDI etc supported for R16 to R24 .def accu_8A = r16 ; accumulator A - 8 bit .def accu_8B = r17 ; accumulator B - 8 bit .def accu_8_ISR = r18 ; accumulator for ISR use - 8 bit .def reg_r19 = r19 ; spare .def reg_r20 = r20 ; spare .def reg_r21 = r21 ; spare .def reg_r22 = r22 ; spare .def accu_16L = r23 ; 16 bit accumulator Low Byte .def accu_16H = r24 ; 16 bit accumulator High Byte ;.def XL = r26 ;.def XH = r27 ;.def YL = r28 ;.def YH = r29 ;.def ZL = r30 ;.def ZH = r31 .EQU gp_flags_0 = GPIOR0 ; Use with SBI,CBI,SBIS & SBIC instructions .EQU gp_flags_1 = GPIOR1 .EQU gp_flags_2 = GPIOR2 ;************************************************************************ ;* ;* I/O Registers (0x20 to 0x5F) ;* ;************************************************************************ ; (defined in tn2313def.inc) ;************************************************************************ ;* ;* SRAM (0x60 to 0xDF) ;* ;************************************************************************ .DSEG temp_16: .byte 2 end_ram_mark_8: .byte 1 ; Marker showing last SRAM address used ;************************************************************************ ;* ;* STACK @ End of SRAM (0xDF) ;* ;************************************************************************ ;************************************************************************ ;* ;* Start of code space ;* ;************************************************************************ .CSEG .org $0000 rjmp reset ; Reset Handler .org $0001 rjmp int0_isr ; External Interrupt0 Handler .org $0002 rjmp int1_isr ; External Interrupt1 Handler .org $0003 rjmp tim1_capt_isr ; Timer1 Capture Handler .org $0004 rjmp tim1_compa_isr ; Timer1 CompareA Handler .org $0005 rjmp tim1_ovf_isr ; Timer1 Overflow Handler .org $0006 rjmp tim0_ovf_isr ; Timer0 Overflow Handler .org $0007 rjmp usart0_rxc_isr ; USART0 RX Complete Handler .org $0008 rjmp usart0_dre_isr ; USART0,UDR Empty Handler .org $0009 rjmp usart0_txc_isr ; USART0 TX Complete Handler .org $000A rjmp ana_comp_isr ; Analog Comparator Handler .org $000B rjmp pcint_isr ; Pin Change Interrupt .org $000C rjmp timer1_compb_isr ; Timer1 Compare B Handler .org $000D rjmp timer0_compa_isr ; Timer0 Compare A Handler .org $000E rjmp timer0_compb_isr ; Timer0 Compare B Handler .org $000F rjmp usi_start_isr ; USI Start Handler .org $0010 rjmp usi_overflow_isr ; USI Overflow Handler .org $0011 rjmp ee_ready_isr ; EEPROM Ready Handler .org $0012 rjmp wdt_overflow_isr ; Watchdog Overflow Handler ;************************************************************************ ;* ;* Title: timer0_config() ;* ;* Purpose: Configure Timer 0 (8 bit timer) ;* as the 4ms system timer ;* ;************************************************************************ timer0_config: in sreg_save,SREG ; Save Global interrupt flag cli ; Disable interrupts ;TCCR0A = TIMER_0_MODE ;TCCR0B = TIMER_0_PRESCALER ;TCNT0 = TIMER_0_4_MILLISECONDS ;OCR0A = 0 ;OCR0B = 0 ldi accu_8A, TIMER_0_MODE out TCCR0A, accu_8A ldi accu_8A, TIMER_0_PRESCALER out TCCR0B, accu_8A ldi accu_8A,TIMER_0_4_MILLISECONDS out TCNT0, accu_8A clr accu_8A out OCR0A, accu_8A out OCR0B, accu_8A ;TIMSK |= (1 << TOIE0) ; Enable Timer 0 Overflow Interrupt in accu_8A, TIMSK ori accu_8A, (1 << TOIE0) out TIMSK, accu_8A ;/*********************************************************** ; * There is no need to perform a read-modify-write cycle to ; * clear an interrupt flag, since all bits in these control ; * registers are interrupt bits, and writing a logical 0 to ; * the remaining bits (as it is done by the simple OUT ; * instruction) will not alter them, so there is no risk ; * of any race condition that might accidentally clear ; * another interrupt request bit. ; * So instead of writing: TIFR |= (1< Enable Timer 1 Output A Match Interrupt in accu_8A, TIMSK ori accu_8A, (1 << OCIE1A) out TIMSK, accu_8A ;*********************************************************** ;* There is no need to perform a read-modify-write cycle to ;* clear an interrupt flag, since all bits in these control ;* registers are interrupt bits, and writing a logical 0 to ;* the remaining bits (as it is done by the simple OUT ;* instruction) will not alter them, so there is no risk ;* of any race condition that might accidentally clear ;* another interrupt request bit. ;* So instead of writing: TIFR |= (1< Reset Timer 1 Output A Match Interrupt Flag ldi accu_8A, (1<:<-Timer 1->:<-Timer 1->:<-Timer 1->:<-Timer 1->: ;* : Period : Period : Period : Period : Period : ;* : : : : : : ;* ,-----------------------, : ,-------------- ;* ELECTRODE_1 | : | : | : ;* --' : '-----------------------' : ;* --, : ,-----------------------, : ;* ELECTRODE_3 | : | : | : ;* '-----------------------' : '-------------- ;* : : : : : : ;* --------------, : ,-----------------------, ;* ELECTRODE_2 : | : | : | ;* : '-----------------------' : '-- ;* : ,-----------------------, : ,-- ;* ELECTRODE_4 : | : | : | ;* --------------' : '-----------------------' ;* : : : : : ;* ;************************************************************************ pattern_table: .DW $05, $09 .DW $0A, $06 .DW $FF, $FF ; FF = End of Table ;************************************************************************ ;* ;* Copyright text in ROM ;* ;************************************************************************ .DB "(c) Sean Quinn 2012 " .DB 0,0 ; NULL terminator ;************************************************************************ ;* ;* EEPROM ;* ;************************************************************************ .ESEG .ORG $00 .DB "(c) Sean Quinn 2012" .DB 0 ;************************************************************************ ;* ;* End h2o_ion.asm ;* ;************************************************************************