mirror of
https://github.com/Genaker/LoraSA.git
synced 2026-03-28 17:42:59 +01:00
Support Wrap with checksum
This commit is contained in:
1
.gitignore
vendored
1
.gitignore
vendored
@@ -3,3 +3,4 @@
|
||||
.vscode/c_cpp_properties.json
|
||||
.vscode/launch.json
|
||||
.vscode/ipch
|
||||
out/*
|
||||
|
||||
@@ -48,6 +48,17 @@ def parse_line(line):
|
||||
_, count, rest = line.split(' ', 2)
|
||||
return int(count), json.loads(rest.replace('(', '[').replace(')', ']'))
|
||||
|
||||
POLY = 0x1021
|
||||
def crc16(s, c):
|
||||
for ch in s:
|
||||
c = c ^ (ord(ch) << 8)
|
||||
for i in range(8):
|
||||
if c & 0x8000:
|
||||
c = ((c << 1) ^ POLY) & 0xffff
|
||||
else:
|
||||
c = (c << 1) & 0xffff
|
||||
|
||||
return c
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(formatter_class=RawTextHelpFormatter, description='''\
|
||||
@@ -81,6 +92,9 @@ def main():
|
||||
# List of frequencies
|
||||
freq_list = []
|
||||
|
||||
checksum = -1
|
||||
so_far = 0
|
||||
|
||||
# Open the COM port
|
||||
with serial.Serial(args.port, args.speed, timeout=None) as com:
|
||||
|
||||
@@ -94,11 +108,33 @@ def main():
|
||||
|
||||
# Read a single line
|
||||
try:
|
||||
line = com.readline().decode('utf-8').strip()
|
||||
line = com.readline().decode('utf-8')
|
||||
except UnicodeDecodeError:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if 'WRAP ' in line:
|
||||
try:
|
||||
_, c, rest = line.split(' ', 2)
|
||||
checksum = int(c, 16)
|
||||
so_far = crc16(rest, 0)
|
||||
except Exception as e:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
if 'SCAN_RESULT ' in line:
|
||||
if checksum == -1:
|
||||
errors += 1
|
||||
continue
|
||||
|
||||
c16 = crc16(line, so_far)
|
||||
if checksum != c16:
|
||||
errors += 1
|
||||
checksum = -1
|
||||
continue
|
||||
|
||||
checksum = -1
|
||||
|
||||
lines += 1
|
||||
try:
|
||||
count, data = parse_line(line)
|
||||
|
||||
@@ -22,7 +22,7 @@ void _onUsbEvent0(void *arg, esp_event_base_t event_base, int32_t event_id,
|
||||
void *event_data)
|
||||
{
|
||||
if (event_base == ARDUINO_HW_CDC_EVENTS)
|
||||
{
|
||||
{
|
||||
// arduino_hw_cdc_event_data_t *data = (arduino_hw_cdc_event_data_t *)event_data;
|
||||
if (event_id == ARDUINO_HW_CDC_RX_EVENT)
|
||||
{
|
||||
@@ -117,6 +117,30 @@ Message *Comms::receive()
|
||||
Message *_parsePacket(String);
|
||||
String _scan_str(ScanTask &);
|
||||
String _scan_result_str(ScanTaskResult &);
|
||||
String _wrap_str(String);
|
||||
|
||||
#define POLY 0x1021
|
||||
uint16_t crc16(String v, uint16_t c)
|
||||
{
|
||||
for (int i = 0; i < v.length(); i++)
|
||||
{
|
||||
uint16_t ch = v.charAt(i);
|
||||
c = c ^ (ch << 8);
|
||||
for (int j = 0; j < 8; j++)
|
||||
{
|
||||
if (c & 0x8000)
|
||||
{
|
||||
c = (c << 1) ^ POLY;
|
||||
}
|
||||
else
|
||||
{
|
||||
c <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
void ReadlineComms::_onReceive()
|
||||
{
|
||||
@@ -126,10 +150,27 @@ void ReadlineComms::_onReceive()
|
||||
int i = partialPacket.indexOf('\n');
|
||||
while (i >= 0)
|
||||
{
|
||||
Message *m = _parsePacket(partialPacket.substring(0, i));
|
||||
String pack = partialPacket.substring(0, i);
|
||||
bool messageOk = true;
|
||||
|
||||
if (wrap != NULL)
|
||||
{
|
||||
messageOk = pack.length() == wrap->payload.wrap.length;
|
||||
if (messageOk)
|
||||
{
|
||||
messageOk = crc16(pack, 0) == wrap->payload.wrap.crc;
|
||||
}
|
||||
delete wrap;
|
||||
wrap = NULL;
|
||||
}
|
||||
Message *m = messageOk ? _parsePacket(pack) : NULL;
|
||||
if (m != NULL)
|
||||
{
|
||||
if (!_messageArrived(*m))
|
||||
if (m->type == WRAP)
|
||||
{
|
||||
wrap = m;
|
||||
}
|
||||
else if (!_messageArrived(*m))
|
||||
{
|
||||
delete m;
|
||||
}
|
||||
@@ -154,53 +195,7 @@ bool ReadlineComms::send(Message &m)
|
||||
break;
|
||||
}
|
||||
|
||||
const char *cstr = p.c_str();
|
||||
size_t cstr_len = strlen(cstr);
|
||||
|
||||
int loops = 0;
|
||||
uint64_t t0 = millis();
|
||||
uint64_t idle_started = 0;
|
||||
|
||||
for (size_t a = serial.availableForWrite(); a < cstr_len;
|
||||
a = serial.availableForWrite(), loops++)
|
||||
{
|
||||
uint64_t now = millis();
|
||||
if (now - t0 > 1000)
|
||||
{
|
||||
Serial.printf("Unable to make progress after %d loops; %d bytes available "
|
||||
"for write, %d chars still to write\n",
|
||||
loops, a, cstr_len);
|
||||
break;
|
||||
}
|
||||
|
||||
if (a == 0)
|
||||
{
|
||||
if (idle_started == 0)
|
||||
{
|
||||
idle_started = now;
|
||||
}
|
||||
|
||||
if (now - idle_started > 2)
|
||||
{
|
||||
vTaskDelay(pdMS_TO_TICKS(2));
|
||||
}
|
||||
else
|
||||
{
|
||||
yield();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
idle_started = 0;
|
||||
|
||||
serial.write(cstr, a);
|
||||
cstr += a;
|
||||
cstr_len -= a;
|
||||
}
|
||||
serial.println(cstr);
|
||||
|
||||
uint64_t dt = millis() - t0;
|
||||
Serial.printf("Wrote stuff in %d iterations and %" PRIu64 " ms.\n", loops, dt);
|
||||
serial.print(_wrap_str(p));
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -218,6 +213,20 @@ int64_t _intParam(String &p, int64_t default_v)
|
||||
return v;
|
||||
}
|
||||
|
||||
int64_t _hexParam(String &p, int64_t default_v)
|
||||
{
|
||||
p.trim();
|
||||
int i = p.indexOf(' ');
|
||||
if (i < 0)
|
||||
{
|
||||
i = p.length();
|
||||
}
|
||||
|
||||
int64_t v = strtol(p.substring(0, i).c_str(), 0, 16);
|
||||
p = p.substring(i + 1);
|
||||
return v;
|
||||
}
|
||||
|
||||
Message *_parsePacket(String p)
|
||||
{
|
||||
p.trim();
|
||||
@@ -239,6 +248,15 @@ Message *_parsePacket(String p)
|
||||
p.trim();
|
||||
}
|
||||
|
||||
if (cmd.equalsIgnoreCase("wrap"))
|
||||
{
|
||||
Message *m = new Message();
|
||||
m->type = MessageType::WRAP;
|
||||
m->payload.wrap.crc = _hexParam(p, -1);
|
||||
m->payload.wrap.length = _intParam(p, -1);
|
||||
return m;
|
||||
}
|
||||
|
||||
if (cmd.equalsIgnoreCase("scan"))
|
||||
{
|
||||
Message *m = new Message();
|
||||
@@ -254,12 +272,12 @@ Message *_parsePacket(String p)
|
||||
|
||||
String _scan_str(ScanTask &t)
|
||||
{
|
||||
return "SCAN " + String(t.count) + " " + String(t.delay);
|
||||
return "SCAN " + String(t.count) + " " + String(t.delay) + "\n";
|
||||
}
|
||||
|
||||
String _scan_result_str(ScanTaskResult &r)
|
||||
{
|
||||
String p = "SCAN_RESULT " + String(r.sz) + " [";
|
||||
String p = "SCAN_RESULT " + String(r.sz) + " [ ";
|
||||
|
||||
for (int i = 0; i < r.sz; i++)
|
||||
{
|
||||
@@ -267,5 +285,11 @@ String _scan_result_str(ScanTaskResult &r)
|
||||
")";
|
||||
}
|
||||
|
||||
return p + " ]";
|
||||
return p + " ]\n";
|
||||
}
|
||||
|
||||
String _wrap_str(String v)
|
||||
{
|
||||
String r = String(v.length()) + "\n" + v;
|
||||
return "WRAP " + String(crc16(r, 0), 16) + " " + r;
|
||||
}
|
||||
|
||||
@@ -6,11 +6,18 @@
|
||||
|
||||
enum MessageType
|
||||
{
|
||||
SCAN = 0,
|
||||
WRAP = 0,
|
||||
SCAN,
|
||||
SCAN_RESULT,
|
||||
_MAX_MESSAGE_TYPE = SCAN_RESULT
|
||||
};
|
||||
|
||||
struct Wrapper
|
||||
{
|
||||
int32_t length;
|
||||
uint16_t crc;
|
||||
};
|
||||
|
||||
struct ScanTask
|
||||
{
|
||||
int64_t count;
|
||||
@@ -29,6 +36,7 @@ struct Message
|
||||
MessageType type;
|
||||
union
|
||||
{
|
||||
Wrapper wrap;
|
||||
ScanTask scan;
|
||||
ScanTaskResult dump;
|
||||
} payload;
|
||||
@@ -41,8 +49,10 @@ struct Comms
|
||||
size_t received_sz;
|
||||
size_t received_pos;
|
||||
|
||||
Message *wrap;
|
||||
|
||||
Comms(Stream &serial)
|
||||
: serial(serial), received(NULL), received_sz(0), received_pos(0) {};
|
||||
: serial(serial), received(NULL), received_sz(0), received_pos(0), wrap(NULL) {};
|
||||
|
||||
virtual size_t available();
|
||||
virtual bool send(Message &) = 0;
|
||||
|
||||
@@ -3,6 +3,34 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <inttypes.h>
|
||||
|
||||
typedef struct {
|
||||
uint16_t checksum;
|
||||
uint16_t so_far;
|
||||
size_t len;
|
||||
} wrap_t;
|
||||
|
||||
#define POLY 0x1021
|
||||
uint16_t crc16(char *p, char *end, uint16_t c) {
|
||||
if (end == NULL) {
|
||||
end = strchr(p, 0);
|
||||
}
|
||||
|
||||
for (; p != end; p++) {
|
||||
uint16_t ch = *p;
|
||||
c = c ^ (ch << 8);
|
||||
for (int j = 0; j < 8; j++) {
|
||||
if (c & 0x8000) {
|
||||
c = (c << 1) ^ POLY;
|
||||
} else {
|
||||
c <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
#define BUFSIZE 102400
|
||||
#define LOOPS 200
|
||||
@@ -24,6 +52,9 @@ int main(int argc, char** argv)
|
||||
int progress = 0;
|
||||
int progress_ln = 0;
|
||||
|
||||
wrap_t wrapper;
|
||||
wrapper.len = 0;
|
||||
|
||||
while(lines - errors < LOOPS)
|
||||
{
|
||||
if (pos == BUFSIZE)
|
||||
@@ -48,17 +79,49 @@ int main(int argc, char** argv)
|
||||
// assert: n points at the first unused byte in buffer
|
||||
pos = (nl - buffer) + 1;
|
||||
|
||||
char *wrap = "WRAP ";
|
||||
char is_wrap = strncmp(buffer, wrap, strlen(wrap)) == 0;
|
||||
if (is_wrap) {
|
||||
char *end;
|
||||
char *p = buffer + strlen(wrap);
|
||||
wrapper.checksum = strtol(p, &end, 16);
|
||||
wrapper.len = 0;
|
||||
if (end == p) {
|
||||
is_wrap = 0;
|
||||
} else {
|
||||
p = end;
|
||||
wrapper.len = strtol(p, &end, 10);
|
||||
if (end == p) {
|
||||
is_wrap = 0;
|
||||
} else {
|
||||
wrapper.so_far = crc16(p+1, end+1, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *scan_result = "SCAN_RESULT ";
|
||||
char is_scan_result = strncmp(buffer, scan_result, strlen(scan_result)) == 0;
|
||||
|
||||
if (is_scan_result) {
|
||||
if (
|
||||
!(buffer[pos-2] == ']' || // that's where it should "normally" appear
|
||||
buffer[pos-3] == ']') // that's where it actually appears - because HWCDC.println produces \r\n
|
||||
)
|
||||
uint16_t c16 = crc16(buffer, buffer + pos, wrapper.so_far);
|
||||
if (wrapper.len == 0 || wrapper.checksum != c16)
|
||||
{
|
||||
errors++;
|
||||
if (wrapper.len == 0) {
|
||||
int n = snprintf(buffer, pos, "E: no wrap"); // string definitely fits
|
||||
buffer[n] = ' ';
|
||||
} else {
|
||||
int n = snprintf(buffer, pos, "E: bad crc"); // string definitely fits
|
||||
buffer[n] = ' ';
|
||||
int n1 = snprintf(buffer + n + 1, pos - n - 1, "want: %x, got: %x", wrapper.checksum, c16);
|
||||
n1 += n + 1;
|
||||
if (n1 <= pos - n - 1) {
|
||||
buffer[n1] = ' ';
|
||||
}
|
||||
}
|
||||
}
|
||||
wrapper.len = 0; // ok, used up the wrapper
|
||||
|
||||
// assert: pos points at the first byte of the next line
|
||||
write(1, buffer, pos);
|
||||
// printf("Last char is: %c\n", buffer[pos-3]); - wow, HWCDC.println ends up producing \r\n
|
||||
@@ -68,7 +131,7 @@ int main(int argc, char** argv)
|
||||
} else if (strncmp(buffer, "Unable to make ", 15) == 0) {
|
||||
lines--;
|
||||
write(1, buffer, pos);
|
||||
} else {
|
||||
} else if (!is_wrap) {
|
||||
errors++;
|
||||
}
|
||||
|
||||
|
||||
@@ -560,7 +560,7 @@ void dumpToCommsTask(void *parameter)
|
||||
int64_t delay = report_scans.delay;
|
||||
if (delay == 0)
|
||||
{
|
||||
delay = (1 << 63) - 1;
|
||||
delay = (1ull << 63) - 1;
|
||||
}
|
||||
|
||||
ulTaskNotifyTake(true, pdMS_TO_TICKS(delay));
|
||||
|
||||
Reference in New Issue
Block a user