2023-12-12 20:56:58 -07:00
/*
DigitalReadSerial
Reads a digital input on pin 2 , prints the result to the Serial Monitor
This example code is in the public domain .
https : //www.arduino.cc/en/Tutorial/BuiltInExamples/DigitalReadSerial
*/
# include "CRC16.h"
2023-12-14 19:15:36 -07:00
volatile uint8_t control_flags = 0xC9 ;
volatile uint32_t timer_end = 0x00000000 ;
volatile uint32_t length = 0x00000000 ;
volatile uint32_t last_timer_sent = 0x00000000 ;
CRC16 crc = CRC16 ( 0x1021 , 0xFFFF , 0x0000 , false , false ) ;
2023-12-12 20:56:58 -07:00
int read_line = 22 ;
int rx2 = 16 ;
int tx2 = 17 ;
2023-12-14 18:28:01 -07:00
uint32_t htonl ( uint32_t val ) {
return ( ( val & 0x000000FF ) < < 24 ) |
( ( val & 0x0000FF00 ) < < 8 ) |
( ( val & 0x00FF0000 ) > > 8 ) |
( ( val & 0xFF000000 ) > > 24 ) ;
}
2023-12-14 17:08:12 -07:00
uint16_t htons ( uint16_t val ) {
return ( ( val & 0xFF ) < < 8 ) | ( ( val & 0xFF00 ) > > 8 ) ;
}
2023-12-12 20:58:24 -07:00
typedef struct __attribute__ ( ( packed ) ) {
2023-12-12 20:56:58 -07:00
uint8_t type ;
uint8_t controller_version ;
uint8_t unknown [ 12 ] ;
uint16_t crc ;
2023-12-14 18:28:01 -07:00
} pkt_discovery_t ;
2023-12-12 20:56:58 -07:00
2023-12-12 20:58:24 -07:00
typedef struct __attribute__ ( ( packed ) ) {
2023-12-12 20:56:58 -07:00
uint8_t type ;
2023-12-14 18:28:01 -07:00
uint8_t unknown_1 [ 7 ] ;
uint32_t serial ;
uint8_t unknown_2 [ 2 ] ;
2023-12-12 20:56:58 -07:00
uint16_t crc ;
2023-12-14 18:28:01 -07:00
} pkt_discovery_resp_t ;
2023-12-12 20:56:58 -07:00
2023-12-12 20:58:24 -07:00
typedef struct __attribute__ ( ( packed ) ) {
2023-12-12 20:56:58 -07:00
uint8_t type ;
uint8_t unknown [ 13 ] ;
uint16_t crc ;
2023-12-14 18:28:01 -07:00
} pkt_init_t ;
2023-12-12 20:56:58 -07:00
2023-12-12 20:58:24 -07:00
typedef struct __attribute__ ( ( packed ) ) {
2023-12-12 20:56:58 -07:00
uint8_t type ;
uint8_t ack_type ;
uint8_t unknown_1 ;
uint8_t unknown_2 [ 7 ] ;
uint8_t unknown_3 ;
uint8_t unknown_4 [ 3 ] ;
uint16_t crc ;
} pkt_ack_t ;
2023-12-12 20:58:24 -07:00
typedef struct __attribute__ ( ( packed ) ) {
2023-12-12 20:56:58 -07:00
uint8_t type ;
uint8_t unknown [ 29 ] ;
uint16_t crc ;
2023-12-14 18:28:01 -07:00
} pkt_set_poll_rate_t ;
2023-12-12 20:56:58 -07:00
2023-12-14 19:15:36 -07:00
typedef struct __attribute__ ( ( packed ) ) {
uint8_t type ;
uint8_t unknown_1 ;
uint16_t system_status ;
uint8_t unknown_2 [ 2 ] ;
uint8_t field_status ;
uint8_t unknown_3 [ 11 ] ;
uint8_t name [ 10 ] ;
uint8_t version [ 2 ] ;
uint16_t crc ;
} pkt_poll_t ;
2023-12-12 20:56:58 -07:00
2023-12-14 18:28:01 -07:00
void parse_discovery ( uint8_t * pkt , size_t len ) {
pkt_discovery_t parsed ;
2023-12-12 20:56:58 -07:00
parsed . controller_version = pkt [ 1 ] ;
memcpy ( parsed . unknown , & pkt [ 2 ] , 12 ) ;
parsed . crc = ( pkt [ 14 ] < < 8 ) + ( pkt [ 15 ] < < 0 ) ;
crc . restart ( ) ;
crc . add ( pkt , 14 ) ;
uint16_t calc_crc = crc . calc ( ) ;
if ( calc_crc ! = parsed . crc ) {
2023-12-14 18:28:01 -07:00
Serial . printf ( " Got dicovery packet with bad crc(%04x != %04x) \n " , calc_crc , parsed . crc ) ;
2023-12-12 20:56:58 -07:00
} else {
2023-12-14 18:28:01 -07:00
Serial . printf ( " Got dicovery packet with matching crc(%04x) \n " , calc_crc ) ;
2023-12-12 20:56:58 -07:00
}
2023-12-14 18:28:01 -07:00
pkt_discovery_resp_t response ;
2023-12-12 20:56:58 -07:00
response . type = 0x03 ;
2023-12-14 18:28:01 -07:00
response . unknown_1 [ 0 ] = 0x01 ;
response . unknown_1 [ 1 ] = 0x64 ;
response . unknown_1 [ 2 ] = 0x00 ;
response . unknown_1 [ 3 ] = 0x00 ;
response . unknown_1 [ 4 ] = 0x00 ;
response . unknown_1 [ 5 ] = 0x00 ;
response . unknown_1 [ 6 ] = 0xBA ;
response . serial = htonl ( 0x881C7C00 ) ;
response . unknown_2 [ 0 ] = 0x00 ;
response . unknown_2 [ 1 ] = 0x00 ;
2023-12-12 20:56:58 -07:00
crc . restart ( ) ;
crc . add ( ( uint8_t * ) & response , 14 ) ;
response . crc = htons ( crc . calc ( ) ) ;
digitalWrite ( read_line , HIGH ) ;
Serial2 . write ( ( uint8_t * ) & response , 16 ) ;
delayMicroseconds ( 100 ) ;
digitalWrite ( read_line , LOW ) ;
}
2023-12-14 18:28:01 -07:00
void parse_init ( uint8_t * pkt , size_t len ) {
pkt_init_t parsed ;
2023-12-12 20:56:58 -07:00
memcpy ( parsed . unknown , & pkt [ 1 ] , 13 ) ;
parsed . crc = ( pkt [ 14 ] < < 8 ) + ( pkt [ 15 ] < < 0 ) ;
crc . restart ( ) ;
crc . add ( pkt , 14 ) ;
uint16_t calc_crc = crc . calc ( ) ;
if ( calc_crc ! = parsed . crc ) {
2023-12-14 18:28:01 -07:00
Serial . printf ( " Got init packet with bad crc(%04x != %04x) \n " , calc_crc , parsed . crc ) ;
2023-12-12 20:56:58 -07:00
} else {
2023-12-14 18:28:01 -07:00
Serial . printf ( " Got init packet with matching crc(%04x) \n " , calc_crc ) ;
2023-12-12 20:56:58 -07:00
}
pkt_ack_t response ;
response . type = 0x02 ;
response . ack_type = pkt [ 0 ] ;
response . unknown_1 = 0x01 ;
memset ( response . unknown_2 , 0 , 7 ) ;
response . unknown_3 = 0x01 ;
memset ( response . unknown_4 , 0 , 3 ) ;
crc . restart ( ) ;
crc . add ( ( uint8_t * ) & response , 14 ) ;
response . crc = htons ( crc . calc ( ) ) ;
digitalWrite ( read_line , HIGH ) ;
Serial2 . write ( ( uint8_t * ) & response , 16 ) ;
delayMicroseconds ( 100 ) ;
digitalWrite ( read_line , LOW ) ;
}
2023-12-14 18:28:01 -07:00
void parse_get_poll_rate ( uint8_t * pkt , size_t len , uint8_t poll_ms ) {
2023-12-12 20:56:58 -07:00
crc . restart ( ) ;
crc . add ( pkt , 30 ) ;
uint16_t parsed_crc = ( pkt [ 30 ] < < 8 ) + ( pkt [ 31 ] < < 0 ) ;
uint16_t calc_crc = crc . calc ( ) ;
if ( parsed_crc ! = calc_crc ) {
2023-12-14 19:15:36 -07:00
Serial . printf ( " Got get_poll_rate packet with bad crc(%04x != %04x \n " , calc_crc , parsed_crc ) ;
2023-12-12 20:56:58 -07:00
} else {
2023-12-14 19:15:36 -07:00
Serial . printf ( " Got get_poll_rate packet with matching crc(%04x) \n " , calc_crc ) ;
2023-12-12 20:56:58 -07:00
}
2023-12-14 18:28:01 -07:00
pkt_set_poll_rate_t response ;
2023-12-12 20:56:58 -07:00
response . type = 0x04 ;
memset ( response . unknown , 0 , 29 ) ;
response . unknown [ 1 ] = 0x14 ;
crc . restart ( ) ;
crc . add ( ( uint8_t * ) & response , 30 ) ;
response . crc = htons ( crc . calc ( ) ) ;
digitalWrite ( read_line , HIGH ) ;
Serial2 . write ( ( uint8_t * ) & response , 32 ) ;
delayMicroseconds ( 200 ) ;
digitalWrite ( read_line , LOW ) ;
}
void send_ack ( uint8_t ack_type , uint8_t unknown ) {
uint8_t response [ 32 ] ;
memset ( response , 0 , 32 ) ;
response [ 0 ] = 0x02 ;
response [ 1 ] = ack_type ;
response [ 2 ] = unknown ;
response [ 10 ] = unknown ;
crc . restart ( ) ;
crc . add ( response , 30 ) ;
uint16_t ack_crc = crc . calc ( ) ;
response [ 30 ] = ( ack_crc > > 8 & 0xFF ) ;
response [ 31 ] = ( ack_crc > > 0 & 0xFF ) ;
digitalWrite ( read_line , HIGH ) ;
Serial2 . write ( ( uint8_t * ) & response , 32 ) ;
delayMicroseconds ( 200 ) ;
digitalWrite ( read_line , LOW ) ;
}
void send_state ( uint8_t control_flags , uint32_t timer ) {
uint8_t response [ 32 ] ;
memset ( response , 0 , 32 ) ;
response [ 0 ] = 0x53 ;
response [ 1 ] = control_flags ;
response [ 2 ] = 0x00 ;
response [ 3 ] = 0x00 ;
2023-12-14 19:15:36 -07:00
response [ 4 ] = ( ( timer > > 0 ) & 0xFF ) ;
response [ 5 ] = ( ( timer > > 8 ) & 0xFF ) ;
response [ 6 ] = ( ( timer > > 16 ) & 0xFF ) ;
response [ 7 ] = ( ( timer > > 24 ) & 0xFF ) ;
2023-12-12 20:56:58 -07:00
response [ 8 ] = 0x03 ;
crc . restart ( ) ;
crc . add ( response , 30 ) ;
uint16_t ack_crc = crc . calc ( ) ;
response [ 30 ] = ( ack_crc > > 8 & 0xFF ) ;
response [ 31 ] = ( ack_crc > > 0 & 0xFF ) ;
digitalWrite ( read_line , HIGH ) ;
Serial2 . write ( ( uint8_t * ) & response , 32 ) ;
delayMicroseconds ( 200 ) ;
digitalWrite ( read_line , LOW ) ;
}
void parse_poll ( uint8_t * pkt , size_t len ) {
pkt_poll_t * parsed = ( pkt_poll_t * ) pkt ;
crc . restart ( ) ;
crc . add ( pkt , 30 ) ;
uint16_t crc_calc = crc . calc ( ) ;
if ( htons ( parsed - > crc ) ! = crc_calc ) {
Serial . printf ( " parsed poll with invalid CRC 0x%04x, calculated to be 0x%04x \n " , htons ( parsed - > crc ) , crc_calc ) ;
} else {
//Serial.printf("parsed poll with valid CRC 0x%04x, system status 0x%04x, field status 0x%02x, team name %s\n", htons(parsed->crc), htons(parsed->system_status), parsed->field_status, parsed->name);
}
2023-12-14 19:15:36 -07:00
uint32_t now = millis ( ) ;
uint32_t current_timer = 0 ;
if ( now < timer_end ) {
current_timer = ( timer_end - millis ( ) ) & 0xFFFFFF00 ;
} else {
current_timer = length ;
control_flags = 0xC9 ;
}
if ( ( parsed - > field_status = = control_flags ) & & ( current_timer = = last_timer_sent ) ) {
2023-12-12 20:56:58 -07:00
send_ack ( 0xA7 , 0x01 ) ;
2023-12-14 19:15:36 -07:00
} else if ( control_flags = = 0xC9 ) {
send_state ( 0xC9 , length ) ;
} else {
last_timer_sent = current_timer ;
send_state ( control_flags , current_timer ) ;
2023-12-12 20:56:58 -07:00
}
}
void on_rx ( void ) {
uint8_t pkt [ 4 ] ;
int n = Serial . available ( ) ;
if ( n < 4 ) {
return ;
}
int read = Serial . readBytes ( pkt , n ) ;
2023-12-14 19:15:36 -07:00
sscanf ( ( const char * ) pkt , " 0x%2hhx%8x " , & control_flags , & length ) ;
timer_end = millis ( ) + length ;
Serial . printf ( " Parsed new control flags: 0x%02x, length 0x%08x \n " , control_flags , length ) ;
2023-12-12 20:56:58 -07:00
}
void on_rx_2 ( void ) {
uint8_t pkt [ 32 ] ;
int n = Serial2 . available ( ) ;
if ( n < 16 ) {
return ;
}
int read = Serial2 . readBytes ( pkt , n ) ;
switch ( pkt [ 0 ] ) {
case 0xA7 :
parse_poll ( pkt , read ) ;
break ;
case 0x0A :
2023-12-14 18:28:01 -07:00
parse_discovery ( pkt , read ) ;
2023-12-12 20:56:58 -07:00
break ;
case 0x13 :
2023-12-14 18:28:01 -07:00
parse_init ( pkt , read ) ;
2023-12-12 20:56:58 -07:00
break ;
case 0x11 :
2023-12-14 19:15:36 -07:00
parse_get_poll_rate ( pkt , read , 20 ) ;
2023-12-12 20:56:58 -07:00
break ;
case 0x02 :
switch ( pkt [ 1 ] ) {
case 0x04 :
send_ack ( 0x02 , 0x00 ) ;
break ;
default :
Serial . printf ( " Unknown ack 0x%x \n " , pkt [ 1 ] ) ;
}
break ;
default :
Serial . printf ( " Unknown command 0x%x \n " , pkt [ 0 ] ) ;
break ;
}
}
void setup ( )
{
Serial . begin ( 115200 ) ;
Serial2 . begin ( 1562500 , SERIAL_8N1 , rx2 , tx2 ) ;
pinMode ( read_line , OUTPUT ) ;
digitalWrite ( read_line , LOW ) ;
Serial2 . onReceive ( on_rx_2 ) ;
Serial . onReceive ( on_rx ) ;
Serial . println ( " Started " ) ;
}
void loop ( )
{
}