;
; getsclick.asm
; gets click - capacitative wireless i0 sensing
; bridge bytes between I0 and RS-232
;
; Stacy DeRuiter, 12/05
; based on i0.bridge.asm and hello3.asm by 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 = PB4 ; I0 input pin
.equ chargepin = PB3 ; charging pin
.def bitcount = R16; bit counter
.def byte = R17; tx/rx byte
.def clickdelay = 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 clickdelay
   sbi ACSR, ACI ; reset comparator
   ;
   ; find click delay from arrival of second start click
   ;
   start2:
      inc clickdelay
      breq getclicktimeout ; time-out if count overflows
      sbis ACSR, ACI
      rjmp start2
   mov tripledelay, clickdelay
   add tripledelay, clickdelay
   add tripledelay, clickdelay
   ;
   ; 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, clickdelay
         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, clickdelay
	 ret
;
;; putclick
;; output an I0 byte
;;
;putclick:
;   ldi bitcount, 8
;   sec; set start bit
;   ;
;   ; send start clicks
;   ;
;   cbi PORTB, clickout
;   sbi PORTB, clickout
;   rcall clickdelay
;   cbi PORTB, clickout
;   sbi PORTB, clickout
;   rcall clickdelay
;   ;
;   ; send data clicks
;   ;
;   putclick0:
;      lsr byte; get next bit
;      brcc putclick1; if carry set, send a 1 click
;      cbi PORTB, clickout
;      sbi PORTB, clickout
;      rcall clickdelay
;      sbi PORTB, clickout
;      sbi PORTB, clickout
;      rcall clickdelay
;      rjmp putclick2; otherwise ...
;   putclick1:
;      sbi PORTB, clickout; ... send a 0 click
;      sbi PORTB, clickout
;      rcall clickdelay
;      cbi PORTB, clickout
;      sbi PORTB, clickout
;      rcall clickdelay
;   putclick2:
;      dec bitcount; if not all bits sent
;      brne putclick0; send next bit
;   ;
;   ; send stop clicks
;   ;
;   cbi PORTB, clickout
;   sbi PORTB, clickout
;   rcall clickdelay
;   cbi PORTB, clickout
;   sbi PORTB, clickout
;   rcall clickdelay
;   ;
;   ; return
;   ;
;   ret
;
; routine to wait for sample to settle
;
;.equ delay = 255
;settle:
;   ldi temp, delay
;   settleloop:
;      dec temp
;      brne settleloop
;   ret
;
; bitdelay
; serial bit delay
;
.equ b = 17
bitdelay:
   ldi temp, b
   bitdelayloop:
      dec temp
      brne bitdelayloop
   ret
;
; clickdelay
; delay between I0 clicks
;
clickdelay:
   ldi temp, 100
   clickdelayloop:
      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
   cbi PORTB, chargepin ; not charging
   sbi DDRB, chargepin ; "
   sbi ACSR, ACIS1 ; setup comparator to output on falling edge of signal
   cbi ACSR, ACIS0 ;
   sbi ADCSRB, ACME ; setup comparator to use ADC multiplexer
   cbi ADCSRA, ADEN ;
   sbi ADMUX, MUX1 ; set channel to ADC2
   cbi ADMUX, MUX0 ;
   ;
   ;ldi delaycnt, 100; delay between sending charge and measuring response is 100
   ;
   loop:
     ;
	 ; settle sample and start upward step response
	 ;
         ;cbi PORTB, chargepin
         ;rcall settle
	     ;mov temp, delaycnt
         sbi PORTB, chargepin
	 ;
     ; wait for delay
	 ;
	 ;delay:
	 ;   dec temp
	 ;   brne delay
     ;
	 ; read response
	 ;
     ; wait for a click or a bit
     ;
      sbi ACSR, ACI ; reset comparator
      waitloop:
         sbic ACSR, ACI ; check comparator for click
	    rjmp I0_to_serial
;         sbis PINB, rxpin ; check serial pin for bit
            rjmp waitloop
      serial_to_I0:
         ldi byte, 'b'
	     rcall putchar
         rcall getchar
	     ;rcall putclick
	     rjmp loop
      I0_to_serial:
         rcall getclick
	     rcall putchar
	     rjmp loop
