Help needed to find checksum method
Posted: 07 Apr 2012 00:59
Hello Fellow MikroC users
I have been working on a project to control my 1/16 scale Heng Long RC tank from the PC using
either a joystick or keyboard by tapping into the PCM signal path of the RC transmitter by using
a PIC to receive rs232 data and then encoding the 4 bytes to manchester format for the heng long
transmitter.
This part works fine except I do not have proportional speed control and or using other functions at
the same time, ex moving forward and rotating the turret, unless I can set particular bits and then
calculate a 4 bit checksum.
I have written a time based manchester decoder to decode the tx PCM signals and getting
4 x 4byte codes, for example the ignition code for the tank is 0xFE3C10B0 and the idle signal
is 0xFE3C0F00 which is continually sent, I have also recorded other 4 byte codes to do other functions
such as rotate turret, fire machine gun etc
Below is the programme I wrote, it's not entirely accurate as the PCM bit times vary a bit
I recorded the 4 byte codes as I pressed the transmitter keys and moved the transmitter pots etc.
my encoding programme to send the 4byte codes works fine no problems.
//pic 16f1827 manchester encoding programme
unsigned char data_bit, bitcnt, data_rdy, first_bit;
unsigned char decode, encode, gtime;
unsigned int led_cnt, gcnt;
unsigned long data_in, temp;
unsigned int TMR1 absolute 0x16;
void interrupt()
{
if ((INTCON.INTF == 1) && (INTCON.INTE == 1) && (OPTION_REG.INTEDG == 1)) // RB0 interrupt on rising edge should be start
{
INTCON.INTF = 0; // clear RB0 interrupt flag
if (first_bit == 1)
{
INTCON.INTE = 0; // disable RB0 interrupt
TMR1 = 64943; // set timer1 for 150us interrupt
decode = 0;
PIE1.TMR1IE = 1; // enable timer1 interrupt
T1CON.TMR1ON = 1; // start TMR1 timer
PIR1.TMR1IF = 0; // clear timer1 interrupt flag
}
if (first_bit == 0) first_bit = 1; // wait for actual first data bit
}
if ((PIR1.TMR1IF == 1) && (PIE1.TMR1IE == 1)) // TMR1IF and TMR1IE should both be set
{
PIR1.TMR1IF = 0; // clear TMR1IF
if (decode == 1)
{
if (PORTB.B0 == 1) data_bit = 1; else data_bit = 0;
data_in = data_in << 1;
data_in = data_in + data_bit;
bitcnt++;
if (bitcnt < 16) TMR1 = 63223; else TMR1 = 63233; // set timer1 for 580us & 585us interrupts
}
if (decode == 0)
{
TMR1 = 63223;
decode = 1;
}
}
}
void main(void)
{
OSCCON = 0x7A; // use 0x7A if using internal osc 16mhz
PORTA = 0; // use 0x70 for 8mhz
ANSELA = 0; // PORTA all digital i/o
TRISA = 0xFF; // set PORTA to inputs
PORTB = 0;
ANSELB = 0; // PORTB all digital i/o
TRISB = 0xCD; // b11001101
INTCON = 0; // clear all interrupts
OPTION_REG = 194; // TMR0 prescaler set 1:8
OPTION_REG.INTEDG = 1; // RB0 interrupt set on rising edge
APFCON0.CCP1SEL = 0; // select RB3 as CCP1
APFCON0.RXDTSEL = 0; // select RB1 as RX
APFCON1.TXCKSEL = 0; // select RB2 as TX
T1CON.T1CKPS1 = 0; // set timer1 prescaler to 1/1
T1CON.T1CKPS0 = 0; // set timer1 prescaler to 1/1
T1CON.TMR1CS1 = 0; // TMRCS1
T1CON.TMR1ON = 0; // set timer1 off
data_bit = 0;
data_in = 0; // preload data_in with the first three ones
bitcnt = 0;
decode = 0;
encode = 0;
first_bit = 0;
INTCON.GIE = 1; // enable GIE, PEIE , disable TMR0IE, INTE interrupts
INTCON.PEIE = 1;
INTCON.TMR0IE = 0; // disable TMR0 interrupt
INTCON.INTE = 0; // disbale RB0 interrupt
PIE1.TMR1IE = 0; // disable timer1 interrupt
PIR1.TMR1IF = 0; // clear TMR1IF
INTCON.INTF = 0; // clear RB0 interrupt flag
UART1_Init(19200);
while(1)
{
mloop: // looking for the guard time about 4ms
gcnt = 0;
while (PORTB.B0 == 1);
while (PORTB.B0 == 0)
{
gcnt++;
delay_us(10);
}
if (gcnt < 120) goto mloop;
txloop:
INTCON.INTE = 1; // found guard time enable RB0 interrupt on rising edge
while (bitcnt < 32);
INTCON.INTE = 0; // disbale RB0 interrupt
INTCON.INTF = 0; // clear RB0 interrupt flag
PIE1.TMR1IE = 0; // disable timer1 interrupt
PIR1.TMR1IF = 0; // clear TMR1IF
T1CON.TMR1ON = 0; // turn TMR1 timer off
if ((Highest(data_in) == 0xFE))
{
UART1_Write(Highest(data_in));
UART1_Write(Higher(data_in));
UART1_Write(Hi(data_in));
UART1_Write(Lo(data_in));
UART1_Write(10);
}
bitcnt = 0;
data_bit = 0;
decode = 0;
data_in = 0;
first_bit = 0;
goto mloop;
}
}
My problem is finding out what checksum method is used, if I want to simulate exactly what the
transmitter sends, for example proportional speed control and rotating turret at the same time
then I need to set the relevant bits and then calculate the checksum and send the 4 bytes.
I have tried online crc calculators using CRC4 to no avail, I have tried LRC checksum by
adding every 4bits then 2's compliment no success, even tried xoring 8bit, 5bit and 4bit codes
again no success.
In the image file attachment, the first two bits of the PCM signal which is 11 is an illegal manchester
code, so I don't know if that is included in the checksum calculation, I have tried by assuming different
values for the first two 11 bits but I get know where.
I am hoping that some checksum genius out there can steer me in the right direction or provide a
solution.
regards Andrew
I have been working on a project to control my 1/16 scale Heng Long RC tank from the PC using
either a joystick or keyboard by tapping into the PCM signal path of the RC transmitter by using
a PIC to receive rs232 data and then encoding the 4 bytes to manchester format for the heng long
transmitter.
This part works fine except I do not have proportional speed control and or using other functions at
the same time, ex moving forward and rotating the turret, unless I can set particular bits and then
calculate a 4 bit checksum.
I have written a time based manchester decoder to decode the tx PCM signals and getting
4 x 4byte codes, for example the ignition code for the tank is 0xFE3C10B0 and the idle signal
is 0xFE3C0F00 which is continually sent, I have also recorded other 4 byte codes to do other functions
such as rotate turret, fire machine gun etc
Below is the programme I wrote, it's not entirely accurate as the PCM bit times vary a bit
I recorded the 4 byte codes as I pressed the transmitter keys and moved the transmitter pots etc.
my encoding programme to send the 4byte codes works fine no problems.
//pic 16f1827 manchester encoding programme
unsigned char data_bit, bitcnt, data_rdy, first_bit;
unsigned char decode, encode, gtime;
unsigned int led_cnt, gcnt;
unsigned long data_in, temp;
unsigned int TMR1 absolute 0x16;
void interrupt()
{
if ((INTCON.INTF == 1) && (INTCON.INTE == 1) && (OPTION_REG.INTEDG == 1)) // RB0 interrupt on rising edge should be start
{
INTCON.INTF = 0; // clear RB0 interrupt flag
if (first_bit == 1)
{
INTCON.INTE = 0; // disable RB0 interrupt
TMR1 = 64943; // set timer1 for 150us interrupt
decode = 0;
PIE1.TMR1IE = 1; // enable timer1 interrupt
T1CON.TMR1ON = 1; // start TMR1 timer
PIR1.TMR1IF = 0; // clear timer1 interrupt flag
}
if (first_bit == 0) first_bit = 1; // wait for actual first data bit
}
if ((PIR1.TMR1IF == 1) && (PIE1.TMR1IE == 1)) // TMR1IF and TMR1IE should both be set
{
PIR1.TMR1IF = 0; // clear TMR1IF
if (decode == 1)
{
if (PORTB.B0 == 1) data_bit = 1; else data_bit = 0;
data_in = data_in << 1;
data_in = data_in + data_bit;
bitcnt++;
if (bitcnt < 16) TMR1 = 63223; else TMR1 = 63233; // set timer1 for 580us & 585us interrupts
}
if (decode == 0)
{
TMR1 = 63223;
decode = 1;
}
}
}
void main(void)
{
OSCCON = 0x7A; // use 0x7A if using internal osc 16mhz
PORTA = 0; // use 0x70 for 8mhz
ANSELA = 0; // PORTA all digital i/o
TRISA = 0xFF; // set PORTA to inputs
PORTB = 0;
ANSELB = 0; // PORTB all digital i/o
TRISB = 0xCD; // b11001101
INTCON = 0; // clear all interrupts
OPTION_REG = 194; // TMR0 prescaler set 1:8
OPTION_REG.INTEDG = 1; // RB0 interrupt set on rising edge
APFCON0.CCP1SEL = 0; // select RB3 as CCP1
APFCON0.RXDTSEL = 0; // select RB1 as RX
APFCON1.TXCKSEL = 0; // select RB2 as TX
T1CON.T1CKPS1 = 0; // set timer1 prescaler to 1/1
T1CON.T1CKPS0 = 0; // set timer1 prescaler to 1/1
T1CON.TMR1CS1 = 0; // TMRCS1
T1CON.TMR1ON = 0; // set timer1 off
data_bit = 0;
data_in = 0; // preload data_in with the first three ones
bitcnt = 0;
decode = 0;
encode = 0;
first_bit = 0;
INTCON.GIE = 1; // enable GIE, PEIE , disable TMR0IE, INTE interrupts
INTCON.PEIE = 1;
INTCON.TMR0IE = 0; // disable TMR0 interrupt
INTCON.INTE = 0; // disbale RB0 interrupt
PIE1.TMR1IE = 0; // disable timer1 interrupt
PIR1.TMR1IF = 0; // clear TMR1IF
INTCON.INTF = 0; // clear RB0 interrupt flag
UART1_Init(19200);
while(1)
{
mloop: // looking for the guard time about 4ms
gcnt = 0;
while (PORTB.B0 == 1);
while (PORTB.B0 == 0)
{
gcnt++;
delay_us(10);
}
if (gcnt < 120) goto mloop;
txloop:
INTCON.INTE = 1; // found guard time enable RB0 interrupt on rising edge
while (bitcnt < 32);
INTCON.INTE = 0; // disbale RB0 interrupt
INTCON.INTF = 0; // clear RB0 interrupt flag
PIE1.TMR1IE = 0; // disable timer1 interrupt
PIR1.TMR1IF = 0; // clear TMR1IF
T1CON.TMR1ON = 0; // turn TMR1 timer off
if ((Highest(data_in) == 0xFE))
{
UART1_Write(Highest(data_in));
UART1_Write(Higher(data_in));
UART1_Write(Hi(data_in));
UART1_Write(Lo(data_in));
UART1_Write(10);
}
bitcnt = 0;
data_bit = 0;
decode = 0;
data_in = 0;
first_bit = 0;
goto mloop;
}
}
My problem is finding out what checksum method is used, if I want to simulate exactly what the
transmitter sends, for example proportional speed control and rotating turret at the same time
then I need to set the relevant bits and then calculate the checksum and send the 4 bytes.
I have tried online crc calculators using CRC4 to no avail, I have tried LRC checksum by
adding every 4bits then 2's compliment no success, even tried xoring 8bit, 5bit and 4bit codes
again no success.
In the image file attachment, the first two bits of the PCM signal which is 11 is an illegal manchester
code, so I don't know if that is included in the checksum calculation, I have tried by assuming different
values for the first two 11 bits but I get know where.
I am hoping that some checksum genius out there can steer me in the right direction or provide a
solution.
regards Andrew