bulk cmd test works
This commit is contained in:
parent
43f64f0e1f
commit
2d392fe60a
7 changed files with 241 additions and 17 deletions
|
|
@ -92,6 +92,9 @@ program: main.elf openocd.cfg
|
|||
8b10b_test_decode: 8b10b_test_decode.c 8b10b.c
|
||||
gcc -o $@ $^
|
||||
|
||||
protocol_test: protocol.c protocol_test.c
|
||||
gcc -o $@ -O0 -Wall -Wextra -g -I../common $^
|
||||
|
||||
clean:
|
||||
rm -f **.o
|
||||
rm -f main.elf main.hex main.bin main.map main.lst
|
||||
|
|
@ -101,4 +104,5 @@ clean:
|
|||
rm -f sources.tar.xz.zip
|
||||
rm -f sources.c
|
||||
rm -f *.dot
|
||||
rm -f protocol_test
|
||||
|
||||
|
|
|
|||
8
fw/adc.c
8
fw/adc.c
|
|
@ -96,12 +96,10 @@ void adc_configure_monitor_mode(struct command_if_def *cmd_if, int ivl_us) {
|
|||
st.det_st.base_interval_cycles = 10;
|
||||
|
||||
st.det_st.sync = 0;
|
||||
st.det_st.rx_st.rxpos = -1;
|
||||
st.det_st.rx_st.address = 5; /* FIXME debug code */
|
||||
st.det_st.last_bit = 0;
|
||||
st.det_st.committed_len_ctr = st.det_st.len_ctr = 0;
|
||||
st.det_st.rx_st.cmd_if = cmd_if;
|
||||
xfr_8b10b_reset((struct state_8b10b_dec *)&st.det_st.rx8b10b);
|
||||
reset_receiver((struct proto_rx_st *)&st.det_st.rx_st, cmd_if);
|
||||
|
||||
adc_dma_init(NCH, true);
|
||||
|
||||
|
|
@ -219,7 +217,7 @@ void bit_detector(struct bit_detector_st *st, int a) {
|
|||
|
||||
} else if (st->len_ctr >= st->committed_len_ctr) {
|
||||
st->committed_len_ctr += st->base_interval_cycles;
|
||||
receive_bit(&st->rx_st, st->last_bit);
|
||||
receive_bit(st, st->last_bit);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -251,7 +249,7 @@ void DMA1_Channel1_IRQHandler(void) {
|
|||
const long vmeas_r_total = VMEAS_R_HIGH + VMEAS_R_LOW;
|
||||
//int a = adc_data.adc_vmeas_a_mv = (st.adc_aggregate[VMEAS_A]*(vmeas_r_total * vcc / VMEAS_R_LOW)) >> 12;
|
||||
int a = adc_data.adc_vmeas_a_mv = (adc_buf[VMEAS_A]*13300) >> 12;
|
||||
bit_detector(&st.det_st, a);
|
||||
bit_detector((struct bit_detector_st *)&st.det_st, a);
|
||||
|
||||
/* ISR timing measurement for debugging */
|
||||
int end = SysTick->VAL;
|
||||
|
|
|
|||
39
fw/datagen.py
Normal file
39
fw/datagen.py
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
#!/usr/bin/env python3
|
||||
|
||||
import statistics
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('infile')
|
||||
|
||||
parser.add_argument('-b', '--bitlen', type=float, default=250, help='Average length of a bit in fractional samples')
|
||||
parser.add_argument('-j', '--jitter', type=float, default=0, help='Bit length jitter standard deviation in fractional samples')
|
||||
|
||||
parser.add_argument('-v', '--high', type=float, default=12.0, help='High level in V')
|
||||
parser.add_argument('-l', '--low', type=float, default=0.2, help='Low level in V')
|
||||
parser.add_argument('-n', '--noise', type=float, default=0, help='Gaussian white voltage noise amplitude on top of signal')
|
||||
|
||||
parser.add_argument('-r', '--risetime', type=int, default=1, help='Rise time in sp/V')
|
||||
parser.add_argument('-f', '--falltime', type=int, default=1, help='Fall time in sp/V')
|
||||
#parser.add_argument('-g', '--glitchfreq', type=float, default=0, help='Add glitches every {g} samples on average (set to 0 to turn off)')
|
||||
#parser.add_argument('--glitchlen', type=float, default=0, help='Length of glitches to add in samples')
|
||||
#parser.add_argument('-t', '--glitch-constant', type=float, default=0, help='When the signal stays constant between bits add a glitch with probability {t}')
|
||||
args = paresr.parse_args()
|
||||
|
||||
with open(args.infile, 'r') as f:
|
||||
bits = f.read().replace(' ', '').splitlines()
|
||||
|
||||
|
||||
def join_transitions(chunks):
|
||||
for l, r in zip(chunks, chunks[1:]):
|
||||
t = args.risetime if l[-1] < r[0] else args.falltime
|
||||
yield from (l[-1] + (r[0] - l[-1] * i/t) for i in range(t))
|
||||
yield from c[args.risetime:-args.falltime]
|
||||
|
||||
def add_noise(vals):
|
||||
yield from (val + random.gauss(0, args.noise) for val in vals)
|
||||
|
||||
def encode_bits(bitstring):
|
||||
return add_noise(join_transitions([ args.high if bit == '1' else args.low for _ in range(random.gauss(args.bitlen, args.jitter)) ]))
|
||||
|
||||
|
|
@ -37,7 +37,7 @@ enum packet_type {
|
|||
struct {
|
||||
struct command_if_def cmd_if;
|
||||
int payload_len[PKT_TYPE_MAX];
|
||||
} cmd_if = {{PKT_TYPE_MAX}, {
|
||||
} cmd_if = {{.packet_type_max=PKT_TYPE_MAX}, {
|
||||
[PKT_TYPE_RESERVED] = 0,
|
||||
[PKT_TYPE_SET_OUTPUTS_BINARY] = 1,
|
||||
[PKT_TYPE_SET_GLOBAL_BRIGHTNESS] = 1,
|
||||
|
|
|
|||
|
|
@ -1,43 +1,66 @@
|
|||
|
||||
#include <unistd.h>
|
||||
#include "protocol.h"
|
||||
#include "8b10b.h"
|
||||
|
||||
void reset_receiver(struct proto_rx_st *st, struct command_if_def *cmd_if) {
|
||||
st->rxpos = -1;
|
||||
st->address = 5; /* FIXME debug code */
|
||||
st->cmd_if = cmd_if;
|
||||
}
|
||||
|
||||
void receive_symbol(struct proto_rx_st *st, int symbol) {
|
||||
if (symbol == -K28_1) { /* Comma/frame delimiter */
|
||||
st->rxpos = 0;
|
||||
/* Fall through and return and just ignore incomplete packets */
|
||||
|
||||
} else if (symbol == -DECODING_ERROR) {
|
||||
st->rxpos = -1;
|
||||
goto reset;
|
||||
|
||||
} else if (symbol < 0) { /* Unknown comma symbol or error */
|
||||
st->rxpos = -1;
|
||||
goto reset;
|
||||
|
||||
} else if (st->rxpos == -1) {
|
||||
return;
|
||||
|
||||
} else if (st->rxpos == 0) { /* First data symbol, and not an error or comma symbol */
|
||||
st->packet_type = symbol & ~PKT_TYPE_BULK_FLAG;
|
||||
if (st->packet_type >= st->cmd_if->packet_type_max) {
|
||||
st->rxpos = -1;
|
||||
return;
|
||||
}
|
||||
if (st->packet_type >= st->cmd_if->packet_type_max)
|
||||
goto reset;
|
||||
|
||||
int payload_len = st->cmd_if->payload_len[st->packet_type];
|
||||
st->is_bulk = symbol & PKT_TYPE_BULK_FLAG;
|
||||
st->offset = (st->is_bulk) ? st->address*st->cmd_if->payload_len[st->packet_type]+1 : 2;
|
||||
st->offset = (st->is_bulk) ? (st->address*payload_len + 1) : 2;
|
||||
st->rxpos++;
|
||||
|
||||
if (payload_len == 0 && st->is_bulk) {
|
||||
handle_command(st->packet_type, NULL);
|
||||
goto reset;
|
||||
}
|
||||
|
||||
} else if (!st->is_bulk && st->rxpos == 1) {
|
||||
st->rxpos = (symbol == st->address) ? 2 : -1;
|
||||
if (symbol != st->address)
|
||||
goto reset;
|
||||
|
||||
if (st->cmd_if->payload_len[st->packet_type] == 0) {
|
||||
handle_command(st->packet_type, NULL);
|
||||
goto reset;
|
||||
}
|
||||
st->rxpos = 2;
|
||||
|
||||
} else {
|
||||
st->argbuf[st->rxpos - st->offset] = symbol;
|
||||
if (st->rxpos - st->offset >= 0)
|
||||
st->argbuf[st->rxpos - st->offset] = symbol;
|
||||
st->rxpos++;
|
||||
|
||||
if (st->rxpos - st->offset == st->cmd_if->payload_len[st->packet_type]) {
|
||||
handle_command(st->packet_type, (uint8_t *)st->argbuf);
|
||||
st->rxpos = -1;
|
||||
goto reset;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
reset:
|
||||
st->rxpos = -1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,7 +1,7 @@
|
|||
#ifndef __PROTOCOL_H__
|
||||
#define __PROTOCOL_H__
|
||||
|
||||
#include "global.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#define PKT_TYPE_BULK_FLAG 0x80
|
||||
|
||||
|
|
@ -24,5 +24,6 @@ struct command_if_def {
|
|||
void handle_command(int command, uint8_t *args);
|
||||
|
||||
void receive_symbol(struct proto_rx_st *st, int symbol);
|
||||
void reset_receiver(struct proto_rx_st *st, struct command_if_def *cmd_if);
|
||||
|
||||
#endif
|
||||
|
|
|
|||
159
fw/protocol_test.c
Normal file
159
fw/protocol_test.c
Normal file
|
|
@ -0,0 +1,159 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#include "protocol.h"
|
||||
#include "8b10b.h"
|
||||
|
||||
int urandom_fd = -1;
|
||||
|
||||
struct test_cmd_if {
|
||||
struct command_if_def cmd_if;
|
||||
int payload_len[256];
|
||||
};
|
||||
|
||||
struct {
|
||||
int ncalls;
|
||||
int last_cmd;
|
||||
uint8_t last_args[sizeof(((struct proto_rx_st *)0)->argbuf)];
|
||||
} handler_state;
|
||||
|
||||
|
||||
void handle_command(int command, uint8_t *args) {
|
||||
handler_state.ncalls++;
|
||||
handler_state.last_cmd = command;
|
||||
if (args)
|
||||
memcpy(handler_state.last_args, args, 8);
|
||||
}
|
||||
|
||||
void send_test_command_single(struct test_cmd_if *cmd_if, struct proto_rx_st *st, int cmd, int address, unsigned char pattern[256]) {
|
||||
receive_symbol(st, -K28_1);
|
||||
receive_symbol(st, cmd);
|
||||
receive_symbol(st, address);
|
||||
for (int i=0; i<cmd_if->payload_len[i]; i++)
|
||||
receive_symbol(st, pattern[i]);
|
||||
}
|
||||
|
||||
void send_test_command_bulk(struct test_cmd_if *cmd_if, struct proto_rx_st *st, int cmd, int index, int len, unsigned char pattern[256]) {
|
||||
receive_symbol(st, -K28_1);
|
||||
receive_symbol(st, cmd | PKT_TYPE_BULK_FLAG);
|
||||
for (int j=0; j<len; j++) {
|
||||
for (int i=0; i<cmd_if->payload_len[cmd]; i++) {
|
||||
if (j == index)
|
||||
receive_symbol(st, pattern[i]);
|
||||
else
|
||||
receive_symbol(st, 0xaa);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void test_commands_with_pattern(struct test_cmd_if *cmd_if, unsigned char pattern[256]) {
|
||||
struct proto_rx_st st;
|
||||
|
||||
for (int cmd=0; cmd<cmd_if->cmd_if.packet_type_max; cmd++) {
|
||||
/* Addresssed tests */
|
||||
/*
|
||||
reset_receiver(&st, &cmd_if->cmd_if);
|
||||
st.address = 23;
|
||||
handler_state.ncalls = 0;
|
||||
send_test_command_single(cmd_if, &st, cmd, 23, pattern);
|
||||
assert(handler_state.ncalls == 1);
|
||||
assert(handler_state.last_cmd == cmd);
|
||||
assert(!memcmp(handler_state.last_args, pattern, cmd_if->payload_len[cmd]));
|
||||
|
||||
reset_receiver(&st, &cmd_if->cmd_if);
|
||||
st.address = 23;
|
||||
handler_state.ncalls = 0;
|
||||
send_test_command_single(cmd_if, &st, cmd, 5, pattern);
|
||||
assert(handler_state.ncalls == 0);
|
||||
|
||||
reset_receiver(&st, &cmd_if->cmd_if);
|
||||
st.address = 5;
|
||||
handler_state.ncalls = 0;
|
||||
send_test_command_single(cmd_if, &st, cmd, 5, pattern);
|
||||
assert(handler_state.ncalls == 1);
|
||||
assert(handler_state.last_cmd == cmd);
|
||||
assert(!memcmp(handler_state.last_args, pattern, cmd_if->payload_len[cmd]));
|
||||
*/
|
||||
|
||||
/* Bulk test */
|
||||
reset_receiver(&st, &cmd_if->cmd_if);
|
||||
st.address = 5;
|
||||
handler_state.ncalls = 0;
|
||||
send_test_command_bulk(cmd_if, &st, cmd, 5, 8, pattern);
|
||||
assert(handler_state.ncalls == 1);
|
||||
assert(handler_state.last_cmd == cmd);
|
||||
assert(!memcmp(handler_state.last_args, pattern, cmd_if->payload_len[cmd]));
|
||||
}
|
||||
}
|
||||
|
||||
void test_commands(struct test_cmd_if *cmd_if) {
|
||||
unsigned char data[256];
|
||||
|
||||
memset(data, 0, sizeof(data));
|
||||
test_commands_with_pattern(cmd_if, data);
|
||||
|
||||
memset(data, 1, sizeof(data));
|
||||
test_commands_with_pattern(cmd_if, data);
|
||||
|
||||
memset(data, 255, sizeof(data));
|
||||
test_commands_with_pattern(cmd_if, data);
|
||||
|
||||
for (int i=0; i<5; i++) {
|
||||
assert(read(urandom_fd, (char *)data, sizeof(data)) == sizeof(data));
|
||||
test_commands_with_pattern(cmd_if, data);
|
||||
}
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
struct test_cmd_if cmd_if;
|
||||
|
||||
urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
assert(urandom_fd > 0);
|
||||
|
||||
for (int ncmds=1; ncmds<128; ncmds++) {
|
||||
cmd_if.cmd_if.packet_type_max = ncmds;
|
||||
|
||||
/* Case 1 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = 0;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 2 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = 1;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 3 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = i&1 ? 1 : 0;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 4 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = i&1 ? 0 : 1;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 5 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = i&1 ? 1 : 2;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 6 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = i%8;
|
||||
test_commands(&cmd_if);
|
||||
|
||||
/* Case 7 */
|
||||
for (int i=0; i<ncmds; i++)
|
||||
cmd_if.payload_len[i] = 4;
|
||||
test_commands(&cmd_if);
|
||||
}
|
||||
|
||||
assert(!close(urandom_fd));
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue