Full Version : RS-232 to 100MHz RF Desktop Channel Adapter
avr >>PROJECTS (AVR) >>RS-232 to 100MHz RF Desktop Channel Adapter


AVR_Admin- 04-29-2006
RS-232 to 100 MHz RF desktop channel adapter


Notice: This section describes an experimental low power, low bandwidth data signaling system that operates at 100 MHz (In the FM broadcast band in the U.S.). Before operating a radio transmitter, find out what kind of transmitter operation, if any, is permitted in your locality. Radio transmitter operation is a serious legal matter. In the United States, operation of unlicensed intentional radiators is covered by Part 15 of Title 47 of the Code of Federal Regulations. This design can be readily adapted to different frequencies and different power levels. If you choose to build and operate the transmitter described here, you do so at your own risk. I'm only publishing this as an example of what can be done, and to show how easy it is to build a simple but functional receiver.


Link to Site: http://cappels.org/dproj/232LINK/232link.htm

CODE

;******************************************************
;Send and receive FM data, pass through UART at 9600 baud
;******************************************************
 
.include "2313def.inc"
;  memory index =r0; used for fetching strings from memory
.def bitsout  = r02; counter for bits sent (couple also use a delay counter)
.def sendheader = r03;headerr to place on outgoing RF byte
.def receiveaddress = r04; Address mask for RF received data header
 
.def temp   = r16; Scratch register.
.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 wirelessdat  = r19; data to be sent via wireless port
 ;REGISTER 19 USED TWICE ON PURPOSE
 
.def inbyte  = r20; Decoded data byte could be same register as runincoung
 
.def header  = r21
.def outbyte  = r21;Byte value to be sent (input to send routine)
 ;REGISTER 21 USED TWICE ON PURPOSE
 
.equ minzeros = 9;Minimum number of consecutive zeros to qualify as run-in code
 
.equ defaultsendheader = $10;Default value of RF sendingheaderr.
.equ defaultreceiveaddress =$02;Default value for RF receiveing address in header
 
 
.equ RFxmitdat = 5 Port bit used to send transmit data to RF transmitter
.equ RFrcvdat = 6 Port bit used to receive data from RF receiver
 
  ;SETTING UP THE UART
.equ clock  = 4000000 ;clock frequency
.equ baudrate = 9600 ;choose a baud rate
.equ baudkonstant  = (clock/(16*baudrate))-1
 
; Used for memory index = ZL,ZH
 
;PORT D
; bit 0 this pin used for UART RX pin
; bit 1 this pinused for UART TX pin
; bit 5 Send data to RF transmitter
; bit 6 receive data from RF receiver
 
;EEPROM
;0 not used
;1 sendheader
;2 receiveaddress
 
 
.cseg
.ORG $0000
;START INITIALIZATION
ldi     temp,low(ramend)
out     spl,temp     ;Set the 8 bit stack pointer to the top of ram.

ldi temp,baudkonstant;load baud rate into the UART
out ubrr,temp

cbi PORTD,RFrcvdat;no pullup on receiver input
cbi DDRD,RFrcvdat;make receier input pin an input
cbi PORTD,RFxmitdat ;initial state of transmitter output is low
sbi DDRD,RFxmitdat;make transmitter output pin an output

; ldi temp,defaultsendheader;Establish the default RF sendingheaderr
; mov sendheader,temp   ;88888TEMPRORAILLY COMMENTED OUT!!!!!!!!!!!!

  ;Fetch default transmit address from EEPROM
ldi temp,$01
out eear,temp ;Set up the read address
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
mov sendheader,temp

   ;Fetch default receive address from EEPROM
ldi temp,$02
out eear,temp ;Set up the read address
sbi eecr,eere ;Trigger the read
in temp,eedr ;Get the data into temp
mov receiveaddress,temp

; mov receiveaddress,temp ;Put it into receiveaddress register.

sbi ucr,rxen;enable UART receive function

;FINISHED WITH THE INITIALIZATION
;SEND GREETING
rcall greeting
 

main:;MAIN FOREGROUND LOOP FOR THIS MACHINE
 
rcall rsreceiveit;Check for RS-232 data coming in and send via RF link if anything's ready
rcall rssendit ;Check for incoming RF data. If coming in, decode and send to RS-232 device.
 
rjmp main
 
 
 
rsreceiveit:;CHECK FOR DATA FROM TERMINAL. IF PRESENT, RESEND IT. Trap and intrepret Escape sequences.
sbis usr,rxc  ;wait for data
rjmp    norsdata
in wirelessdat,udr ;read data
cpi wirelessdat,$1B ;See if this is an escape character.
brne NotEscapeCommand;If it keep going as if nothing happened -skip to bottom

