APPENDIX B: Code

 

 

adb_talk0asm.asm

adb_osc.c

adb_video.c

ps2_tp.asm

 

 

 

adb_talk0asm.asm

 

.include "c:\avrtools\appnotes\m32def.inc"

 

.def  temp  =r16

.def  cmdbyte     =r20

.def  inbyte      =r21

.def  bytenum     =r22

.def  bitcnt      =r23

.def  txchar      =r24

 

;.def bstart_l=r28

;.def bstart_h=r29

 

 

.equ  talk3 =$3f

.equ  talk2 =$3e

.equ  talk1 =$3d

.equ  talk0 =$3c

.equ  listen3     =$3b

 

 

;r17,r18,r19 used in delay loops

 

;-------------------------------------------

.dseg

buffer: .byte 10;to store complete response

;--------------------------------------------

 

.cseg

 

rjmp reset

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

rjmp ignore_int

 

 

ignore_int: reti

 

;-------------------------------------------------------

reset:

      ldi temp, low(RAMEND);reset stack pointer

      out SPL, temp

      ldi temp, high(RAMEND)

      out SPH, temp

 

      ldi temp, $ff;portb output for debugging

      out ddrb, temp

      out portb, temp;turn off leds

 

      ldi temp, $00;initialize portc.0 to be adb signal

      out ddrc, temp;float it high

      ldi temp, $ff

      out portc, temp

 

      ldi temp, $08     ;initialize usart to enable Tx

      out ucsrb, temp

      ldi temp, $67;baud rate set to 9600

      out ubrrl, temp

 

      ldi temp, $03;init counter0 for 4us per tick

      out tccr0, temp

      ldi temp, $00;disable interrupts

      out timsk, temp        

      out tifr, temp

 

ldi txchar, 'H'

      rcall UAputc

      ldi txchar, 'E'

      rcall UAputc

      ldi txchar, 'L'

      rcall UAputc

      ldi txchar, 'L'

      rcall UAputc

      ldi txchar, 'O'

      rcall UAputc

      ldi txchar, '!'

      rcall UAputc

       

       

      ldi r28, low(buffer)

      ldi r29, high(buffer)

      ldi r17, 0

      ldi temp, 10

clear:      st y+, r17

      dec temp

      brne clear

       

       

 

       

      ;call 200ms delay for touchpad initialization

      rcall delay_200ms

 

mloop: ;main loop could start here once cmd is talk0

 

resend:     ldi temp, $00;initialize portc.0 to be adb signal

      out ddrc, temp          ;float it high

      ldi temp, $ff

      out portc, temp

       

      rcall delay_10ms

       

      ldi cmdbyte, talk0

 

      rcall sendcmd

      ldi temp, $00

      out portb, temp

      ldi bytenum, $02;# of bytes in response

      ldi r28, low(buffer) ;init buffer to store response

      ldi r29, high(buffer) ;this is 'Y'

      rjmp getresp

      ldi temp, $ff

      out portb, temp

 

txnow:      ;ldi temp, $ff

      ;out portb, temp

      ldi bytenum, $3

      ldi r28, low(buffer) ;re-init buffer to tx response

      ldi r29, high(buffer) ;this is 'Y'

      rcall UAputbyte

 

;mloop:    

      rjmp mloop

 

;------------------------------------------------------------------

 

UAputc:

      sbis ucsra, udre

      rjmp UAputc

      out udr, txchar

      ret

;------------------------------------------------------------------

sendcmd:

      ldi temp, $01;portc.0=adb output

      out ddrc, temp

      out portc, temp

      ldi temp, $00;attention

      out portc, temp

      out tcnt0, temp

wattn:in temp, tcnt0

      cpi temp, 200

      brne wattn

      ldi temp, $01;sync

      out portc, temp

      out tcnt0, temp

wsync:in temp, tcnt0

      cpi temp, 16

      brne wsync

      ldi bitcnt, 8

sdbtlp:; send 8 bits

      ldi temp, $00

      out portc, temp

      out tcnt0,temp

      rol cmdbyte

      brcs wait36

wait64:     in temp, tcnt0

      cpi temp, 16     

      brlt wait64

      ;mov inbyte, temp

      ;rcall UAputbyte

      rjmp lowdone

wait36:     in temp, tcnt0

      cpi temp, 9

      brlt wait36

lowdone:ldi temp, $01

      out portc, temp

celldn:     in temp, tcnt0

      cpi temp, 25

      brlt celldn

      dec bitcnt

      brne sdbtlp

      ldi temp, $00;stop bit

      out portc, temp

      out tcnt0, temp

      ;ldi temp, $ff

      ;out portb, temp

wstop:in temp, tcnt0

      cpi temp, 18

      brlt wstop

      ldi temp, $01;stop bitcell high part

      out portc, temp

      ldi temp, $00;reload timer to keep check on stop till start time (200+28)

      out tcnt0, temp

wstos:in temp, tcnt0

      cpi temp, 56

      brlt wstos 

      ldi temp, $00;wait for responce

      out ddrc, temp

      ldi temp, $01;float pin high

      out portc, temp

      ;in temp, pinc

      ;out portb, temp

      ret

;--------------------------------------------------------------------------------

getresp:

      in temp, tcnt0

      cpi temp, 58      ;(200+28)/4 + some leeway

      brmi continue

      rjmp resend;if high time greater than 200us then resend command

continue:

      in temp, pinc

      ;out portb, temp

      sbrc temp, 0

      rjmp getresp;wait for start bit

      ldi temp, $ff

      out portb, temp

       

       

      in temp,pinc

      sbrs temp, 0

      rjmp continue

bytelp:                             ;send data byte

      ldi inbyte, $00  

      ldi bitcnt, 8

gtbtlp: lsl inbyte

wforlw: sbic pinc, 0;low time

      rjmp wforlw

      ldi temp, $00

      out tcnt0, temp

wforhi: sbis pinc, 0; high time

      rjmp wforhi

      in temp, tcnt0

      cpi temp , 13

      brge got0

      ori inbyte, $01

got0:                         ;interpret "0" logic

      dec bitcnt

      brne gtbtlp

      st y+, inbyte

      dec bytenum

      brne bytelp

wstlw:      sbic pinc, 0;wait for stop bit

      rjmp wstlw

wsthi:sbis pinc, 0

      rjmp wsthi

      ldi temp, $01           ;float signal line high.

      out portc, temp

      rjmp txnow

;---------------------------------------------------------------------------------

UAputbyte:

      push temp

      ldi bitcnt, 8

      ld temp, y+

txlp: tst bitcnt        ;transmit 8 bits

      breq txlpdn

      ldi txchar, 0b10000000

      and txchar, temp

      lsr txchar

      lsr txchar

      lsr txchar

      lsr txchar

      lsr txchar

      lsr txchar

      lsr txchar

      subi txchar, -'0'

      rcall UAputc

      dec bitcnt

      lsl temp

      rjmp txlp

