;Blair Lee ;John McDonald ;EE 476 Final Project ;RC Car - TRANSMITTER ;PORTA is used for speed control input. ;PORTB is used for pushbutton input. ;PORTC is used for steering control input. ;PORTD is used for serial output. .include "4414def.inc" .def savSREG =r16 ;save the status register .def TXbusy =r17 ;transmit busy flag .def TXflash =r18 ;text to be sent is in flash if <> 0 .def command =r19 ;command register .def temp =r20 ;general-purpose temporary register .def Volt =r21 ;ADC sample value .def Count =r22 ;a counter .def LEDReg =r23 ;register to store LED output (debug) .def debounce =r24 ;debounce ON or OFF .def DBcnt =r25 ;debounce counter .def status =r26 ;running and lights status .def release =r27 ;button release register .def temp2 =r28 ;another temporary register .equ baud96 =25 ;9600 baud constant for 4Mhz crystal .equ SpdMid =0x0c ;midpoint for fwd-back control .equ StrMid =0x0c ;midpoint for left-right control .equ FwdOffset=0xfd ;forward offset .equ RevOffset=0xfc ;reverse offset .equ LftOffset=0xfd ;left offset .equ RgtOffset=0xfd ;right offset .equ OFF =0x00 ;off .equ ON =0xff ;on .equ AADCDO =1 ;ADC data out .equ AADCCLK =2 ;ADC clock .equ AADCCS =3 ;ADC chip-select .equ AADCDI =4 ;ADC data in .equ CADCDO =1 ;ADC data out .equ CADCCLK =2 ;ADC clock .equ CADCCS =3 ;ADC chip-select .equ CADCDI =4 ;ADC data in .equ TOP =4 ;top hat switch .equ TRIG =5 ;trigger switch .equ SWmask =0x30 ;switch mask .equ Maxlights=0x04 ;nuumber of light modes .equ fwdcmd =0x00 ;forward prefix .equ bakcmd =0x10 ;backward prefix .equ lftcmd =0x20 ;left prefix .equ rgtcmd =0x30 ;right prefix .equ gocmd =0x40 ;lights prefix .equ stpcmd =0x50 ;other prefix .equ But1 =0x01; .equ But2 =0x02; .equ But3 =0x04; .equ But4 =0x08; .equ But5 =0x10; .equ But6 =0x20; .equ But7 =0x40; .equ But8 =0x80; ;======================================================== ; Toggle ADC Clock - PORTA ;ADC reads and outputs data on falling edge of the clock .MACRO A_CLOCKPULSE sbi PORTA, AADCCLK ;CLK high nop cbi PORTA, AADCCLK ;CLK low nop .ENDMACRO ;======================================================== ; Toggle ADC Clock - PORTC ;ADC reads and outputs data on falling edge of the clock .MACRO C_CLOCKPULSE sbi PORTC, CADCCLK ;CLK high nop cbi PORTC, CADCCLK ;CLK low nop .ENDMACRO ;======================================================== ;************************ .dseg ;define variable strings to be tranmitted from RAM cntstr: .byte 2 ;************************ .cseg .org $0000 rjmp Reset ;reset entry vector reti reti reti reti reti reti reti reti reti rjmp TXempty ;UART buffer empty rjmp TXdone ;UART transmit done reti RESET: cli ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, temp ldi temp, HIGH(RAMEND) out SPH, temp ;initial conditions clr TXbusy ;start out not busy on TX ;setup UART -- enable TXempty & RXdone int, and RX, TX pins ldi temp, 0b00101000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ;initialize ADCs on ports A and C ldi temp, 0b00011101 ;power ADC and set AADCCS out DDRA, temp ldi temp, 0b00001001 ;power ADC and set AADCCS out PORTA, temp ldi temp, 0b00011101 ;power ADC and set CADCCS out DDRC, temp ldi temp, 0b00001001 ;power ADC and set CADCCS out PORTC, temp ;set up leds on port B ldi temp, 0b00000011 ;input from switches on joystick out DDRB, temp out PORTB, temp ;debounce setup clr debounce ;debounce on or off clr DBcnt ;debounce counter clr status ;initialize car to off sei ;*********************Setup and Read Speed********************* Getspd: clr Volt ldi Count, 5 ;get top 5 bits A_CLOCKPULSE cbi PORTA, AADCCS ;initiate conversion A_CLOCKPULSE sbi PORTA, AADCDI ;startbit A_CLOCKPULSE sbi PORTA, AADCDI ;single ended A_CLOCKPULSE cbi PORTA, AADCDI ;channel 0 A_CLOCKPULSE ReadA: A_CLOCKPULSE clc ;clear carry sbic PINA, AADCDO sec ;set carry if high rol Volt dec Count brne ReadA ;more bits remaining ldi Count, 8 IgnoreA:A_CLOCKPULSE dec Count brne IgnoreA ;ignore lsb first data sbi PORTA, AADCCS ;conversion complete ;***********************Transmit Speed*********************** _bakCmd: cpi Volt, SpdMid brlt _fwdCmd cpi Volt, SpdMid breq _stpCmd lsr Volt subi Volt, RevOffset ori Volt, bakcmd mov command, Volt rjmp Sendspd _fwdCmd: ldi temp, SpdMid sub temp, Volt subi temp, FwdOffset ori temp, fwdcmd mov command, temp rjmp Sendspd _stpCmd: ldi command, 0x00 Sendspd: ; rcall LEDSt rcall SendMsg ;********************Setup and Read Steering******************** Getstr: clr Volt ldi Count, 5 ;get top 5 bits C_CLOCKPULSE cbi PORTC, CADCCS ;initiate conversion C_CLOCKPULSE sbi PORTC, CADCDI ;startbit C_CLOCKPULSE sbi PORTC, CADCDI ;single ended C_CLOCKPULSE cbi PORTC, CADCDI ;channel 0 C_CLOCKPULSE ReadC: C_CLOCKPULSE clc ;clear carry sbic PINC, CADCDO sec ;set carry if high rol Volt dec Count brne ReadC ;more bits remaining ldi Count, 8 IgnoreC:C_CLOCKPULSE dec Count brne IgnoreC ;ignore lsb first data sbi PORTC, CADCCS ;conversion complete ;***********************Transmit Steering*********************** _rgtCmd: cpi Volt, StrMid brlt _lftCmd cpi Volt, StrMid breq _ctrCmd lsr Volt subi Volt, RgtOffset ori Volt, rgtcmd mov command, Volt rjmp Sendstr _lftCmd: ldi temp, StrMid sub temp, Volt subi temp, LftOffset ori temp, lftcmd mov command, temp rjmp Sendstr _ctrCmd: ldi command, 0x00 ori command, rgtcmd Sendstr: ; rcall LEDSt rcall SendMsg ;***************************Get Status*************************** Getstat: cpi debounce, ON ;check if debounce is on breq _debounce in temp, PORTB cpi release, OFF ;check if buttons have been released breq _release ;buttons have been debounced and released sbic PINB, TRIG rjmp _trig _running: sbis PINB, TOP rjmp _status mov temp, status com temp andi temp, 0xf0 andi status, 0x0f or status, temp rjmp _status _trig: mov temp2, status andi temp2, 0x0f inc temp2 cpi temp, Maxlights brge _lightsoff rjmp _running _lightsoff: ori status, 0xf0 rjmp _running _debounce: inc DBcnt ;increment debounce counter breq _DBdone rjmp _release _DBdone: ldi debounce, OFF ;turn debounce off rjmp _release _release: ori temp, 0x30 brne _status ldi release, ON ;************************Transmit Status************************* _status: mov command, status ori command, 0xf0 breq _off _on: mov command, status ori command, 0x5f _off: mov command, status ori command, 0x4f rcall SendMsg rjmp GetSpd ;***************************Return******************************* ;****************** ;Pause procedure ;****************** ;_Wait: ; cli ;disable interrupts ; clr temp2 ;clear upper 8 bits of counter ;outerL: ; clr temp3 ;clear lower 8 bits of counter ;innerL: ; inc temp3 ; cpi temp3, 0 ; brne innerL ; inc temp2 ; cpi temp2, 255 ; brne outerL ; sei ;here the outer loop is complete; approx. 1 ms has passed ; ret ;return from wait subroutine ;******************* ;message sending sub ;******************* SendMsg: ldi ZL, LOW(cntstr) ;ptr to RAM ldi ZH, HIGH(cntstr) inc ZL st Z, command ld r0,Z out UDR, r0 ;fire off the UART transmit clr TXflash ;the string is in RAM ser TXbusy ;and set the TX busy flag sbi UCR, UDRIE ;enable the TXempty interrupt rcall TXwait ret ;****************** ;Debug procedure ;****************** LEDSt: mov LEDReg, command com LEDReg ;invert to send correct output to leds out PORTB, LEDReg ret ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;UART stuff follows. ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ; UART needs a character TXempty:in savSREG, SREG ;save processor status tst TXflash ;Is the string in flash memory? breq TXram ;If not, it is in RAM inc ZL ;get the next char from flash lpm ;and put it in r0 rjmp TXfls TXram: inc ZL ;get the next char from RAM ld r0,Z TXfls: tst r0 ;if char is zero then exit breq TXend out UDR, r0 ;otherwise transmit it rjmp TXexit ;exit until next char TXend: clr TXbusy ;no more chars cbi UCR, UDRIE ;clear the TXempty interrupt TXexit: out SREG, savSREG ;restore proc status reti ;back to pgm ; TX done -- buffer is empty -- unused here TXdone: in savSREG, SREG ;save processor status out SREG, savSREG ;restore proc status reti ;back to pgm ;***************************** ;subroutine TXwait: tst TXbusy ;now wait for the tranmission to finish brne TXwait ret