;Dick Cappels' project pages sap@cappels.org - you should be able to copy and paste this text into an assembler file.
   ;©2002 Richard Cappels All Rights Reserved. email projects@cappels.org
;Use of information presented on this page is for personal, nonprofit educational
;and noncommercial use only. This material (including object files) is copyrighted
;by Richard Cappels and may not be republished or used directly for commercial
;purposes without explicit permission For commercial license,
click HERE.
;

;HOME; ;****************************************************** ;Decode FM ;****************************************************** ;A word to anyone who might be looking at this to pick up some style pointers: DON'T. This is just ;something tossed together that servs a need. Don't don't inflict these poor practices on another ;project. ;Minimize stack usage so can be used with AT90S1200 or ATtiny12. ;Allocation of three level stack: one stack entry each for noninterrupt subroutines, subroutines within interrupts, and inerrupt return. ;.include "2313def.inc" .include "tn12def.inc";When using ATtiny12, remember to enable the crystal oscillator. .def temp = r16 ; Scratch register -noninterrupt time. .def tcounter = r17 ; 8 Bit loop timing counter. .def delaycounter = r18 ; Delay to increase time measureble with 8 bit tcounter. .def runincount = r19 ; Used to keep track of consecutive zeros detected in runin code. .def inbyte = r20 ; Decoded data byte could be same register as runincoung .def Hedder = r21 .equ minzeros = $09 ;Minimum number of consecutive zeros to qualify as run-in code ; Port B ; bit 0 High to flag receiving activity. ; bit 1 LED -low to turn on wbe $A5 received, off when $5A received. ; bit 2 Received bit input. ; bit 3 ; bit 4 .ORG $0000 ; ldi temp,low(ramend) ; out spl,temp ;Set the 8 bit stack pointer to the top of ram. ; ldi temp,$FF ;Set up PORTD. ; out DDRD,temp ; ldi temp,$00 ; out PORTD,temp ldi temp,$03 ;Set up PORTB. out DDRB,temp ldi temp,$02 out PORTB,temp sbi PORTB,$01 ;set B0 so LED is off. Loop: FindRunin: sbi PORTB,0 ;Turn the "receive activity" LED off. ldi Hedder,$00 ldi temp,$00 mov runincount,temp GetAnotherZero: ;Start of loop to gather minzeros zeros in runin code. rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. brcs FindRunin ;If Getbit comes back with carry set, its a one, not a zero -start over cbi PORTB,0 ;Bits are coming in, so ligt "Revceive Activity" LED. inc runincount cpi runincount,minzeros brmi GetAnotherZero WaitForStartbit: ;Start of loop waiting for a one, which will be the start bit. rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. brcc WaitForStartbit ;If its a zero, keep looking ;OK, Now we have the start bit, so the next 8 bits will be the hedder. Shift them in. rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol Hedder rcall Getbit ;Throw this one away. Its the start bit for the next byte ;It must be here so two bytes of zeros can't look like ;the runing code. brts FindRunin ;It Getbit comes back with T set, its an error; start over. ;Now we have the runinbits, the start bit, and the hedder. Next is the data. Shift it in. rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte rcall Getbit brts FindRunin ;It Getbit comes back with T set, its an error; start over. rol inbyte cpi hedder,$10 ;Is this data addressed to device 1? breq itsforme ;If it is addressed to device 1, its for me. rjmp loop itsforme: ; out PORTD,inbyte ;Send it out port D (Only does anyting if you have a Port D). cpi inbyte,$A5 breq ledon cpi inbyte,$5A breq ledoff sbi PORTB,1 ;heck, turn it off anyway (for testing) rjmp loop ledon: cbi portb,1 ;If its for me, and code is $A5, turn LED on. rjmp loop ledoff: sbi portb,1 ;If its for me, and the code is $5A, turn LED off. rjmp loop Getbit: ;Subroutine to get a received bit. ;It returns the value of the received bit in the carry bit ;If this routine does not receive a valid data bit IT WILL NOT RETURN. ;If it is necessary to recover from this situation, the watchdog timer can be used. ;It measures the time between rising edges on the input pin (B3 originally). ;Successfult bit decoding will return with T flag clear. T flag =1 means error. ;nobit: ;Re-entry point when valid bit is not detected. ;****for more robust system, it should be return with error so false bits cause a ; reset of the receiving routine. ldi tcounter,$00 ;Zero the counter. ;Count, waiting for pin to go low. WaitForLow: ldi delaycounter,$16 ;load with $16, 1 cycle takes 17.5 us delayloop1: dec delaycounter brne delayloop1 inc tcounter breq nobit sbic PINB,2 rjmp WaitForLow ;Continue to count, waiting for pin to go high. WaitForHigh: ldi delaycounter,$16 delayloop2: dec delaycounter brne delayloop2 inc tcounter breq nobit sbis PINB,2 rjmp WaitForHigh ; When we get here, the time being low and high has been measured in tcount. ; If the count is between $84 and $DC its a zero,light the LED ;Determine if we measured a "legal" bit and if so wheter it as a one of a zero. ;pcode: ;If tcount < $42 start over ;If tcount <$6E its a one ;If tcount is < $84 start over ;If tcount is >$DC start over ;Else, its a zero cpi tcounter,$42 brmi nobit cpi tcounter,$6E brmi ItsAOne cpi tcounter,$84 brmi nobit cpi tcounter,$DC brpl nobit ;If it gets here, its a valid zero.; clt ;Clear T flag (no error), set the carry bit to show that its a zero and return. clc ret ItsAOne:clt ;Clear T flag (error) set carry flag (data is a one), and return. sec ret nobit: ;Error receiving a bit, set T flag and leave set ret ; delay parameters for a half cycle ; basicdealy = 00 ; delaymult = 01 for 1, =02 for 0. ;Delay: ; dec basicdelay ; brne Delay ; dec delaymult ; brne delay ; Time for 1/2 cycle at high freuencey = 771.625 us (1.5435 ms full cycle) ; Time for 1/2 cycle at low fequency =1.5435 ms (3.0865 ms full cycle) ; Input signal is frequenc modulated. A zero is one cycle at 3.0865 ms per cycle ; and a one is two cycles of 1.5435 ms per cycle. ; The test signal starts with 16 zeros for the receiver circuitry to settle, followed ; by a one as a startbit, followed by 8 bits of data. The value of the 8 bits is incremented ; at each transmission. ;17 April -for now on, a one will be decoded as a single cycle of the high frequency pulse. It makes my life simpler. ; To detect the zeros in the leader, the time between positive transitions on the data line ; will be measured by a simple counting routine. If the value is greater than 2.314875 ms, ; and less than 3.858125 ms, the edge will be considered the end of a zero bit. ; If the value is greater than 578.7185 us and less than 964.5325 us, the edge will be considered ; the end of a high frquency cycle. Two cycles of these in succession is considered a one. ;http://projects.cappels.org/ ;HOME