txlpdn: ldi txchar, $0d;tx newline

      rcall UAputc

      ldi txchar, $0a

      rcall UAputc

      pop temp

      dec bytenum

      brne UAputbyte

      ret

;----------------------------------------------------------------------------------------

delay_200ms:

      ldi r17, 20

lp17: ldi r18, 200

lp18: ldi r19, 200

lp19: nop

      dec r19

      brne lp19

      dec r18

      brne lp18

      dec r17

      brne lp17

      ret

;-------------------------------------------------------------------------------------------

delay_10ms:

      ldi r17, 1

lp170:      ldi r18, 200

lp180:      ldi r19, 200

lp190:      nop

      dec r19

      brne lp19

      dec r18

      brne lp18

      dec r17

      brne lp17

      ret

 

Go Back

 

adb_osc.c

 

#include <Mega32.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <delay.h>

 

#pragma regalloc-

 

register char cmdbyte@13;

register char bytenum@14;

 

#asm

.def  temp  =r16

#endasm

 

unsigned char txchar, resp;

inttemp1;

#pragma regalloc+

 

unsigned char time1,reload;

unsigned int count;

 

//predefined command bytes

#define     talk3       0x3f

#define     talk2       0x3e

#define     talk1       0x3d

#define     talk0       0x3c

#define     listen3     0x3b

 

 

unsigned char buffer[10];//to store complete response

unsigned char bufferx[901],buffery[901]; //to store incremental x,y, offsets

 

//---------------------------------------------------

//function declarations

void initialize(void);

void UAputbyte(void);//takes in bytenum, buffer and displays bytes in hyperterm

void delay_10ms(void);// delays 10 ms

void delay_200ms(void); // delays 200 ms

void getresp(void);// gets input from device and stores in buffer

void sendcmd(void);// takes in cmdbyte and sends the command packet to device

void UAputc(void);      //takes in a char in txchar and displays it in hyperterm

void executecmd(void); // takes in cmdbyte and bytenum and executes the entire transaction

void refresh(void);// draws all the points to the oscilloscope screen

void delete_pic(void); //delete the picture and plot a center point

 

void initialize(void)

{

      int j;

       //initialize portc.0 to be adb signal

      DDRC =0x00;

      PORTC = 0xff;//float it high

 

       //initialize DAC ports

      DDRA = 0xff;// PORT A is an ouput to DAC: X

      DDRB = 0xff;// PORT B is an ouput to DAC: Y

 

       //initialize usart to enable Tx

      UCSRB = 0x08;

      UBRRL= 0x67;//baud rate set to 9600

       

       //init counter0 for 4us per tick

      TCCR0 = 0x03;

 

       //disable interrupts for timer0

      TIMSK=0x00;

      TIFR=0x00;

 

 

//initializations for drawing on screen

count=900;//screen just has a dot in the center

delete_pic(); //needbufferx[0]=buffery[0]=0;

 

 

txchar= 'H';

      UAputc();

      txchar='E';

      UAputc();

      txchar ='L';

      UAputc();

      txchar ='L';

      UAputc();

      txchar ='O';

      UAputc();

      txchar ='!';

      UAputc();

       

      for (j=0;j<=10;j++) //clear screen

      {

buffer[j]=0;

}

 

       //call 200ms delay for touchpad initialization

      delay_200ms();

}

 

 

void main(void)

{

      initialize();

      count=0;//keep count of points stored in buffers

      while(1)

      {

 

      cmdbyte = talk0;//define talk to register 0 command

      executecmd();// get the motion pkts

refresh();// output to oscilloscope

      }

}

//------------------------------------------------------------------

void executecmd(void)

{

      int i,sh;

      char dy=0, dx=0;

      DDRC=0x00;//initialize portc.0 to be adb signal

      PORTC=0xff;//float it high

 

       //delay_10ms();//---check if it makes a difference

      bytenum= 2;//# of bytes in response

      sendcmd();

 

       

      resp=1;// flag set to signal touchpad has data to send

      getresp();

 

if ((resp ==1) && (count<3600))

{

//display response in hyperterm

            UAputbyte();

       

             

       //the sign of the deltax and deltay determine up, down, left, right direction

      if ((buffer[0] & 0x80) ==0x00)

      delete_pic();

       else

      {     //mask the 7 LSB

                  buffer[0]= (buffer[0] & 0b01111111);

                  buffer[1]= (buffer[1] & 0b01111111);

 

                   //get sign bit

                  dy= (buffer[0]>>6);

                  dx= (buffer[1]>>6);

            if (buffer[0]==0x00)dy=0x00;//same

             else

            {

                  if (dy==0x01)dy=0x01;//UP

                  elsedy=0x03;//DOWN

            }

                  if (buffer[1]==0x00)dx=0x00;//same

             else

            {

                  if (dx==0x01)dx=0x03;//LEFT

                  elsedx=0x01;                  //RIGHT

            }

 

       

            count++;

            i=(int)(count>>2); //number of bytes

            sh= (8 - ((int)((count%4)+1)<<1));

            bufferx[i]=(bufferx[i] | (dx << sh));//shift by this amount

                  buffery[i]=(buffery[i] | (dy << sh));//position the delta at the next available position

             

                  if ((buffer[0]>=7)|| (buffer[1]>=7))//if delta is large than draw 2 points to improve speed

                  {

                  count++;

                  i=(int)(count>>2);//number of bytes

                  sh= (8 - ((int)((count%4)+1)<<1));//shift by this amount

                  bufferx[i]=(bufferx[i] | (dx << sh));//position the delta at the next available position

                        buffery[i]=(buffery[i] | (dy << sh));

                  }

 

}

            txchar=0x0d;//new line

            UAputc();

            txchar=0x0a;

            UAputc();

             

 

      }    

       

}

//------------------------------------------------------------------

void UAputc(void)

{

      #asm

      UAputclp:

            sbis 0x0b, 5;UCSRA      =$0b UDRE   =5 , UDR      =$0c

            rjmp UAputclp

      #endasm

      UDR=txchar;

}

//------------------------------------------------------------------

void sendcmd(void)

