| CODE |
;****************************************************** .include "2313def.inc" ;****************************************************** ; User timer 1 to make a 4 khz interrupt and put a square wave sampling pulse on pin 16. ; Firmware expects a 4 Mhz AT90S2313 ; Keep other I/O pins low, except when outpulse is greater than $C0, hold reset pin high .def chargecount = r2;Value of measuered charge in integrator .def counterlow = r3;Lower byte of the preload for 4 kHz interrupt. Usaed for programmability .def oldchargecount = r4;Value of charge on prior measurement .def quarterycles = r5;Value to change timer low .def meascount = r6;Count of measurements modulus 256. Used for alternative meas output .def temp =r16;Scratch register .def temp2 =r17;Second scratch register .def outpulse =r18;Interrupt counter .def datab =r19;Temporary data for PORTB, to be output every interrupt time (only 4 lsb available). ;.def resetcounter =r20;Counter to determine reset time .def flagreg =r21;Flags stored here .def H = r22;Used to send decimal ascii .def T = r23;Used to send decimal ascii .def U = r24;Used to send decimal ascii ;NOTE: Y register is used as integration timer ;definition of I/O ;B0 COMPARITOR NONINVERTING ;B1 COMPARITOR INVERTING ;B2 ;B3 SAMPLE CLOCK PHASE 1 ON EVEN MEASUREMENTS ;B4 SAMPLE CLOCK PHASE 1 ;B5 SAMPLE CLOCK PHASE 2 ;B6 SAMPLE CLOCK PHASE 3 ;B7 SAMPLE CLOCK PHASE 4 ;D0 USED FOR UART RECEIVE ;D1 USED FOR UART TRANSMIT ;D2 ;D3 LED - SIGNAL ABOVE THRESOLD ;D4 CLAMP INTEGRATOR TO ZERO ;D5 MEASURE ;D6 ;D7 ;definition of flagreg bit assignments .equ meastaken =0;Set after new measurement taken. Cleared by servo ;1 ;2 ;3 ;4 ;5 ;6 ;7 .equ counterhigh =$03;High byte of the perolaod for 4 kHz interrupt .equ measuretime =$E7;Point detector cycle that measurement takes place .equ measuretimeH =$03 .equ resettime =$E8 .equ resettimeH =$03 .equ detthreshold =$40;Threshold above which a signal is said to have been detected .equ outpulsepattern =0b00110011;Note: As used here, the high and low nybble are used sequentially,and ;repeats every two cycles. For odd and even cycles to be identicle, both nybbles should be identicle. ;The pattern "0b00110011 would result in a 50% duty cycle at 1 kHz. ;UART baud rate calculation .equ clock = 4000000;clock frequency .equ baudrate = 9600 ;choose a baudrate .equ baudconstant = (clock/(16*baudrate))-1 .cseg ; Main program entry point on reset .ORG $0000 rjmp start .ORG $0004 rjmp timerservice;Timer/counter compare interrupt handler start: ldi r16,RAMEND;Init Stack Pointer out spl,r16 ldi temp,baudconstant out ubrr,temp ;Load baudrate. ; sbi ucr,rxen ;Enable WAUT receive;Uart receive not used so not enabled bere. sbi ucr,txen ;Enable UART Transmit ldi outpulse,outpulsepattern;Initial pulse ouput pattern ldi flagreg, 0b00000000;Initialize all flags clr YL ;Initialize integration cycle counter clr YH ldi temp,$04;Initialize quarter cycle counter mov quarterycles,temp ldi temp,$E8;Initialize the variable for interrupt timer mov counterlow,temp ldi temp,$00;Set data on PORTD and PORTB low. out PORTD,temp out PORTB,temp ldi temp,0b11111100;Make pins on PORTB, except comparitor pins, ouputs. out DDRB,temp ldi temp,0b11111111;Make all pins on PORTD out DDRD,temp ldi temp,$09;Set timer 1 to reset 0000 after compare match. Prescaler = 1X out TCCR1B,temp ldi temp,counterhigh;Set compare register to $03E8 for 4 khZ interrupt out OCR1AH,temp mov temp,counterlow out OCR1AL,temp ldi temp,$40;Enable interrupt on compare match out TIMSK,temp sei ;Enable interrupts rjmp Main ;Go to main loop and wait for interrupt locklight: mov temp,chargecount cpi temp,detthreshold brmi ledoff sbi PORTD,3 ret ledoff: cbi PORTD,3 ret servo: sbrs flagreg,meastaken ret ;Return if this is not first call after signal measurement andi flagreg,$FE mov temp,chargecount;Send the latest measuremnet followed by a CR and LF. rcall sendnumber rcall crlf rcall locklight ret ;Code below is not executed mov temp,chargecount cpi temp,$10 brpl nosignal inc counterlow ldi temp,counterhigh;Set compare register out OCR1AH,temp mov temp,counterlow out OCR1AL,temp nosignal: ret Main: rcall servo rjmp Main sendnumber:;Enter with value to be sent in temp, sends as three digit ascii ;via serial port. mov U,temp ;Enter with 8 bit value in U, Exits with numerals in H,T,U clr H ;(Hundreds, Tens, and Units). clr T anotherh: subi U,100 ;Find out how many hundreds in U. brcs hdone inc H rjmp anotherh hdone: subi U,-100 ;Subtracted one too many -add back. anothert: subi U,10 brcs tdone inc T rjmp anotherT tdone: subi U,-10 cpi H,0 breq dontsendh subi H,-48 mov temp,H rcall emitchar cpi t,0 brne dontsendh ldi temp,$30 ;If U=0 then don't emit this zero rcall emitchar dontsendh: cpi t,0 breq dontsendt subi T,-48 mov temp,T rcall emitchar dontsendt: subi U,-48 mov temp,U rcall emitchar ret crlf: ;Send return and linefeed ldi temp,$0A ;Send return and line feed rcall emitchar ldi temp,$0D rcall emitchar ret emitchar:;Send character contained in temp with two stop bits. sbis usr,udre ;wait until the register is cleared. rjmp emitchar cbi ucr,0 ;Set 9th bit to zero (second stop bit). sbi ucr,2 ;Set to send 9 data bits. out udr,temp ;send the character. ret measurecharge: ;Measure time it takes to zero integrator. Output range is $80 to $00, ldi temp,$81;which is later adjusted to 0 to $127 in timerservice and sendnumber. mov chargecount,temp;Set chargevalue to $81 so it will only spend 127 cycles in this routine. ori flagreg,1;Set meastaken flag. cbi PORTB,4 ;Make both phase 1 and phase 3 low during the measurement cbi PORTB,6 ;so incoming signals don't affect measurement accuracy. sbi PORTD,5 ;Turn on discharge resistor. ;(Discharge resistor turned off after return). sbic acsr,aco;If comparitor is high, then charge is zero or negative. In this case. ret ;skip measurement and go on to discharge capacitor. morch: inc chargecount;Stay in a counting loop until the comparitor goes high. breq saturated sbis acsr,aco rjmp morch saturated: ret ;(Discharge resistor turned off after return) writeportb:;Output outpulse combined with datab lower 4 bits to PORTB mov temp,datab andi temp,$0F mov temp2,outpulse andi temp2,$F0 or temp,temp2 out PORTB,temp ret timerservice: ;Timer 1 interrupt service push temp push temp2 clc rol outpulse ;Rotate bit image and output to PORTB. brcc B1 ;If carry set, set bit 0. ori outpulse,$01 B1: ;If meascount is even, copy PORTB bit 4 to PORTB bit 3 ;so that pulses are sent from B3 on alternate measurements mov temp,meascount andi temp,0b00000001 brne noclockout ;If meascount lsb is not zero, skip to noclockout ;If meascount is zero, then copy outputle bit 4 into datab bit 3 mov temp,datab andi temp,0b11110111 mov datab,temp mov temp,outpulse lsr temp andi temp,0b00001000 or datab,temp noclockout: rcall writeportb dec quarterycles ;If four quarter cycles haven't passed, then don't brne notfullcycle ;increment resetcounter or see if its time to measure charge. ldi temp,$04 mov quarterycles,temp adiw YL,1 ;There will be a glitch on D4 during resets. mov temp,YL mov temp2,YH subi temp,measuretime sbci temp2,measuretimeH ; cpi resetcounter,measuretime;See if its time to measure charge and reset the integrator. brcs noreset brne nomeasure ;If this is the first time through, measure the charge (250 us). rcall measurecharge ;First time is when resercounter = measuretime. inc meascount ;Increment measurement count mov temp,chargecount;After measuring charge, adjust offset and save previoius charge subi temp,$81 ;for possible future use. mov oldchargecount,chargecount;Save old charge value before replacing. mov chargecount,temp;Remove offset from count. nomeasure: mov temp,YL mov temp2,YH subi temp,resettime sbci temp2,resettimeH brne nozeroY clr YL clr YH nozeroY: cbi PORTD,5 ;Turn off discharge resistor. sbi PORTD,4 ;Turn on dump resistor. rcall writeportb ;Restore PORTB rjmp finishedinterupt noreset: cbi PORTD,4 ;Turn off dump resistor. notfullcycle: ;Skip to here if this is not at the end of a full cycle. finishedinterupt: pop temp2 pop temp reti .exit ;don't assemble past here. |