APPENDIX B: Code
.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
#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
}
//Electronic drawing board
//Input=Touchpad
//Output=TV screen
//Dalia
//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
}
; modified file from
original (ANDREW FIORE)
; Spring 2003/EE476/
.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