;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