{

      #asm

            ;PORTC      =$15, DDRC  =$14 ,TCNT0 =$32

            .def  bitcnt      =r23

            ldi temp, $01;portc.0=adb output

            out 0x14, temp

            out 0x15, temp

            ldi temp, $00;attention

            out 0x15, temp

            out 0x32, temp

      wattn:in temp, 0x32

            cpi temp, 200

            brne wattn

            ldi temp, $01;sync

            out 0x15, temp

            out 0x32, temp

      wsync:in temp, 0x32

            cpi temp, 16

            brne wsync

            ldi bitcnt, 8

      sdbtlp:

            ldi temp, $00

            out 0x15, temp

            out 0x32,temp

            rol r13

            brcs wait36

      wait64:     in temp, 0x32

            cpi temp, 16     

            brlt wait64

            rjmp lowdone

      wait36:     in temp, 0x32

            cpi temp, 9

            brlt wait36

      lowdone:ldi temp, $01

            out 0x15, temp

      celldn:     in temp, 0x32

            cpi temp, 25

            brlt celldn

            dec bitcnt

            brne sdbtlp

            ldi temp, $00;stop bit

            out 0x15, temp

            out 0x32, temp

      wstop:in temp, 0x32

            cpi temp, 18

            brlt wstop

            ldi temp, $01;stop bitcell high part

            out 0x15, temp

            ldi temp, $00;reload timer to keep check on stop till start time (200+28)

            out 0x32, temp

      wstos:in temp, 0x32

            cpi temp, 56

            brlt wstos 

            ldi temp, $00;wait for responce

            out 0x14, temp

            ldi temp, $01;float pin high

            out 0x15, temp

      #endasm

}

//--------------------------------------------------------------------------------

void getresp(void)

{

      #asm

            ; PINC      =$13

            .def  inbyte      =r21

            .def  bitcnt      =r23

            ldi r30, low(_buffer) ;init buffer to store response

            ldi r31, high(_buffer) ;this is 'Z'

            ldi r26, low(_resp) ;init response

            ldi r27, high(_resp);this is 'X'

            mov r25,r14

      stgetresp:

            in temp, 0x32

            cpi temp, 58      ;(200+28)/4 + some leeway

            brmi continue

            ;if high time greater than 200us then resend command

            ; set flag to show that no response is sent

            ldi r24 , 0x00

            st x, r24

            rjmp endloop

      continue:

            in temp, 0x13

            sbrc temp, 0

            rjmp stgetresp;wait for start bit

             

            in temp,0x13

            sbrs temp, 0

            rjmp continue

      bytelp:                             ;get byte

            ldi inbyte, $00  

            ldi bitcnt, 8

      gtbtlp: lsl inbyte

      wforlw: sbic 0x13, 0

            rjmp wforlw

            ldi temp, $00

            out 0x32, temp

      wforhi: sbis 0x13, 0

            rjmp wforhi

            in temp, 0x32

            cpi temp , 13

            brge got0

            ori inbyte, $01

      got0:                         ;interpret a logic "0"

            dec bitcnt

            brne gtbtlp

            st z+, inbyte

            dec r25

            brne bytelp

      wstlw:      sbic 0x13, 0      ;wait for stop bit     

            rjmp wstlw

      wsthi:sbis 0x13, 0

            rjmp wsthi

            ldi temp, 0x01;float signal line high.

            out 0x15, temp

      endloop:

#endasm

 

}

//---------------------------------------------------------------------------------

void UAputbyte(void)

{

#asm

      .def  bitcnt      =r23

      .def txc=r24

      ldi r26, low(_buffer) ;re-init buffer to tx response

      ldi r27, high(_buffer) ;this is 'X'

      mov r25, r14

      push temp

stUAputbyte:

       

      ldi bitcnt, 8

      ld temp, x+

txlp: tst bitcnt              ;send byte

      breq txlpdn

      ldi txc, 0b10000000

      and txc, temp

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      subi txc, -'0'

      sts _txchar, txc

      rcall _UAputc

      dec bitcnt

      lsl temp

      rjmp txlp

txlpdn: ldi txc, $0d          ;tx newline

sts _txchar, txc

      rcall _UAputc

      ldi txc, $0a

      sts _txchar, txc

      rcall _UAputc

       

      dec r25

      brne stUAputbyte

      pop temp

#endasm

}

//----------------------------------------------------------------------------------------

void delay_200ms(void)

{

#asm

      ldi r17, 20

lp17: ldi r18, 200

lp18: ldi r19, 200

lp19: nop

      dec r19

      brne lp19

      dec r18

      brne lp18

      dec r17

      brne lp17

#endasm

}

//-------------------------------------------------------------------------------------------

void delay_10ms(void)

{

#asm

      ldi r17, 1

lp170:      ldi r18, 200

lp180:      ldi r19, 200

lp190:      nop

      dec r19

      brne lp19

      dec r18

      brne lp18

      dec r17

      brne lp17

#endasm

}

 

//======================================================

void delete_pic(void)

{

int j,temp2;

temp2=(int)(count>>2)+1; //number of bytes

for (j=0;j<=temp2;j++) //clear screen

{

bufferx[j]=0;

      buffery[j]=0;

}

count=0;

PORTA=64;//show center point

PORTB=64;

}

//===================================================================================

void refresh(void)

{

temp1 =(int)(count>>2)+1;//number of bytes ceil[(count/4)] as four directions in a byte

#asm

 

push r1 ;save reg old contents

push r2

push r3

push r4

push r5

push r6

push r16

push r17

push r18

push r19

push r20

 

ldi temp, 0x03

mov r5, temp

 

ldi r30, low(_temp1)

ldi r31, high(_temp1)

ld r20,Z;load no. of bytes

mov r6, r20

ldi r30, low(_bufferx);load buffer of x-increments

ldi r31, high(_bufferx)

ldi r26, low(_buffery);load buffer of y-increments

ldi r27, high(_buffery)

 

ldi r19, 0

ldi r16, 0x40;initialize center point0x40

ldi r17, 0x40

 

loop1:

ldi r18, 4;4 points in a byte

ld r1, Z+;read buffer (1 byte= 4 direction updates)

ld r2, X+

 

;parse throught the byte to get all four direction increments

;incrementchange in current position (x and y)

;-------------------------------------

; 11|-1

; 01|+1

; 00|no change

;-------------------------------------

loop2:

rol r1

brcc addx

dec r16;currx--

rol r1

rjmp endx

 

addx:

rol r1

brcc endx

adc r16, r19;currx++

 

endx:

rol r2

brcc addy

dec r17;curry--

rol r2

rjmp endy

 

addy:

rol r2

brcc endy

adc r17, r19;curry++

 

endy:

out 0x1b, r16;PORTA     =$1b

out 0x18, r17;PORTB     =$18

dec r18;get next byte if 4 updates complete

brne loop2;next point

dec r20;check if all relevant bytes from buffer read (ie till count)

brne loop1;next byte

;--------------------------------------

 

 

;ld r1, z-

;ld r2, x-

mov r20, r6

 

loop12:

ldi r18, 4;4 points in a byte

ld r1, -Z;read buffer (1 byte= 4 direction updates)

ld r2, -X

 

;parse throught the byte to get all four direction increments

;incrementchange in current position (x and y)

;-------------------------------------

; 11|+1

; 01|-1

; 00|no change

;-------------------------------------

 

 

 

loop22:

mov r3, r1

and r3, r5

mov r4, r2

and r4, r5

 

cpse r3, r5

rjmp nosubx

inc r16

rjmp donex

 

nosubx:

sbrs r3, 0

rjmp donex

dec r16

 

donex:

 

cpse r4, r5

rjmp nosuby

inc r17

rjmp doney

 

nosuby:

sbrs r4, 0

rjmp doney

dec r17

 

doney:

 

lsr r1

lsr r1

lsr r2

lsr r2

out 0x1b, r16

out 0x18, r17

dec r18

brne loop22

dec r20

brne loop12

 

 

 

 

 

;------------------------------------------

 

pop r20 ;put old values back into regs

pop r19

pop r18

pop r17

pop r16

pop r6

pop r5

pop r4

pop r3

pop r2

pop r1

 

 

#endasm

 

}

 

