PIC Specific
RS232 routine
for Sony and the code for 16F84@4MHz written with CC5XFree
follows. see if u can figure it :-)
//=============cut--here=================================
/*
* IR reception
* 05/Sep/1999 JLS & CAE
* jls at certi.ufsc.br
* cae at certi.ufsc.br
* CC5xFree v3.0E (www.bknd.com)
*/
/*
Sony Data format: 12 bits
Bit zero:
400
+--+ +...
| | |
+ +---+
800
Bit one:
400
+--+ +...
| | |
+ +------+
1400
Frame:
400 400
--+ +--+ +--+ +--+
| | | | | | |
+---2600---+ +---+ +------+ +...
800 1400
Decoding algorithm:
- Detect 2600us pulse,
- measure next high pulse as P1 (400us)
- measure next low pulse as P2 (800/1400us)
- store min(P1)
- store max(P2)
After all measurements:
- calculate mean = (max-min)/2 + min
- For all (P1,P2) measured:
. Add P1+P2=P3
. If P3< mean => bit is zero
. If P3>=mean => bit is one
Measures with Timer0 & Prescaler:16
2600us = 162
1400us = 87
800us = 50
400us = 25
400+800 = 25+50 = 75
400+1400 = 25+87 = 112
mean ~= (112-75)/2+75 = 18+75 = 93
*/
#define _16f84_
#include <16f84.h>
#ifdef _12C508_
bit _TxOUT @ GP0;
bit RxD_pin @ GP1;
bit IR_input @ GP2;
#else
#define RP0 STATUS.5
#pragma update_RP 0 /* OFF */
#define DEF_TRISA 0
#define DEF_TRISB 6
bit Rele @ PORTA.1;
bit IR_input @ PORTB.1;
bit RxD_pin @ PORTB.2;
bit _TxOUT @ PORTB.3;
bit LED @ PORTB.4;
#endif
unsigned char size,x,y,med,min,max,rxBuf;
unsigned char r[4];
unsigned char buff[32];
void TxSerial (unsigned char txBuf);
/*--------------------------------------------------------------------------*/
void TxEnter (void) {
/*--------------------------------------------------------------------------*/
TxSerial(0xD);
TxSerial(0xA);
}
/*--------------------------------------------------------------------------*/
void TxHexAscii (unsigned char in) {
/*--------------------------------------------------------------------------*/
unsigned char Hex;
Hex = swap(in); // upper nibble
Hex &= 0x0F;
if (Hex<10) Hex += 0x30;
else Hex += 0x37;
TxSerial(Hex);
Hex = in & 0x0F;
if (Hex<0x0A) Hex += 0x30;
else Hex += 0x37;
TxSerial(Hex);
}
/*--------------------------------------------------------------------------*/
void Delay_uSeg (unsigned char timeout) {
/*--------------------------------------------------------------------------*/
// delay = 3*timeout + 7uS (including call and return)
while (1) {
timeout--;
if (timeout==0) {
nop();
nop();
return;
}
}
}
/*--------------------------------------------------------------------------*/
void TxSerial (unsigned char txBuf) {
/*--------------------------------------------------------------------------*/
/*
;---------------------------------------------------------------------------*
; Transmit 1 start bit Lo, 8 data bits and 1 stop bit Hi at 9600 bps
; No Parity
; Byte time = 1.040 mS
; Bit time = 104 uS (0.16% erro w/4.00 Mhz Internal RC)
; Input : W = byte to be transmitted
; Output: byte transmitted by serial pin
;---------------------------------------------------------------------------*
*/
char idx;
while (1)
{
Carry = 0; // start bit
for (idx=10; idx; idx--) // 3us
{
_TxOUT = Carry; // 4us
Delay_uSeg(28); // 91us (28*3+7)
Carry = 1; // 1us
txBuf = rr(txBuf); // 1us
nop(); // 1us
} // 3us
return;
}
}
/*--------------------------------------------------------------------------*/
void RxSerial (void) {
/*--------------------------------------------------------------------------*/
/*
;---------------------------------------------------------------------------*
; Receives 1 start bit Lo, 8 data bits and 1 stop bit Hi at 9600 bps
; No Parity
; Byte time = 1.040 mS
; Bit time = 104 uS (0.16% erro w/4.00 Mhz Internal RC)
;
; False start bit check
;
; Start bit hunting timeout = 4*1.283ms
;
; Input : none
; Output : Carry = 1 => success
; rxBuf = input byte
; Carry = 0 => error (timeout or stop bit=0)
;---------------------------------------------------------------------------*
*/
char idx;
rxBuf = 4; // 5.135 ms timeout
idx = 0;
while (1)
{
while (RxD_pin) // input "high"
{
if ((-- idx)==0)
{
if ((-- rxBuf)==0)
{
Carry = 0;
return;
}
}
}
Delay_uSeg(14); // 1/2 bit delay (14*3+7)
if (RxD_pin)
continue; // false start bit detection
rxBuf = 0x80; // 8 bits counter and reception buffer
nop();
nop(); // timming adjustment
do
{
Delay_uSeg(30); // (30*3+7)us
Carry = RxD_pin; // bit read
rxBuf = rr(rxBuf); // store and count
}
while (Carry==0);
Delay_uSeg(30); // 1 bit delay
nop(); // timming adjustment
Carry = RxD_pin; // stop bit read
return; // 100 us availiable
}
}
/*--------------------------------------------------------------------------*/
void main (void) {
/*--------------------------------------------------------------------------*/
#ifdef _12C508_
// OSCCAL = W; // OscCal Value - OTP part
OSCCAL = 0xB0; // OscCal Value - Windowed part
GPIO = 0x00;
TRIS = 0x08; // GP3 input
OPTION = 0b11000011; // Prescaler Timer0 1:16
#else
INTCON = 0; // no interrupts
PCLATH = 0; // bank 0
PORTA = 0;
PORTB = 0;
RP0 = 1; // RAM bank 1
TRISA = DEF_TRISA;
TRISB = DEF_TRISB;
OPTION = 0b11000011; // Prescaler Timer0 1:16
RP0 = 0; // RAM bank 0
#endif
while (1)
{
/* set vars to start */
FSR = buff; // pointer to buffer
x = 12; // only 12 bits
size = 0; // word size in bits
min = 255; // min period
max = 0; // max period
/* start bit management */
while (IR_input==1); // wait for 0
/* 2600us start bit */
while (IR_input==0); // wait for 1
TMR0 = 0; // start counter
do
{
/* measure high pulse */
INDF = 0; // period: default to zero
while (TMR0==0); // wait TMR0 advance
while (IR_input==1) // wait for 0
{
if (TMR0==0) // timer overflow (4096us) ?
goto frame_end; // yes, exit
}
INDF = TMR0; // store period
TMR0 = 0; // start counter
med = INDF; // save high period
FSR++; // bump pointer
INDF = 0; // period: default to zero
size++; // inc bit counter
/* measure low pulse */
while (TMR0==0); // wait TMR0 advance
while (IR_input==0); // wait for 1
INDF = TMR0; // store period
TMR0 = 0; // start counter
med += INDF; // total period
if (med>=max) max = med; // find max
if (med<min) min = med; // find min
FSR++; // bump pointer
size++; // inc period counter
x--; // dec max bits
}
while (x);
frame_end:
LED = 1;
med = max - min;
med /= 2;
med += min;
r[0] = 0;
r[1] = 0;
r[2] = 0;
r[3] = 0;
FSR = buff;
FSR += size;
x = size/2;
do
{
Carry = 0;
r[3] = rl(r[3]);
r[2] = rl(r[2]);
r[1] = rl(r[1]);
r[0] = rl(r[0]);
FSR--;
max = INDF;
FSR--;
max += INDF;
if (max>=med) r[3]++;
} while (--x);
/* now r[0],r[1],r[2], r[3] has the frame */
/* Tx the periods and the encoded word */
TxHexAscii(size);
TxSerial(0x20);
TxHexAscii(med);
TxEnter();
for(x=0;x<size; x++)
{
TxHexAscii(buff[x]);
TxSerial(0x20);
}
TxEnter();
TxHexAscii(r[0]);
TxHexAscii(r[1]);
TxHexAscii(r[2]);
TxHexAscii(r[3]);
TxEnter();
LED = 0;
}
}