receivecommand:   ;If that was an Escape, then wait for command.
sbis usr,rxc  ;wait for data
rjmp    receivecommand
in wirelessdat,udr ;read command
andi wirelessdat,$DF ;And with $DF to make ASCII upper-casce.

receiveparameter:  ;Receive the parameter
sbis usr,rxc  ;wait for data
rjmp    receiveparameter
in temp,udr ;Read parameter (interpreded as in the range of 0..7).
subi temp,$30 ;Then make into address to insert into the header.
andi temp,$07
lsl temp
lsl temp
lsl temp
mov bitsout,temp ;Store results in bitsout for now.

 ;Now interpret the command
 
cpi wirelessdat,$54 ;"T" set transmit address
brne NotTransmit
mov temp,bitsout
mov sendheader,temp ;Store the address

wrat: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrat
ldi temp,$01
out eear,temp ;Set up the write address
mov temp,sendheader  
out eedr,temp ;Set up the  write data
sbi eecr,eemwe
sbi eecr,eewe ;Trigger the write

 
NotTransmit:
 
cpi wirelessdat,$52 ;"R" set receive  address
brne NotReceive
mov receiveaddress,bitsout;Put the number in the address receive register
wrar: sbic eecr,eewe ;Wait for EEPROM write to not be busy
rjmp wrar
ldi temp,$02
out eear,temp ;Set up the write address
mov temp,receiveaddress  
out eedr,temp ;Set up the  write data
sbi eecr,eemwe
sbi eecr,eewe ;Trigger the write

NotReceive:
 

ret   ;End of processing escape.


NotEscapeCommand:
; com wirelessdat ;///////////////////TEST ONLY INVERTED DATA if not commented out///////////
rcall  sendabyte
norsdata:
ret
   
 
 
rs_send: ;SEND CONTENTS OF TEMP VIA SERIAL PORT
    sbi  ucr,txen    ;set sender bit
    sbis   usr,udre    ;wait till register is cleared
    rjmp  rs_send    
    out udr,temp    ;send the contents of temp.
    cbi   ucr,txen    ;clear sender bit
    ret              ;go back
 
 
sendstring:         ;call with location of string in Z
    lpm                   ; Load byte from program memory into r0
    tst r0              ; Check if we've reached the end of the message
    breq  finishsendstering    ; If so, return
    mov  temp,r0
    rcall rs_send
    adiw  ZL,1              ; Increment Z registers
    rjmp  sendstring
finishsendstering:
    ret
 
greeting:
    ldi  ZH,high(2*gteetingmessage)    ; Load high part of byte address into ZH
    ldi ZL,low(2*gteetingmessage)    ; Load low part of byte address into ZL
    rcall sendstring         ; sent it.
 
    mov temp,sendheader ;display defualt transmit address
    andi temp,$78;mask off all but the address
    lsr temp;shift to right to make address into a binary number
    lsr      temp
    lsr temp
    ori temp,$30;make into an ascii number
    rcall rs_send
   
 
   ldi  ZH,high(2*greetingsecondpart)    ; Load high part of byte address into ZH
   ldi  ZL,low(2*greetingsecondpart)    ; Load low part of byte address into ZL
   rcall sendstring         ; sent it.
 
 
    mov temp,receiveaddress ;display defualt receive address
    andi temp,$78;mask off all but the address
    lsr temp;shift to right to make address into a binary number
    lsr      temp
    lsr temp
    ori temp,$30;make into an ascii number
    rcall rs_send  
   
      ;print some blank lines
    ldi  ZH,high(2*crlfs)    ; Load high part of byte address into ZH
    ldi ZL,low(2*crlfs)    ; Load low part of byte address into ZL
    rcall sendstring  
   
   
    ret
 
 
 
 
gteetingmessage:
.db $0A,$0D
.db "RF interface.              02JUN2002 Dick Cappels."
.db $0A,$0D
.db "To change receive address, type <ESC>, R, <Address> "
.db $0A,$0D
.db "To change transmit address, type <ESC>, T, <Address>"
.db $0A,$0D
.db "Where the valid range of address is 0..7"
.db $0A,$0D
.db "Default transmit address is set to  = $0"
.db $00,00
 
greetingsecondpart:
.db $0A,$0D
.db "Default receive address is set to = $0"
.db $00,00
 
crlfs:
.db $0A,$0D
.db $0A,$0D
.db $0A,$0D
.db $00,00
 
;/////////////////////////////////////////////////////////////////////////////////////////////////////
rssendit:;CHECK FOR DATA FROM RADIO RECEIVER AND IF PRESENT, SEND TO TERMINAL