Go Back

 

adb_video.c

 

//Electronic drawing board

//Input=Touchpad

//Output=TV screen

//Dalia Burgos & Prachi Pandit

//ECE 476 Final Project

 

#pragma regalloc-    //I allocate the registers myself

#pragma optsize-     //optimize for speed

 

#include <Mega32.h>

#include <stdio.h>

#include <stdlib.h>

#include <math.h>

#include <delay.h>

 

//cycles = 63.625 * 16 Note NTSC is 63.55

//but this line duration makes each frame exactly 1/60 sec

//which is nice for keeping a realtime clock

#define lineTime 1018

 

#define begin {

#define end   }

#define ScreenTop 30

#define ScreenBot 230

#define T0reload 256-60

 

//NOTE that v1 to v8 and i must be in registers!

register char v1 @4;

register char v2 @5;

register char v3 @6;

register char v4 @7;

register char v5 @8;

register char v6 @9;

register char v7 @10;

register char v8 @11;

register int i @12;

 

//touchpad variables (only talk0 required, others for debugging)

#define     talk3    0x3f

#define     talk2    0x3e 

#define     talk1    0x3d

#define     talk0    0x3c

#define     listen3        0x3b

 

register char cmdbyte  @13;

register char bytenum  @14;

 

#asm

.def  temp  =r16

#endasm

 

unsigned char txchar, resp, count, mode, alreadydrawn;

unsigned char intX, intY, currX, currY, firstX, firstY;

#pragma regalloc+

//tv varirables

 

char screen[1600],t;

char syncON, syncOFF;

int LineCount;

char buffer[10];   //to store temporary touchpad response

 

// ==============================================

// functions

void initialize(void);

//execute commands specified from switches

void TheTask(void);

//Touchpad

void UAputbyte(void); //debugging

void delay_10ms(void); //debugging

void delay_200ms(void); //degugging

void getresp(void);

void sendcmd(void);

void UAputc(void);

 

 

//Point plot lookup table

flash char pos[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01};

//====================================================================================

//This is the sync generator and raster generator. It MUST be entered from

//sleep mode to get accurate timing of the sync pulses

#pragma warn-

interrupt [TIM1_COMPA] void t1_cmpA(void)

begin

  //start the Horizontal sync pulse

  PORTD = syncON;

  //count timer 0 at 1/usec

  //TCNT0=0;

  //update the curent scanline number

  LineCount ++ ;

  //begin inverted (Vertical) synch after line 247

  if (LineCount==248)

  begin

    syncON = 0b00100000;

    syncOFF = 0;

  end

  //back to regular sync after line 250

  if (LineCount==251)

  begin

    syncON = 0;

    syncOFF = 0b00100000;

  end

  //start new frame after line 262

  if (LineCount==263)

  begin

     LineCount = 1;

  end

 

  //delay_us(2); //adjust to make 5 us pulses

  //end sync pulse

  PORTD = syncOFF;

 

  if (LineCount<ScreenBot && LineCount>=ScreenTop)

    begin

 

       //compute byte index for beginning of the next line

       //left-shift 4 would be individual lines

       // <<3 means line-double the pixels

       //The 0xfff8 truncates the odd line bit

       //i=(LineCount-ScreenTop)<<3 & 0xfff8; //

 

       #asm

       push r13

       push r14

       push r21

       push r23

       push r24

       push r25

       push r26

       push r27

       push r30

       push r31

       push r16

 

       lds   r12, _LineCount

       lds   r13, _Linecount+1

       ldi   r16, 30

       sub  r12, r16

       ldi  r16,0

       sbc  r13, r16

       lsl  r12

       rol  r13

       lsl  r12

       rol  r13

       lsl  r12

       rol  r13

       mov  r16,r12

       andi r16,0xf0

       mov  r12,r16

       pop r16

 

       ;load 16 registers with screen info

       push r14

       push r15

       push r16

       push r17

       push r18

       push r19

       push r26

       push r27

 

       ldi  r26,low(_screen)   ;base address of screen

       ldi  r27,high(_screen)

       add  r26,r12            ;offset into screen (add i)

       adc  r27,r13

       ld   r4,x+              ;load 16 registers and inc pointer

       ld   r5,x+

       ld   r6,x+

       ld   r7,x+

       ld   r8,x+

       ld   r9,x+

       ld   r10,x+

       ld   r11,x+

       ld   r12,x+

       ld   r13,x+

       ld   r14,x+

       ld   r15,x+

       ld   r16,x+

       ld   r17,x+

       ld   r18,x+

       ld   r19,x

 

       pop  r27

       pop  r26

       #endasm

 

       delay_us(4);  //adjust to center image on screen

 

       //blast 16 bytes to the screen

       #asm

       ;but first a macro to make the code shorter

       ;the macro takes a register number as a parameter

       ;and dumps its bits serially to portD.6

       ;the nop can be eliminated to make the display narrower

       .macro videobits ;regnum

        BST  @0,7

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,6

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,5

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,4

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,3

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,2

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,1

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

 

      BST  @0,0

      IN   R30,0x12

      BLD  R30,6

      nop

      OUT  0x12,R30

       .endm

 

      videobits r4 ;video line -- byte 1

        videobits r5 ;byte 2

        videobits r6 ;byte 3

        videobits r7 ;byte 4

        videobits r8 ;byte 5

        videobits r9 ;byte 6

        videobits r10 ;byte 7

        videobits r11 ;byte 8

        videobits r12 ;byte 9

        videobits r13 ;byte 10

        videobits r14 ;byte 11

        videobits r15 ;byte 12

        videobits r16 ;byte 13

        videobits r17 ;byte 14

        videobits r18 ;byte 15

        videobits r19 ;byte 16

      clt   ;clear video after the last pixel on the line

      IN   R30,0x12

      BLD  R30,6

      OUT  0x12,R30

 

       pop r19

       pop r18

       pop r17

       pop r16

       pop r15

       pop r14

 

       pop r31

       pop r30

       pop r27

       pop r26

       pop r25

       pop r24

       pop r23

       pop r21

       pop r14

       pop r13

       #endasm

 

    end

end

#pragma warn+

 

//==================================

//plot one point

//at x,y with color 1=white 0=black 2=invert

#pragma warn-

