Skip to content

Commit

Permalink
Add /n command to select next routine.
Browse files Browse the repository at this point in the history
  • Loading branch information
Onwrikbaar committed Oct 1, 2024
1 parent dd1d4a9 commit 9c17496
Show file tree
Hide file tree
Showing 13 changed files with 1,490 additions and 1,342 deletions.
7 changes: 7 additions & 0 deletions Design.md
Original file line number Diff line number Diff line change
Expand Up @@ -76,3 +76,10 @@ The device's on-board control program (aka firmware) consists of a collection of
Conceptually, the firmware consists of two layers:
1. The hardware-dependent part, called the Board Support Package (BSP), which implements the _mechanisms_. This is the only module that needs to be changed when porting the application to a different processor.
2. The hardware-independent application logic, implementing the _policies_.

### About the code
- All C modules, with the exception of the BSP, are less than 300 lines long.
- Functions are short, or have low cyclomatic complexity.
- There are no global variables, preventing unwanted coupling between modules and violation of invariants.
- Most 'plumbing' is done through dependency injection.
- Object types are opaque where possible.
2,594 changes: 1,320 additions & 1,274 deletions firmware/build/neodk_g071.hex

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion firmware/inc/app_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ enum {
ET_APP_HEARTBEAT, ET_ADC_DATA_AVAILABLE,
ET_CONTROLLER_CONNECTED, ET_CONTROLLER_DISCONNECTED,
ET_CONTROLLER_SENT_REQUEST, ET_CONTROLLER_SENT_CHOICE,
ET_SEQUENCER_READY, ET_SEQUENCER_PLAY_PAUSE,
ET_SEQUENCER_READY, ET_SEQUENCER_PLAY_PAUSE, ET_NEXT_ROUTINE,
ET_BURST_REQUESTED, ET_BURST_REJECTED, ET_BURST_STARTED, ET_BURST_COMPLETED, ET_BURST_EXPIRED,
};

Expand Down
3 changes: 2 additions & 1 deletion firmware/inc/datalink.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ DataLink *DataLink_new();
// Instance methods.
bool DataLink_open(DataLink *, void *packet_handler, PacketCallback);
void DataLink_waitForSync(DataLink *);
bool DataLink_sendPacket(DataLink *, uint8_t const *, uint16_t);
bool DataLink_sendDebugPacket(DataLink *, uint8_t const *, uint16_t);
bool DataLink_sendDatagram(DataLink *, uint8_t const *, uint16_t);
void DataLink_close(DataLink *);
void DataLink_delete(DataLink *);

Expand Down
11 changes: 10 additions & 1 deletion firmware/inc/pattern_iter.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,15 @@

#include "bsp_app.h"

typedef struct {
char const *name;
uint8_t const (*pattern)[2];
uint16_t nr_of_elcons;
uint8_t pace_ms;
uint8_t nr_of_steps;
uint16_t nr_of_reps;
} PatternDescr;

