; ; i0.7.bridge.asm ; bridge bytes between I0 and RS-232 ; ; Neil Gershenfeld CBA MIT 9/8/05 ; (c) Massachusetts Institute of Technology 2005 ; Permission granted for experimental and personal use; ; license for commercial use available from MIT ; .include "tn13def.inc" .equ rxpin = PB0; receive pin .equ txpin = PB2; transmit pin .equ clickin = PB3 ; I0 input pin .equ ledpin2 = PB4 ; I0 output pin .def txbyte = R24 .def bitcount = R16; bit counter .def byte = R17; tx/rx byte .def clickdelay2 = R18; click spacing .def tripledelay = R19; triple click spacing .def count = R20; loop counter .def doublecount = R21; double loop count .def temp = R22; temporary storage .def temp1 = R23; temporary storage .cseg .org 0 rjmp reset ; ; getchar ; input a serial byte following first transition ; getchar: ldi bitcount, 9 ; 8 data bit + 1 stop bit rcall bitdelay ; 0.5 bit delay getcharloop: rcall bitdelay ; 1 bit delay rcall bitdelay ; clc ; clear carry sbis PINB, rxpin ; if RX pin high skip sec ; otherwise set carry dec bitcount breq getcharend ; return if all bytes read ror byte ; otherwise shift bit into receive byte rjmp getcharloop ; get next bit getcharend: ret ; ; putchar ; output a serial byte ; putchar: .equ sb = 1 ; number of stop bits ldi bitcount, 9+sb; 1+8+sb com byte ; invert everything sec ; set start bit putchar0: brcc putchar1 ; if carry set sbi PORTB, txpin ; send a '0' rjmp putchar2 ; else putchar1: cbi PORTB, txpin ; send a '1' nop ; even out timing putchar2: rcall bitdelay ; one bit delay rcall bitdelay lsr byte ; get next bit dec bitcount ; if not all bits sent brne putchar0 ; send next bit ret ; ; getclick ; input an I0 byte following first click ; getclick: clr clickdelay2 sbi ACSR, ACI ; reset comparator ; ; find click delay from arrival of second start click ; start2: inc clickdelay2 breq getclicktimeout ; time-out if count overflows sbis ACSR, ACI rjmp start2 mov tripledelay, clickdelay2 add tripledelay, clickdelay2 add tripledelay, clickdelay2 ; ; decode data clicks ; clr byte ldi bitcount, 8 bitloop: ; ; time arrival of next click ; clr count sbi ACSR, ACI ; reset comparator bitclickloop: inc count breq getclicktimeout ; time-out if count overflows sbis ACSR, ACI rjmp bitclickloop ; ; determine bit delay ; mov doublecount, count add doublecount, count cp doublecount, tripledelay brsh zero ; ; one bit ; sec ; set carry ror byte ; shift in carry ; ; even out timing with click delay ; mov count, clickdelay2 onedelay: nop ; time for breq nop ; time for sbis dec count brne onedelay dec bitcount brne bitloop ; output if byte received rjmp getclickend zero: ; ; zero bit ; clc ; clear carry ror byte ; shift in carry dec bitcount brne bitloop ; output if byte received getclickend: ret getclicktimeout: mov byte, clickdelay2 ret ; ; putclick ; output an I0 byte ; putclick: ldi bitcount, 8 sec; set start bit ; ; send start clicks ; cbi PORTB, ledpin2 sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 rcall clickdelay sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 cbi PORTB, ledpin2 rcall clickdelay ; ; send data clicks ; putclick0: lsr txbyte; get next bit brcc putclick1; if carry set, send a 1 click cbi PORTB, ledpin2 sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 cbi PORTB, ledpin2 rcall clickdelay rjmp putclick2; otherwise ... putclick1: cbi PORTB, ledpin2; ... send a 0 click cbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 rcall clickdelay sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 cbi PORTB, ledpin2 rcall clickdelay putclick2: dec bitcount; if not all bits sent brne putclick0; send next bit ; ; send stop clicks ; cbi PORTB, ledpin2 sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 rcall clickdelay sbi PORTB, ledpin2 rcall clickdelay cbi PORTB, ledpin2 cbi PORTB, ledpin2 rcall clickdelay ; ; return ; ret ; ; bitdelay ; serial bit delay ; .equ b = 17 bitdelay: ldi temp, b bitdelayloop: dec temp brne bitdelayloop ret ; ; clickdelay ; delay between clicks ; clickdelay: ldi temp, 200 clickdelayloop: ldi temp1, 200 clickdelayloop2: dec temp1 brne clickdelayloop2 dec temp brne clickdelayloop ret ; ; main program ; reset: ldi temp, low(RAMEND) ; set stack pointer to top of RAM out SPL, temp ; cbi PORTB, txpin; init comm pin for output sbi DDRB, txpin sbi PORTB, ledpin2 ; init mosfet control pin for output sbi DDRB, ledpin2 cbi ACSR, ACIS1 ; setup comparator to output on state change cbi ACSR, ACIS0 ; sbi ADCSRB, ACME ; setup comparator to use ADC multiplexer cbi ADCSRA, ADEN ; sbi ADMUX, MUX1 ; set channel to ADC3 sbi ADMUX, MUX0 ; loop: ; ; wait for a click or a bit ; sbi ACSR, ACI ; reset comparator waitloop: sbic ACSR, ACI ; check comparator for click rjmp I0_to_serial ;ldi txbyte, 2 ;rcall putclick rjmp waitloop serial_to_I0: ldi byte, 'b' rcall putchar rcall getchar rcall putclick rjmp loop I0_to_serial: ;rcall getclick rcall putclick ;rcall putchar rjmp loop