void video_pt(char x, char y, char c)

begin

 

      #asm

      ;  i=(x>>3) + ((int)y<<4) ;   the byte with the pixel in it

 

      push r16

      ldd r30,y+2             ;get x

      lsr r30

      lsr r30

      lsr r30                 ;divide x by 8

      ldd r12,y+1             ;get y

            lsl r12                 ;mult y by 16

            clr r13

      lsl r12

      rol r13

      lsl r12

      rol r13

      lsl r12

      rol r13

      add r12, r30     ;add in x/8

 

      ;v2 = screen[i];   r5

        ;v3 = pos[x & 7];  r6

      ;v4 = c            r7

      ldi r30,low(_screen)

      ldi r31,high(_screen)

      add r30, r12

      adc r31, r13

      ld r5,Z           ;get screen byte

      ldd r26,y+2             ;get x

      ldi r27,0

      andi r26,0x07           ;form x & 7

      ldi r30,low(_pos*2)

      ldi r31,high(_pos*2)

      add r30,r26

      adc r31,r27

      lpm r6,Z

      ld r16,y          ;get c

 

       ;if (v4==1) screen[i] = v2 | v3 ;

       ;if (v4==0) screen[i] = v2 & ~v3;

       ;if (v4==2) screen[i] = v2 ^ v3 ;

 

       cpi r16,1

       brne tst0

       or  r5,r6

       tst0:

       cpi r16,0

       brne tst2

       com r6

       and r5,r6

       tst2:

       cpi r16,2

       brne writescrn

       eor r5,r6

       writescrn:

            ldi r30,low(_screen)

      ldi r31,high(_screen)

      add r30, r12

      adc r31, r13

      st Z, r5          ;write the byte back to the screen

 

      pop r16

      #endasm

 

end

#pragma warn+

 

//=====================================

 

//plot a line

//at x1,y1 to x2,y2 with color 1=white 0=black 2=invert

//NOTE: this function requires signed chars

//Code is from David Rodgers,

//"Procedural Elements of Computer Graphics",1985

void video_line(char x1, char y1, char x2, char y2, char c)

begin

      int e;

      signed char dx,dy,j, temp;

      signed char s1,s2, xchange;

        signed char x,y;

 

      x = x1;

      y = y1;

      dx = cabs(x2-x1);

      dy = cabs(y2-y1);

      s1 = csign(x2-x1);

      s2 = csign(y2-y1);

      xchange = 0;

      if (dy>dx)

      begin

            temp = dx;

            dx = dy;

            dy = temp;

            xchange = 1;

      end

      e = ((int)dy<<1) - dx;

      for (j=0; j<=dx; j++)

      begin

            video_pt(x,y,c) ;

            if (e>=0)

            begin

                  if (xchange==1) x = x + s1;

                  else y = y + s2;

                  e = e - ((int)dx<<1);

            end

            if (xchange==1) y = y + s2;

            else x = x + s1;

            e = e + ((int)dy<<1);

      end

end

//==========================================================

//return the value of one point

//at x,y with color 1=white 0=black 2=invert

char video_set(char x, char y)

begin

      //The following construction

      //detects exactly one bit at the x,y location

      i=((int)x>>3) + ((int)y<<4) ;

    return ( screen[i] & 1<<(7-(x & 0x7)));

end

//============================================================

 

void main(void)

begin

  initialize(); // set up the ports and timers

 

   //The following loop executes once/video line during lines

  //1-230, then does all of the frame-end processing

  while(1)

  begin

 

    //stall here until next line starts

    //sleep enable; mode=idle

    //use sleep to make entry into sync ISR uniform time

 

    #asm ("sleep");

 

    //The following code executes during the vertical blanking

    //Code here can be as long as

    //a total of 60 lines x 63.5 uSec/line x 8 cycles/uSec

 

    if (LineCount==231)

    begin

          cmdbyte = talk0;

          if(~PINA==0x01) //SW0

                  mode=1;    //cursor repositioning mode

          if(~PINA==0x02) //SW1

          {

            mode=2;    //line drawing mode

            count=1;

          }

          if(~PINA==0x04) //SW2

          {

            mode=3;   //clearing screen

            count=0;

          }

          TheTask();

      end  //line 231

  end  //while

end  //main

 

//================================================

void initialize(void)

{

      int j;

      //initialize portB for debugging

      DDRB=0xff;     //output

      PORTB = 0xff;  //leds off 

     

      //initialize portA for switches

      DDRA=0x00;     //input

 

      //initialize portC.0 to be adb signal

      DDRC =0x00;

      PORTC = 0xff;    //float it high

 

      //initialize usart to enable Tx

      UCSRB = 0x08;

      UBRRL= 0x67;     //baud rate set to 9600

 

      //init counter0 for 4us per tick

      //for ADB protocol

      TCCR0 = 0x03;

     

     

      //debugging

    /*txchar= 'H';

      UAputc();

      txchar='E';

      UAputc();

      txchar ='L';

      UAputc();

      txchar ='L';

      UAputc();

      txchar ='O';

      UAputc();

      txchar ='!';

      UAputc();*/

 

      for (j=0;j<=10;j++) //clear response buffer

      {

     buffer[j]=0;

    }

 

  //init timer 1 to generate sync

  OCR1A = lineTime;     //One NTSC line

  TCCR1B = 9;           //full speed; clear-on-match

  TCCR1A = 0x00;  //turn off pwm and oc lines

  TIMSK = 0x10;         //enable interrupt T1 cmp

 

  //init ports

  DDRD = 0xf0;          //video out and switches

  //D.5 is sync:1000 ohm + diode to 75 ohm resistor

  //D.6 is video:330 ohm + diode to 75 ohm resistor

 

 

  //initialize synch constants

  LineCount = 1;

  syncON = 0b00000000;

  syncOFF = 0b00100000;

 

  //initial display position at center of the screen

  currX=64;

  currY=50;

  alreadydrawn=0; // to keep track while cursor repositioning and line drawing

  count=1;  //to keep track of frames (even and odd)

  mode=1;  //mode selection from switches

 

 

  //side lines

  #define width 126

  video_line(0,0,0,99,1);

  video_line(width,0,width,99,1);

 

  //top line & bottom lines

  video_line(0,0,width,0,1);

  video_line(0,99,width,99,1);

 

               

 

  //enable sleep mode

  MCUCR = 0b10000000;

  #asm ("sei");

}

 

//===================================================================================

//get input from touchpad and display on TV

void TheTask(void)