typedef struct {
uint8_t const (*pattern)[2];
uint16_t nr_of_elcons, elcon_nr;
Expand All @@ -30,7 +39,7 @@ typedef struct {
bool PatternIterator_checkPattern(uint8_t const pattern[][2], uint16_t nr_of_elcons);

// Instance methods.
void PatternIterator_init(PatternIterator *, uint8_t const pattern[][2], uint16_t nr_of_elcons, uint8_t pace_ms, uint16_t nr_of_reps, uint8_t nr_of_steps);
void PatternIterator_init(PatternIterator *, PatternDescr const *);
bool PatternIterator_done(PatternIterator *);
bool PatternIterator_getNextPulseTrain(PatternIterator *, PulseTrain *);

Expand Down
9 changes: 5 additions & 4 deletions firmware/maolib/inc/net_frame.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@ extern "C" {

// Class methods.
uint16_t PhysFrame_headerSize(void);
char const *PhysFrame_typeName(FrameType);
char const *PhysFrame_frameTypeName(FrameType);
char const *PhysFrame_serviceTypeName(NetworkServiceType);

// Instance methods.
PhysFrame *PhysFrame_initHeader(PhysFrame *, FrameType, uint8_t seq);
PhysFrame *PhysFrame_initHeaderWithAck(PhysFrame *, FrameType, uint8_t seq, uint8_t ack);
PhysFrame *PhysFrame_init(PhysFrame *, FrameType, uint8_t seq, uint8_t const *, uint16_t nb);
PhysFrame *PhysFrame_initHeader(PhysFrame *, FrameType, uint8_t seq, NetworkServiceType);
PhysFrame *PhysFrame_initHeaderWithAck(PhysFrame *, FrameType, uint8_t seq, uint8_t ack, NetworkServiceType);
PhysFrame *PhysFrame_init(PhysFrame *, FrameType, uint8_t seq, NetworkServiceType, uint8_t const *, uint16_t nb);
bool PhysFrame_hasValidHeader(PhysFrame const *);

ProtocolVersion PhysFrame_protocolVersion(PhysFrame const *);
Expand Down
Binary file modified firmware/maolib/libmao.a
Binary file not shown.
21 changes: 9 additions & 12 deletions firmware/src/controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,11 @@
*/

#include <stdlib.h>
#include <string.h>

#include "bsp_dbg.h"
#include "bsp_app.h"
#include "app_event.h"
#include "sequencer.h"
#include "debug_cli.h"

// This module implements:
Expand All @@ -27,15 +28,13 @@ struct _Controller {
uint8_t event_storage[400];
StateFunc state;
DataLink *datalink;
Sequencer *sequencer;
};


static void handleHostMessage(Controller *me, uint8_t const *msg, uint16_t nb)
{
char nt_msg[nb + 1];
strncpy(nt_msg, (const char *)msg, nb);
nt_msg[nb] = '\0';
CLI_handleConsoleInput(nt_msg, nb);
BSP_logf("%s, len=%hu\n", __func__, nb);
}


Expand All @@ -51,10 +50,10 @@ static void *stateIdle(Controller *me, AOEvent const *evt)
switch (AOEvent_type(evt))
{
case ET_AO_ENTRY:
BSP_logf("%s ENTRY\n", __func__);
BSP_logf("Controller_%s ENTRY\n", __func__);
break;
case ET_AO_EXIT:
BSP_logf("%s EXIT\n", __func__);
BSP_logf("Controller_%s EXIT\n", __func__);
break;
default:
BSP_logf("Controller_%s unexpected event: %u\n", __func__, AOEvent_type(evt));
Expand All @@ -65,7 +64,7 @@ static void *stateIdle(Controller *me, AOEvent const *evt)
// Send one event to the state machine.
static void dispatchEvent(Controller *me, AOEvent const *evt)
{
BSP_logf("%s(%u)\n", __func__, evt);
// BSP_logf("%s(%u)\n", __func__, AOEvent_type(evt));
StateFunc new_state = me->state(me, evt);
if (new_state != NULL) { // Transition.
StateFunc sf = me->state(me, AOEvent_newExitEvent());
Expand Down Expand Up @@ -95,6 +94,7 @@ void Controller_init(Controller *me, DataLink *datalink)
me->datalink = datalink;
BSP_logf("%s\n", __func__);
me->state = &stateIdle;
me->state(me, AOEvent_newEntryEvent());
DataLink_open(me->datalink, me, (PacketCallback)&handleHostMessage);
DataLink_waitForSync(me->datalink);
}
Expand All @@ -103,12 +103,9 @@ void Controller_init(Controller *me, DataLink *datalink)
void Controller_start(Controller *me)
{
BSP_logf("Starting NeoDK!\n");
BSP_logf("Push the button to play or pause! :-)\n");
BSP_logf("Push the button to play or pause :-)\n");
BSP_setPrimaryVoltage_mV(2500);
BSP_primaryVoltageEnable(true);

me->state = stateIdle;
me->state(me, AOEvent_newEntryEvent());
}


Expand Down
66 changes: 49 additions & 17 deletions firmware/src/datalink.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@
*/

#include <stdlib.h>
#include <string.h>

#include "bsp_dbg.h"
#include "bsp_mao.h"
#include "bsp_app.h"
#include "circbuffer.h"
#include "net_frame.h"
#include "debug_cli.h" // Temporary.

// This module implements:
#include "datalink.h"
Expand Down Expand Up @@ -95,15 +97,35 @@ static uint32_t writeFrame(DataLink *me, uint8_t const *frame, uint32_t nb)
}


static void respondWithAckFrame(DataLink *me, uint8_t ack_nr)
static void respondWithAckFrame(DataLink *me, uint8_t ack_nr, NetworkServiceType nst)
{
uint8_t ack_frame[me->header_size];
PhysFrame_initHeaderWithAck((PhysFrame *)ack_frame, FT_ACK, 0, ack_nr);
PhysFrame_initHeaderWithAck((PhysFrame *)ack_frame, FT_ACK, 0, ack_nr, nst);
BSP_logf("%s(%hhu) to controller\n", __func__, ack_nr);
writeFrame(me, ack_frame, sizeof ack_frame);
}


static void handleIncomingDataFrame(DataLink *me, PhysFrame const *frame)
{
uint8_t rx_seq_nr = PhysFrame_seqNr(frame);
uint16_t payload_size = PhysFrame_payloadSize(frame);
BSP_logf("Got packet, seq_nr=%hhu, payload_size=%hu\n", rx_seq_nr, payload_size);
NetworkServiceType nst = PhysFrame_serviceType(frame);
respondWithAckFrame(me, rx_seq_nr, nst);

uint8_t const *payload = PhysFrame_payload(frame);
if (nst == NST_DEBUG) {
char zt_msg[payload_size + 1];
strncpy(zt_msg, (const char *)payload, payload_size);
zt_msg[payload_size] = '\0';
CLI_handleConsoleInput(zt_msg, payload_size);
} else {
me->packet_callback(me->packet_handler, payload, payload_size);
}
}


static void handleIncomingFrame(DataLink *me, PhysFrame const *frame)
{
if (! PhysFrame_isIntact(frame)) {
Expand All @@ -115,35 +137,33 @@ static void handleIncomingFrame(DataLink *me, PhysFrame const *frame)
if (frame_type == FT_ACK) {
uint8_t ack_nr = PhysFrame_ackNr(frame);
BSP_logf("Got ACK for frame %hhu\n", ack_nr);
me->tx_seq_nr = (ack_nr + 1) & 0xf;
me->tx_seq_nr = (ack_nr + 1) & 0x7;
return;
}

uint8_t rx_seq_nr = PhysFrame_seqNr(frame);
if (frame_type == FT_SYNC) {
BSP_logf("Got SYNC frame, seq_nr=%hhu\n", rx_seq_nr);
respondWithAckFrame(me, rx_seq_nr);
respondWithAckFrame(me, rx_seq_nr, PhysFrame_serviceType(frame));
return;
}

uint16_t payload_size = PhysFrame_payloadSize(frame);
if (frame_type == FT_DATA) {
BSP_logf("Got packet, seq_nr=%hhu, payload_size=%hu\n", rx_seq_nr, payload_size);
respondWithAckFrame(me, rx_seq_nr);
me->packet_callback(me->packet_handler, PhysFrame_payload(frame), payload_size);
return;
handleIncomingDataFrame(me, frame);
} else {
BSP_logf("Got %s frame, seq_nr=%hhu, payload_size=%hu\n",
PhysFrame_frameTypeName(frame_type), rx_seq_nr, payload_size);
}

BSP_logf("Got %s frame, seq_nr=%hhu, payload_size=%hu\n",
PhysFrame_typeName(frame_type), rx_seq_nr, payload_size);
}


static void rxCallback(DataLink *me, uint32_t ch)
{
if (! me->synced) {
if (ch == '\n') { // Dweeb's poll character.
respondWithAckFrame(me, 0x7);
respondWithAckFrame(me, 0x7, NST_DATAGRAM);
me->synced = true;
} else if (assembleIncomingFrame(me, (uint8_t)ch) == FT_SYNC) {
// BSP_logf("Byte %2hu is 0x%02x\n", me->rx_nb, ch);
handleIncomingFrame(me, (PhysFrame const *)me->rx_frame_buffer);
Expand Down Expand Up @@ -181,6 +201,15 @@ static void txErrorCallback(DataLink *me, uint32_t tx_error)
BSP_logf("%s(%u)\n", __func__, tx_error);
}


static bool sendPacket(DataLink *me, NetworkServiceType nst, uint8_t const *packet, uint16_t nb)
{
uint8_t frame_store[me->header_size + nb];
PhysFrame_init((PhysFrame *)frame_store, FT_DATA, me->tx_seq_nr, NST_DEBUG, packet, nb);
// BSP_logf("Writing frame with size %hu to buffer\n", sizeof frame_store);
return writeFrame(me, frame_store, sizeof frame_store) == sizeof frame_store;
}

/*
* Below are the functions implementing this module's interface.
*/
Expand Down Expand Up @@ -228,12 +257,15 @@ void DataLink_waitForSync(DataLink *me)
}


bool DataLink_sendPacket(DataLink *me, uint8_t const *packet, uint16_t nb)
bool DataLink_sendDebugPacket(DataLink *me, uint8_t const *packet, uint16_t nb)
{
uint8_t frame_store[me->header_size + nb];
PhysFrame_init((PhysFrame *)frame_store, FT_DATA, me->tx_seq_nr, packet, nb);
// BSP_logf("Writing frame with size %hu to buffer\n", sizeof frame_store);
return writeFrame(me, frame_store, sizeof frame_store) == sizeof frame_store;
return sendPacket(me, NST_DEBUG, packet, nb);
}


bool DataLink_sendDatagram(DataLink *me, uint8_t const *datagram, uint16_t nb)
{
return sendPacket(me, NST_DATAGRAM, datagram, nb);
}


Expand Down
11 changes: 7 additions & 4 deletions firmware/src/debug_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ static void interpretCommand(CmndInterp *me, char ch)
switch (ch)
{
case '?':
CLI_logf("Commands: /? /a /b /d /l /q /u /v /0 /1../9\n");
CLI_logf("Commands: /? /a /b /d /l /n /q /u /v /0 /1../9\n");
break;
case '0':
BSP_primaryVoltageEnable(false);
Expand All @@ -73,6 +73,9 @@ static void interpretCommand(CmndInterp *me, char ch)
case 'l':
BSP_toggleTheLED();
break;
case 'n':
EventQueue_postEvent(me->delegate_queue, ET_NEXT_ROUTINE, NULL, 0);
break;
case 'q': { // Quit.
int sig = 2; // Simulate Ctrl-C.
EventQueue_postEvent(me->delegate_queue, ET_POSIX_SIGNAL, (uint8_t const *)&sig, sizeof sig);
Expand All @@ -82,7 +85,7 @@ static void interpretCommand(CmndInterp *me, char ch)
BSP_changePrimaryVoltage_mV(+200);
break;
case 'v':
CLI_logf("Firmware V0.24-beta\n");
CLI_logf("Firmware V0.25-beta\n");
break;
default:
CLI_logf("Unknown command '/%c'\n", ch);
Expand Down Expand Up @@ -112,7 +115,7 @@ static void vLogToUser(CmndInterp *me, char const *fmt, va_list args)
{
char msg[80];
int nbw = vsnprintf(msg, sizeof msg, fmt, args);
if (nbw > 0) DataLink_sendPacket(me->datalink, (uint8_t const *)msg, nbw + 1);
if (nbw > 0) DataLink_sendDebugPacket(me->datalink, (uint8_t const *)msg, nbw + 1);
}

/*
Expand Down Expand Up @@ -140,7 +143,7 @@ int CLI_logf(char const *fmt, ...)
void CLI_handleConsoleInput(char const *cmnd, uint16_t nb)
{
if (nb == 2 && cmnd[0] == '/') interpretCommand(&my, cmnd[1]);
else CLI_logf("%s('%s')", __func__, cmnd);
else BSP_logf("%s('%s')\n", __func__, cmnd);
}


Expand Down
3 changes: 3 additions & 0 deletions firmware/src/neodk_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,9 @@ static void dispatchEvent(Boss *me, AOEvent const *evt)
case ET_BUTTON_RELEASED:
// Ignore for now.
break;
case ET_NEXT_ROUTINE:
EventQueue_repostEvent((EventQueue *)me->sequencer, evt);
break;
default:
BSP_logf("%s(%hu)?\n", __func__, evt_type);
}
Expand Down
16 changes: 8 additions & 8 deletions firmware/src/pattern_iter.c
Original file line number Diff line number Diff line change
Expand Up @@ -61,19 +61,19 @@ bool PatternIterator_checkPattern(uint8_t const pattern[][2], uint16_t nr_of_elc
}


void PatternIterator_init(PatternIterator *me, uint8_t const pattern[][2],
uint16_t nr_of_elcons, uint8_t pace_ms, uint16_t nr_of_reps, uint8_t nr_of_steps)
void PatternIterator_init(PatternIterator *me, PatternDescr const *pd)
{
me->pattern = pattern;
me->nr_of_elcons = nr_of_elcons;
me->pattern = pd->pattern;
me->nr_of_elcons = pd->nr_of_elcons;
me->pace_ms = pd->pace_ms;
me->nr_of_reps = pd->nr_of_reps;
me->nr_of_steps = pd->nr_of_steps; // Length of a transition.

me->pulse_width_micros = 80;
me->elcon_nr = 0;
me->nr_of_steps = nr_of_steps; // Length of a transition.
M_ASSERT(me->nr_of_steps != 0);
me->step_nr = 0;
me->segment_nr = 0; // 0 or 1.
me->pulse_width_micros = 80;
me->pace_ms = pace_ms;
me->nr_of_reps = nr_of_reps;
}


Expand Down
Loading

0 comments on commit 9c17496

Please sign in to comment.