;*************************************** ;***** Analog out to AD557 DAC ********** ;**************************************** ;Makes a waveform of 256 points byte-wide data from ;PORTC at a variable sample rate of (1 to 255)*0.25 microsecond ;waits for about a variable time between waveforms (1 to 255)*5 mSec. ;produces 1-255 repeats of the waveform ; ;Header format: ;header bytes are transmitted as nibbles+32, 2 bytes each ; 0x00 this is the start-file flag ;samplerate (in 0.25 microsec ) ;number-of-repeats, ;delay-between-waves (in 5 mSec intervals) ; each of the above is TWO nibbles to be combined into ONE byte ;followed by 512 data bytes emcoded as byte pairs: ; (top nibble)+32 then (bottom nibble)+32 .include "d:\bruce\atmel\asm src\8515def.inc" .device AT90S8515 .def save =r1 ;save the SREG .def preload =r2 ;preload time0 for 10 Msec .def temp =r16 ;temporary register .def count =r17 ;number of waveforms to gen .def sample =r18 ;waveform sample .def itemp =r19 ;ISR temp variable .def delay =r20 ;t0 ovfl counter for long delay .def playbk =r21 ;playback flag .def cntmax =r22 ;maximum for count variable .def dlymax =r23 ;maximum for delay variable .def sampleT =r24 ;time for one wave sample .def RXchar =r25 ;a received character .def chrcnt =r26 ;character count for rs232 function .def datacnt =r27 ;data count for rs232 .def byte1 =r28 ;first incoming nibble (zeroed by code) ;remember that r30 and r31 are the Z register ;*********** ;constants .equ PreScal1=1 ;timer1 prescale by unity .equ ClrMatch=8 .equ baud96 =25 ;9600 baud constant for 4Mhz crystal ;***** Initialization .cseg .org $0000 rjmp RESET ;reset entry vector reti ;external intrupt not used reti reti rjmp CmpA ;compare A match reti reti ;T1ovfl ;timer 1 inter vector rjmp T0ovfl ;timer 0 interrupt vector reti rjmp RXdone ;rs232 receive reti reti reti RESET: ldi temp, LOW(RAMEND) ;setup stack pointer out SPL, Temp ldi Temp, HIGH(RAMEND) out SPH, Temp ;set up timer zero to overflow every 16 mSec ; but preload to make time 5 mSec ldi temp, 178 ;256 - 5/.064 mov preload, temp out TCNT0, preload ldi temp, 4 out TCCR0, temp ;prescale=256 one tick=64 microSec ;set up timer1 to clear on match reg A & prescale=1 ;ldi temp, PreScal1+ClrMatch ;prescalar and clear on match ;out TCCR1B, temp ldi temp, 0 ;disable timer1 until triggered in t0ovfl out TCCR1B, temp ;enable time0 ovfl and T1 match ldi temp, 0b01000010 ;enable the T1 match interrupt out TIMSK, temp ;and enable T0 overflow ;make port C an output port and set it to midrange ldi temp, 0xff out DDRC, temp ldi temp, 0x80 out PORTC, temp ;make port B an output port ldi temp, 0xff out DDRB, temp out PORTB, temp ;and turn off LEDS ;make port D an input port for pushbuttons clr temp out DDRD, temp ;setup UART -- enable RXdone int, and RX pins ldi temp, 0b10010000 out UCR, temp ;set baud rate to 9600 ldi temp, baud96 out UBRR, temp ;********************************************* ;Build a waveform from 0x100 to 0x1ff ; This default wave is for calibration ; It is: ; amp=0x80 for 100 samples ; amp=0xff for 100 samplse ; amp=0x00 for 50 samples ; amp=0x10 for 6 samples ; ldi sample, 0x80 clr ZL ;start triangle wave at RAM location ldi ZH,1 ;0x100 wavefm: st Z, sample cpi ZL, 100 ; brlo index ldi sample, 0xff ; cpi ZL, 200 brlo index ldi sample, 0x00 cpi ZL, 250 brlo index ldi sample, 0x10 index: adiw ZL, 1 ;increment pointer cpi ZL, 0 ;then see if 256 points written brne wavefm ;************************************************ ;get ready to playback the waveform ; initializing all variables ldi ZH, 1 ;init the waveform pointer clr ZL ldi cntmax, 4 ;default total num to play mov count, cntmax ;start number of times to play at max clr playbk ;start in no-play mode ldi dlymax, 15 ;default time between waveforms = 150 Msec clr delay ;interval between waveforms ldi sampleT,39 ;default sample time in ticks = 10 microsec sei playlp: sbic PIND, 2 ;if the PD2 button is pushed, play some more rjmp playlp ;otherwise wait cli ;critical section setup playback ser playbk ;playback active clr count ;number of waveforms clr delay ;interval between waveforms ldi temp, 0x00 ;set up sample time out OCR1AH, temp ;load the A comp reg HIGH BYTE first out OCR1AL, sampleT ;load the A-comp reg LOW BYTE cbi PORTB, 0 ;light the play LED sei ;end critical section rjmp playlp ;****************************************** ; t1 compare match -- ;which will be every sample of the waveform ;sends 256 samples, then disables itself by truning off the timer CmpA: in save, SREG ;save processor status ld sample, Z ;get the sample out PORTC, sample ;to DAC inc ZL ;update ptr with wraparound cpi ZL, 0 brne leave ldi itemp, 0 ;kill timer1 counter out TCCR1B, itemp leave: out SREG, save ;restore proc status reti ;back to pgm ;***************************************** ; t0 overflow sets waveform rep rate ; Several things happen here: ; The waveform rep rate counter 'delay' is incremented and checked ; If the delay counter maxes out AND playback mode is TRUE then ; the playback is started by reseting timer1 and setting a clock rate ; If the number of playback cycles 'count' is at max then stop ; timer1 clock and turn off the playback LED. T0ovfl: in save, SREG ;save processor status out TCNT0, preload ;set ovfl time to 5 mSec inc delay ;wait a while cp delay, dlymax ;enough time gone by? brne leavt0 ;if not leave tst playbk ;else; are we playing? breq leavt0 ;start playback ldi itemp,0 ;init timer1 out TCNT1H, itemp out TCNT1L, itemp ldi itemp, PreScal1+ClrMatch;start timer1 out TCCR1B, itemp clr delay ;start a new delay cycle cp count, cntmax ;and keep track of # times played breq stopit inc count rjmp leavt0 ;stop playback stopit: clr playbk ldi itemp, 0 ;kill timer1 counter out TCCR1B, itemp sbi PORTB,0 ;turn off play LED leavt0: out SREG, save ;restore proc status reti ;back to pgm ;****************************************** ; UART read a character RXdone: in save, SREG ;save processor status in RXchar, UDR ;get the character cpi RXchar, 0x00 ;ascii null is data stream reset char brne RXchr0 ;if not zero read the data stream clr playbk ;turn off the waveform clr chrcnt ;reset char counter clr datacnt ;reset data counter clr byte1 ;no data recieved yet ldi ZL, 0 ;ready for new data cbi PORTB, 7 ;turn on LED 7 ldi itemp, 0 ;freeze timer0 out TCCR0, itemp rjmp RXexit RXchr0: cpi chrcnt, 0 ;first byte is sample time brne RXchr1 ;in units of 0.25 microSec tst byte1 ;see if first byte is received brne strate ;if so, the current RXchar must be low-nibble mov byte1, RXchar ;save the high-order nibble rjmp RXexit ;and wait for low-order nibble strate: subi byte1, 32 subi RXchar, 32 andi RXchar, 0x0f ;zero the high order bits andi byte1, 0x0f ;ditto swap byte1 ;form upper nibble or RXchar, byte1 ;form byte value sample clr byte1 subi RXchar, 1 ;timer1 is ZERO based mov sampleT, RXchar inc chrcnt rjmp RXexit RXchr1: cpi chrcnt, 1 ;second byte is number of waveforms brne RXchr2 tst byte1 ;see if first byte is received brne stnum ;if so, the current RXchar must be low-nibble mov byte1, RXchar ;save the high-order nibble rjmp RXexit ;and wait for low-order nibble stnum: subi byte1, 32 subi RXchar, 32 andi RXchar, 0x0f ;zero the high order bits andi byte1, 0x0f ;ditto swap byte1 ;form upper nibble or RXchar, byte1 ;form byte value sample clr byte1 mov cntmax, RXchar inc chrcnt rjmp RXexit RXchr2: cpi chrcnt, 2 ;third byte is delay between waveforms brne RXchr3 ;in units of 5 mSec ticks tst byte1 ;see if first byte is received brne stdly ;if so, the current RXchar must be low-nibble mov byte1, RXchar ;save the high-order nibble rjmp RXexit ;and wait for low-order nibble stdly: subi byte1, 32 subi RXchar, 32 andi RXchar, 0x0f ;zero the high order bits andi byte1, 0x0f ;ditto swap byte1 ;form upper nibble or RXchar, byte1 ;form byte value sample clr byte1 mov dlymax, RXchar inc chrcnt rjmp RXexit RXchr3: cpi chrcnt, 3 ;ready for data brne RXexit tst byte1 ;see if first byte is received brne store ;if so, the current RXchar must be low-nibble mov byte1, RXchar ;save the high-order nibble rjmp RXexit ;and wait for low-order nibble store: subi byte1, 32 subi RXchar, 32 andi RXchar, 0x0f ;zero the high order bits andi byte1, 0x0f ;ditto swap byte1 ;form upper nibble or RXchar, byte1 ;form byte value sample clr byte1 ;get ready for next char-pair st Z, RXchar ;store the sample inc ZL ;move the pointer brne RXexit ;see if we have 256 samples ser playbk ;enable playback clr count clr delay ldi itemp, 0x00 ;set up sample time out OCR1AH, itemp ;load the A comp reg HIGH BYTE first out OCR1AL, sampleT ;load the A-comp reg LOW BYTE cbi PORTB, 0 ;waveform run indicator sbi PORTB, 7 ;done with rs232 inc chrcnt ;receive state machine waits for 0x00 ldi itemp, 4 ;unfreeze timer0 out TCCR0, itemp ;prescale=256 RXexit: out SREG, save ;restore proc status reti