{

      int ind;

      char dy=0, dx=0; //increments per frame

      char datamask=0b01111111;

      DDRC=0x00;    //initialize portc.0 to be adb signal

      PORTC=0xff;  //float it high

      bytenum= 2;    //# of bytes in response

      switch (mode)

      begin

          case 1:

                        sendcmd();

                        resp=1;     //to check if new input      was   received

                        getresp();

                        if (resp ==1)

                        {                

                              if (((buffer[0]   & 0x80)==0x00)&&(alreadydrawn==0)) //for repositioning ie touchpad button pressed

                                    video_pt(currX,currY,0);  //delete old point

 

                              //the sign of the deltax and deltay      determine up, down,     left, right direction

                              dy=   ((buffer[0] & datamask)>>6);

                              dx=   ((buffer[1] & datamask)>>6);

                             if ((buffer[1] & datamask) !=0)

                              {

                                    if (dx==0)//right

                                    {

                                          currX= currX+1;      //bits

                                          if (currX>=126)      currX=125;

                                    }

                                    else  //left

                                    {

                                          currX= currX-1;

                                          if (currX<=0) currX=0;

                                    }

                              }

 

                             if ((buffer[0] & datamask) !=0)

                              {

                                    if (dy==0) //down

                                    {

                                          currY= currY+1;

                                          if (currY>=99) currY=99;

                                    }

                                    else  //up

                                    {

                                          currY= currY-1;   //linenumber

                                          if (currY<=0) currY=0;

                                    }

                              }

                              alreadydrawn=0; //check if cursor moving over an already drawn point (then don't delete)

                              if ((video_set(currX,currY))&&(((buffer[0] & 0x80)==0x00)))

                                    alreadydrawn =1;       

                              video_pt(currX,currY,1); //draw new point

                        }

                        break;

           case 2:    //Draw Line

                        count++; //check even or odd frame (alternate frame get new input, update new input to screen )

                        //to maintain TV timing

                        if((count%2)==0)  // get input from      touchpad

                        {

                              sendcmd();

                              resp=1;

                              getresp();

                              if    (resp==1)

                              {

                                    //the sign  of the deltax and deltay determine up, down, left, right direction

                                    dy= ((buffer[0] & datamask)>>6);

                                    dx= ((buffer[1] & datamask)>>6);

 

                                    intX=currX; //to be able to see point while moving across the screen

                                    intY=currY; //when drawing the line

 

                                    if    (((buffer[0] & 0x80)==0x00)      && (alreadydrawn==0))   //   first point of line

                                          video_pt(intX,intY,1);

 

                                    if    ((buffer[1] & datamask)   !=0)

                                    {

                                          switch      (dx)

                                          begin

                                                case 0:  //right

                                                      currX=      currX+1; //bits

                                                      if      (currX>=126) currX=125;

                                                      break;

                                                case 1: //left           

                                                      currX=      currX-1;

                                                      if      (currX<=0) currX=0;

                                                      break;

                                      end //switch

                                    }

                                    if    ((buffer[0] & datamask)   !=0)

                                    {

                                          switch      (dy)

                                          begin

                                                case 0:  //down

                                                      currY=      currY+1; //bits

                                                      if      (currY>=99) currY=99;

                                                      break;

                                                case 1: //up                                   

                                                      currY=      currY-1;

                                                      if      (currY<=0) currY=0;

                                                      break;

                                      end //switch

                                    }            

                                    video_pt(currX,currY,1);

                              }

                        }

                        else //update screen array ie TV display

                        {    

                              if    ((buffer[0] & 0x80)==0x00)      //if button pressed                 

                              {

                                    if(alreadydrawn!=0)      // while drawing line (cursor movement)

                                    {

                                          video_pt(intX,intY,0);                                           

                                    }

                                    else  //first point of line

                                    {

                                          firstX=currX;

                                          firstY=currY;

                                          alreadydrawn=1;  

                                          video_pt(intX,intY,1);                                           

                                    }

                              }

                              else

                              {

                                    if    (alreadydrawn==1)  //if  button press is   released for first time

                                    {

                                          video_line(firstX,firstY,currX,currY,1); //line complete

                                          alreadydrawn=0;

                                    }    

                              }

                        }//end of frame conditions   

                        break;

          //================================================================================                

           case 3:  //delete whole screen

                              if    ((count%2)==0) //done in two frames to maintain TV timing

                              {

                                   for (ind=0;ind<800;ind++)

                                    {

                                          screen[ind]=0;

                                    }                                        

                                    //topline

                                    video_line(0,0,width,0,1);   

                                   //side lines (upper half)

                                    video_line(0,0,0,50,1);

                                    video_line(width,0,width,50,1);          

                              }

                              else

                              {

                                    for (ind=800;ind<1600;ind++)

                                    {

                                          screen[ind]=0;

                                    }          

                                    //bottom lines            

                                    video_line(0,99,width,99,1); 

                                   //side lines (lower half)

                                    video_line(0,50,0,99,1);

                                    video_line(width,50,width,99,1);

                                    mode=1; //revert back to cursor repositioning mode

                                    currX=64; //initialize to center of screen

                                    currY=50;                    

                              }

                              count++;

                              break;

    end //switch

}

//=======================================================================

//send character to hyperterminal (used for debugging)

void UAputc(void)

{

      #asm

      UAputclp:

            sbis 0x0b, 5   ;UCSRA   =$0b UDRE   =5 , UDR    =$0c

            rjmp UAputclp

      #endasm

      UDR=txchar;

}

//=======================================================================

//send touchpad command (talk0 for normal operation)

void sendcmd(void)

{

      #asm

            ;PORTC      =$15, DDRC  =$14 ,TCNT0 =$32

            .def  bitcnt      =r23

            ldi temp, $01      ;portc.0=adb output

            out 0x14, temp

            out 0x15, temp

            ldi temp, $00      ;attention

            out 0x15, temp

            out 0x32, temp

      wattn:  in temp, 0x32

            cpi temp, 200

            brne wattn

            ldi temp, $01      ;sync

            out 0x15, temp

            out 0x32, temp

      wsync:  in temp, 0x32

            cpi temp, 16

            brne wsync

            ldi bitcnt, 8

      sdbtlp:

            ldi temp, $00

            out 0x15, temp

            out 0x32,temp

            rol r13

            brcs wait36

      wait64:     in temp, 0x32

            cpi temp, 16

            brlt wait64

            rjmp lowdone

      wait36:     in temp, 0x32

            cpi temp, 9

            brlt wait36

      lowdone:ldi temp, $01

            out 0x15, temp

      celldn:     in temp, 0x32

            cpi temp, 25

            brlt celldn

            dec bitcnt

            brne sdbtlp

            ldi temp, $00     ;stop bit

            out 0x15, temp

            out 0x32, temp

      wstop:  in temp, 0x32

            cpi temp, 18

            brlt wstop

            ldi temp, $01     ;stop bitcell high part

            out 0x15, temp

            ldi temp, $00     ;reload timer to keep check on stop till start time (200+28)

            out 0x32, temp

      wstos:  in temp, 0x32

            cpi temp, 56

            brlt wstos

            ldi temp, $00     ;wait for responce

            out 0x14, temp

            ldi temp, $01     ;float pin high

            out 0x15, temp

      #endasm

}