rcall TryToGetbytemessage; returns with header in header and data in inbyte
andi header,$78 ;mask off all but the address part of the header
cp header,receiveaddress ;check the header to see if header matches address
brne notforme ;if not for address $01 then don't send it on.
mov temp,inbyte ;if it is addressed tho this machine then send it on to terminal
 
 
 
waittosend:
sbi ucr,txen;set sender bit
sbis usr,udre;wait till register is cleared
rjmp waittosend
out udr,temp;send the recived data
cbi ucr,txen;clear sender bit
 
notforme:
ret
 
 
;///////////////RADIO RECEIVE BYTE ROUTINES///////////////////
 
;Try and decode a valid header and data byte. In the case or error, return with header = $00
ErrorQuitReceiving:
ldi header,$00
ret
 
TrytoGetbytemessage:
 
 
ldi header,$00
ldi temp,$00
mov runincount,temp
GetAnotherZero:  ;Start of loop to gather minzeros zeros in runin code.
rcall Getbit
brts ErrorQuitReceiving;It Getbit comes back with T set, its an error; start over.
brcs ErrorQuitReceiving;If Getbit comes back with carry set, its a one, not a zero -start over
inc runincount
cpi runincount,minzeros
brmi GetAnotherZero  

 
WaitForStartbit: ;Start of loop waiting for a one, which will be the start bit.
rcall Getbit
brts ErrorQuitReceiving;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 header. Shift them in.

ldi temp,$08
mov runincount,temp
Getheader:
rcall  Getbit
brts ErrorQuitReceiving;It Getbit comes back with T set, its an error; Stop receiveing.
rol header ;Shift new bit into header byte
dec runincount
brne Getheader;If all bits aren't in yet, go get another.
 
;At this point, one could tell whether this data is addressed to this machine, but I am going to leave
;address qualification to another part of the code. If time were very precious, one could stop
;execution of this part of the receive routine right here.

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 ErrorQuitReceiving;It Getbit comes back with T set, its an error; start over.

;Now we have the runinbits, the start bit, and the header. Next is the data. Shift it in.



ldi temp,$08
mov runincount,temp
GetInbyte:
rcall  Getbit
brts ErrorQuitReceiving;It Getbit comes back with T set, its an error; Stop receiveing.
rol inbyte ;Shift new bit into input data byte
dec runincount
brne GetInbyte;If all bits aren't in yet, go get another


 
ret ;RETURN WITH header IN header AND DATA IN INBYTE
 

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.
 
 
 
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 PIND,RFrcvdat
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 PIND,RFrcvdat
rjmp WaitForHigh

;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
 
;/////////////////////////RADIO SEND BYTE ROUTINES/////////////////////////
 
Sendabyte:
 ;SEND RUNIN CODE (16 ZEROS)

ldi outbyte,$00 ;get ready to send 16 zeros
ldi temp,$0F ;$0F databits plus a zero "start bit"
mov bitsout,temp
clc   ;no start bit (it goes as another zero)
rcall LateTransmitAByte;jump into byte sending routine

 
;Send the header byte. The first and last bit in the headder is always a "1". Its the law.
mov outbyte,sendheader
rcall TransmitAByte


;(Ok, now the 16 bits of runin, the start bit, and the 8 bits of header have been sent.
;Time to send the data byte.
 
mov outbyte,wirelessdat
rcall TransmitAByte


ldi outbyte,$FF ;get ready to send 1 one, channel idle, to finish the last data bit.
ldi temp,$02 ;$01 databits plus a start bit
mov bitsout,temp
sec   ;no start bit
rcall LateTransmitAByte;jump into byte sending routine
 
ret  ;finished sending the one byte message
 
 
 
TransmitAByte:;send a byte out the wireless port
ldi temp,$09
mov bitsout,temp
sec;start bit is a "one"

LateTransmitAByte:
SendACycle:;a one or a zero, depending on the state of carry bit
sbi PORTD,RFxmitdat
ldi tcounter,$00
ldi delaycounter,$04
brcs notazero1
ldi delaycounter,$08
notazero1:
 
Delay:
dec tcounter
brne Delay
dec delaycounter
brne delay

cbi PORTD,RFxmitdat
 

ldi tcounter,$00
ldi delaycounter,$04
brcs notazero2
ldi delaycounter,$08
notazero2:
 
Delay2:
dec tcounter
brne Delay2
dec delaycounter
brne delay2

 
rol outbyte;sent start bit and all 8 data bits yet?
dec bitsout
brne SendACycle;if not send another bit

ret
     
;//////////END OF CODE FOR SEND ROUTINE///////////////



Forumer™ is Voted #1 Free Forum Hosting provider
Build your own community today with the largest message board hosting company.