//=======================================================================

//get motion bytes from touchpad

void getresp(void)

{

      #asm

            ; PINC      =$13

            .def  inbyte      =r21

            .def  bitcnt      =r23

            ldi r30, low(_buffer) ;init buffer to store response

            ldi r31, high(_buffer) ;this is 'Z'

            ldi r26, low(_resp) ;init response

            ldi r27, high(_resp);this is 'X'

            mov r25,r14

      stgetresp:

            in temp, 0x32

            cpi temp, 58        ;(200+28)/4 + some leeway

            brmi continue

            ;rjmp resend       ;if high time greater than 200us then resend command

            ;ld r24, x            ; set flag to show that no response is sent

            ldi r24 , 0x00

            st x, r24

            rjmp endloop

      continue:

            in temp, 0x13

            sbrc temp, 0

            rjmp stgetresp      ;wait for start bit

 

            in temp,0x13

            sbrs temp, 0

            rjmp continue

      bytelp:

            ldi inbyte, $00

            ldi bitcnt, 8

      gtbtlp: lsl inbyte

      wforlw: sbic 0x13, 0

            rjmp wforlw

            ldi temp, $00

            out 0x32, temp

      wforhi: sbis 0x13, 0

            rjmp wforhi

            in temp, 0x32

            cpi temp , 13

            brge got0

            ori inbyte, $01

      got0:

            dec bitcnt

            brne gtbtlp

            st z+, inbyte

            dec r25

            brne bytelp

      wstlw:      sbic 0x13, 0

            rjmp wstlw

      wsthi:  sbis 0x13, 0

            rjmp wsthi

            ldi temp, 0x01  ;float signal line high.

            out 0x15, temp

      endloop:

#endasm

}

//=======================================================================

//send bytes (in binary form) to hyperterminal. used for debugging

void UAputbyte(void)

{

#asm

      .def  bitcnt      =r23

      .def txc     =r24

      ldi r26, low(_buffer) ;re-init buffer to tx response

      ldi r27, high(_buffer) ;this is 'X'

      mov r25, r14

      push temp

stUAputbyte:

 

      ldi bitcnt, 8

      ld temp, x+

txlp: tst bitcnt

      breq txlpdn

      ldi txc, 0b10000000

      and txc, temp

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      lsr txc

      subi txc, -'0'

      sts _txchar, txc

      rcall _UAputc

      dec bitcnt

      lsl temp

      rjmp txlp

txlpdn: ldi txc, $0d  ;tx newline

   sts _txchar, txc

      rcall _UAputc

      ldi txc, $0a

      sts _txchar, txc

      rcall _UAputc

 

      dec r25

      brne stUAputbyte

      pop temp

#endasm

}

 

 

 

 

Go Back

ps2_tp.asm

 

; modified file from original (ANDREW FIORE)

; Spring 2003/EE476/Cornell University

 

.nolist

 

.include "c:\definitions\m32def.inc"

 

.list

 

 

 

;***** register variables

 

.def  temp  =r16

.def  save  =r17        ;saves the SREG in ISRs

.def  clock =r18

.def  bitcnt      =r19

.def  delayLO     =r20

.def  delayHI     =r21

.def  inByte      =r22

.def  outByte =r23

.def  parity      =r24

.def  stop  =r25

.def  TXchar      =r26

.def  bytenum     =r27

.def  bitmask     =r28

.def  delaydone = r1

 

.equ  t0on        = 0b00001011      ; prescale by 64 for 4 ms ticks

                              ; reset on t0comp match

.equ  t0off       = 0x00

.equ  timercnt    = 0xc8

.equ  loopcnt     = 0x7d

.equ  baud96      =103  ;9600 baud constant for 16Mhz crystal

 

 

.cseg

 

.MACRO setClockLow

      cbi   portC, 0

.ENDMACRO

 

.MACRO setClockHigh

      sbi   portC, 0

      ; Delays to allow pull-up charging

      push temp

      ldi temp, 5

noplp:      nop   ; 1 usec delay thus total 5usec

      nop

      nop

      nop

      nop

      nop

      nop

      nop

      nop

      nop

      nop

      nop

      dec temp

      brne noplp

      pop temp

.ENDMACRO

 

.MACRO waitForDataLow

      push  temp

wfdl: in    temp, pinC

      andi  temp, 0b00000010

      brne  wfdl

      pop   temp

.ENDMACRO

 

.MACRO waitForDataHigh

      push  temp

wfdh: in    temp, pinC

      andi  temp, 0b00000010

      breq  wfdh

      pop   temp

.ENDMACRO

 

 

.MACRO waitForClockLow

      push  temp

wfcl: in    temp, pinC

      andi  temp, 0b00000001

      brne  wfcl

      pop   temp

.ENDMACRO

 

.MACRO waitForClockHigh

      push  temp

wfch: in    temp, pinC

      andi  temp, 0b00000001

      breq  wfch

      pop   temp

.ENDMACRO

 

.MACRO crlf

      ldi   TXchar, 0x0d

      rcall UAputc

      ldi   TXchar, 0x0a

      rcall UAputc

.ENDMACRO

 

.MACRO delay1sec

      ldi   delayLO, timercnt

      ldi   delayHI, loopcnt

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

      rcall delay

.ENDMACRO

 

;     Interrupt vectors

 

.org $0000

; FOR 8535

      rjmp reset ;reset entry vector

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

      reti

 

.org $0014

      rjmp  t0match     ;timer 0 compare match ISR

      reti

      reti

      reti

      reti

      reti

      reti

      reti

 

 

 

 

;     Main program entry point on reset

 

 

 

reset:ldi   temp, LOW(RAMEND) ;setup stack pointer

      out   SPL, temp

      ldi   temp, HIGH(RAMEND)

      out   SPH, temp

 

      ;define PORTB to be LEDs for debugging

serTemp;set PORTB to be

outDDRB,Temp;all outputs

ldiTemp, 0x00;and turn them on

outPortB, Temp

 

      ;define PORTC to be touchpad

ldiTemp, 0b00000001;D0 is clock (output)

outDDRC,Temp;D1 is data (input)

 

      ldi   temp, 0b00000010; let data float high, clock low

      out   portC, temp

      ldi   bytenum, 0

 

      ;setup UART -- enable TX pin

      ldi   temp, 0b00001000

      out   UCSRB, temp

      ;set baud rate to 9600

      ldi   temp, baud96

      out   UBRRL, temp

 

      sei

 

 

main: crlf

      crlf

      ldi   TXchar, 'H'

      rcall UAputc

      ldi   TXchar, 'e'

      rcall UAputc

      ldi   TXchar, 'l'

      rcall UAputc

      ldi   TXchar, 'l'

      rcall UAputc

      ldi   TXchar, 'o'

      rcall UAputc

      ldi   TXchar, '.'

      rcall UAputc

      crlf

 

      ;rcall      getByte

      ;rcall      UAputbyte

 

      ;rcall      getByte

      ;rcall      UAputbyte

 

      ldi   outByte, 0xF4; command == enable

      rcall putByte

 

      crlf

      ldi   TXchar, 'H'

      rcall UAputc

      crlf

 

      rcall getByte

      rcall UAputbyte

 

 

 

      ldi   outByte, 0xE9; command == status

      rcall putByte

 

      rcall getByte

      rcall UAputbyte

      clr   bytenum

mainlp:

      rcall getByte

      mov   TXchar, bytenum

      subi  TXchar, -'0'

      cpi   bytenum, 9

      brne  noBnRs

      clr   bytenum

noBnRs:     rcall UAputc

      ldi   TXchar, '='

      rcall UAputc

      rcall UAputbyte

      rjmp  mainlp

 

;     mov   temp, bytenum

;     ori   temp, 0b10000000

;     com   temp

;     out   portB, temp

;     delay1sec

;     delay1sec

;     com   inByte

;     out   portB, inByte

;     delay1sec

;     delay1sec

;     rjmp  mainlp

 

UAputbyte:

      push  temp

      ldi   bitcnt, 8

      mov   temp, inbyte

bitlp:      tst   bitcnt

      breq  btlpdn

      ldi   TXchar, 0b10000000

      and   TXchar, temp

      lsr   TXchar

      lsr   TXchar

      lsr   TXchar

      lsr   TXchar

      lsr   TXchar

      lsr   TXchar

      lsr   TXchar

      subi  TXchar, -'0'

      rcall UAputc

      dec   bitcnt

      lsl   temp

      rjmp  bitlp

btlpdn: crlf

      pop   temp

      ret

 

 

; CALL STATE:idle

; RETURN STATE: inhibit

getByte:push      temp

      ldi   temp, 0b00000000  ; data, clk are inputs

      out   DDRC, temp

      ldi   temp, 0b00000011

      out   portC, temp       ; float data, clk high

      clr   inByte

      ldi   bitcnt, 8

      clr   parity

      waitForClockLow         ; discard start bit

      waitForClockHigh

      ldi   bitmask, 0b00000001

 

gbLoop:     tst   bitcnt

      breq  gbLpDn

      waitForClockLow

      in    temp, pinC

      waitForClockHigh

      andi  temp, 0b00000010

      breq  gbLp2

      inc   parity

      or    inByte, bitmask

gbLp2:      lsl   bitmask

      dec   bitcnt

      rjmp  gbLoop

 

gbLpDn: waitForClockLow

      in    parity, pinC

      andi  parity, 0b00000010

      waitForClockHigh

      waitForClockLow

      in    stop, pinC

      andi  stop, 0b00000010

 

      ; enter inhibit mode:pull clock low

      ldi   temp, 0b00000001

      out   DDRC, temp

      ldi   temp, 0b00000010  ; keep data floating high, set clock low

      out   portC, temp

      inc   bytenum

 

      pop   temp

      ret

 

; CALL STATE: inhibit

; RETURN STATE: inhibit

putByte:push      temp

      push  outByte

      ldi   temp, 0b10000000

      and   temp, outByte

      lsl   outByte           ; put bit 0 into the bit 1 position so it will go out first

      tst   temp        ; see whether high bit of outByte was set before shift

      breq  pbA

      ori   outByte, 0x01     ; if so, put high bit's 1 into low bit position

pbA:  ldi   bitcnt, 8

      clr   parity

 

ldiTemp, 0b00000001;D0 is clock (output)

outDDRC,Temp;D1 is data (input)

      ldi   temp, 0b00000010; float data high, pull clock low

      out   portC, temp

 

      ldi   delayHI, 1

      ldi   delayLO, 38 ; delay for 152 usec

      rcall delay

 

;ldiTemp, 0b00000011;D0 is clock (output)

;outDDRC,Temp;D1 is data (output)

;     ldi   temp, 0b00000000; pull data low, keep clock low

;     out   portC, temp

 

ldiTemp, 0b00000010;D0 is clock (input)

outDDRC,Temp;D1 is data (output)

      ldi   temp, 0b00000001; keep data low, float clock high

      out   portC, temp

 

 

pbLoop:     tst   bitcnt

      breq  pbLpDn

      waitForClockLow

      mov   temp, outByte

      andi  temp, 0b00000010

      ori   temp, 0x01  ; be sure to keep clock floating high

      out   portC, temp

      waitForClockHigh

      cbr   temp, 0x01

      tst   temp

      breq  pbLp2

      inc   parity

pbLp2:      ldi   temp, 0b00000001

      and   temp, outByte

      lsr   outByte           ; slide bits right to move next one into bit 1 position

      tst   temp        ; see whether low bit of outByte was set before shift

      breq  pbB

      ori   outByte, 0b10000000     ; if so, put low bit's 1 into high bit position

pbB:  dec   bitcnt

      rjmp  pbLoop

 

pbLpDn: ror outByte           ; get outByte's bits into original positions

      waitForClockLow

      inc   parity

      andi  parity, 0x01

      lsl   parity

      mov   temp, parity

      ori   temp, 0x01  ; be sure to keep clock floating high

      out   portC, temp

      waitForClockHigh

      waitForClockLow

ldiTemp, 0b00000000;D0 is clock (input)

outDDRC,Temp;D1 is data (input)

      ldi   temp, 0b00000011; and float them high

      out   portC, temp

      waitForClockHigh

      waitForClockLow

      waitForClockHigh

;     waitForDataLow

;     waitForDataHigh

ldiTemp, 0b00000001;D0 is clock (output)

outDDRC,Temp;D1 is data (input)

      ldi   temp, 0b00000010  ; data stays floating high, clk pulled low

      out   portC, temp

 

      pop   outByte

      pop   temp

      ret

 

 

 

UAputc:     sbis  UCSRA, UDRE ;wait until clear then send one char

      rjmp  UAputC

      out   UDR, TXchar

      ret

 

; delay spins for 4*number stored in delayLO*number stored in delayHI

delay:      push temp

loop1:outTCNT0, delayLO

lditemp, t0on

outTCCR0, temp

lditemp, 0b00000010

outTIMSK, temp

clrtemp

movdelaydone, temp

dlylp:      tst   delaydone

      breq  dlylp

      ; NOTE: counter is stopped in t1matchA ISR

      decdelayHI

      brneloop1

dlydn:

      pop   temp

      ret

 

 

 

t0match:

      in    save, SREG

      push  temp

      ldi   temp,t0off

      out   TCCR0, temp; stop the counter

      ldi   temp,0b00000000   ;disable t0comp interrupt

      out   TIMSK, temp

      ser   temp

      mov   delaydone, temp

      ;------------

 

      outportB, temp

 

;--------------

      pop   temp

      out   SREG, save

      reti

Go Back