Skip to content

Commit

Permalink
Basic event subscription mechanism.
Browse files Browse the repository at this point in the history
  • Loading branch information
Onwrikbaar committed Oct 15, 2024
1 parent fe11fd0 commit 2d7c368
Show file tree
Hide file tree
Showing 14 changed files with 1,651 additions and 1,573 deletions.
2 changes: 1 addition & 1 deletion firmware/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ PROJ_COMMON_SRC += \
$(PROJ_DIR_SRC)/pattern_iter.c \
$(PROJ_DIR_SRC)/datalink.c \
$(PROJ_DIR_SRC)/debug_cli.c \
$(PROJ_DIR_SRC)/matter.c \
$(PROJ_DIR_SRC)/attributes.c \

# Target-dependent include folders.
STM32G0xx_INC += \
Expand Down
2,895 changes: 1,459 additions & 1,436 deletions firmware/build/neodk_g071.hex

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions firmware/inc/app_event.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,9 @@ enum {
ET_THIRD_PARTY = ET_AO_FIRST_APP_EVENT, // To keep other libs working.
ET_APP_HEARTBEAT, ET_ADC_DATA_AVAILABLE,
ET_DEBUG_SYNC, ET_DATAGRAM_SYNC, ET_INCOMING_PACKET,
ET_CONTROLLER_CONNECTED, ET_CONTROLLER_DISCONNECTED,
ET_CONTROLLER_CONNECTED, ET_CONTROLLER_DISCONNECTED, ET_ATTRIBUTE_CHANGED,
ET_PLAY, ET_PAUSE, ET_STOP, ET_UNKNOWN_COMMAND, ET_TOGGLE_PLAY_PAUSE,
ET_SELECT_NEXT_PATTERN, ET_SELECT_PATTERN_BY_NAME, ET_SET_INTENSITY, ET_SET_PULSE_WIDTH,
ET_SELECT_NEXT_PATTERN, ET_SELECT_PATTERN_BY_NAME, ET_SET_INTENSITY,
ET_BURST_REQUESTED, ET_BURST_REJECTED, ET_BURST_STARTED, ET_BURST_COMPLETED, ET_BURST_EXPIRED,
};

Expand Down
29 changes: 29 additions & 0 deletions firmware/inc/attributes.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
/*
* attributes.h
*
* NOTICE (do not remove):
* This file is part of project NeoDK (https://github.com/Onwrikbaar/NeoDK).
* See https://github.com/Onwrikbaar/NeoDK/blob/main/LICENSE.txt for full license details.
*
* Created on: 15 Oct 2024
* Author: mark
* Copyright 2024 Neostim™
*/

#ifndef INC_ATTRIBUTES_H_
#define INC_ATTRIBUTES_H_

#include "matter.h"


typedef enum {
AI_ALL_PATTERN_NAMES = 5, AI_CURRENT_PATTERN_NAME, AI_INTENSITY_PERCENT, AI_PLAY_PAUSE_STOP
} AttributeId;

typedef void (*AttrNotifier)(void *target, AttributeId, ElementEncoding, uint8_t const *data, uint16_t size);


bool Attribute_subscribe(AttributeId, ElementEncoding, AttrNotifier, void *target);
void Attribute_changed(AttributeId, uint8_t const *data, uint16_t size);

#endif
3 changes: 2 additions & 1 deletion firmware/inc/debug_cli.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,11 @@
#define INC_DEBUG_CLI_H_

#include "eventqueue.h"
#include "sequencer.h"
#include "datalink.h"


void CLI_init(EventQueue *, DataLink *);
void CLI_init(EventQueue *, Sequencer *, DataLink *);
int CLI_logf(char const *fmt, ...);
void CLI_handleRemoteInput(uint8_t const *, uint16_t nb);

Expand Down
2 changes: 2 additions & 0 deletions firmware/inc/sequencer.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@

typedef struct _Sequencer Sequencer; // Opaque type.

typedef enum { PS_UNKNOWN, PS_IDLE, PS_PAUSED, PS_PLAYING } PlayState;

// Class method.
Sequencer *Sequencer_new(void);

Expand Down
2 changes: 2 additions & 0 deletions firmware/inc/matter.h → firmware/maolib/inc/matter.h
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ uint16_t Matter_encodedStringLength(char const *str);
uint16_t Matter_encodeString(uint8_t dst[], char const *str);
uint16_t Matter_encodedStringArrayLength(char const *strings[], uint8_t nr_of_strings);
uint16_t Matter_encodeStringArray(uint8_t dst[], char const *strings[], uint8_t nr_of_strings);
uint16_t Matter_encodedDataLength(ElementEncoding enc, uint16_t nr_of_octets);
uint16_t Matter_encodeData(uint8_t dst[], ElementEncoding, uint8_t const *src, uint16_t nr_of_octets);

#ifdef __cplusplus
}
Expand Down
Binary file modified firmware/maolib/libmao.a
Binary file not shown.
66 changes: 66 additions & 0 deletions firmware/src/attributes.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
/*
* attributes.c
*
* NOTICE (do not remove):
* This file is part of project NeoDK (https://github.com/Onwrikbaar/NeoDK).
* See https://github.com/Onwrikbaar/NeoDK/blob/main/LICENSE.txt for full license details.
*
* Created on: 15 Oct 2024
* Author: mark
* Copyright 2024 Neostim™
*/

#include "bsp_dbg.h"
#include "convenience.h"

// This module implements:
#include "attributes.h"


typedef struct {
AttributeId ai; // Key.
ElementEncoding encoding;
AttrNotifier notify;
void *target;
} Subscription;


static Subscription subscriptions[4];
static uint8_t nr_of_subs = 0;


static Subscription const *findSubForId(AttributeId ai)
{
for (uint8_t i = 0; i < M_DIM(subscriptions); i++) {
Subscription const *sub = &subscriptions[i];
if (ai == sub->ai) return sub;
}
return NULL;
}

/*
* Below are the functions implementing this module's interface.
*/

bool Attribute_subscribe(AttributeId ai, ElementEncoding enc, AttrNotifier notify, void *target)
{
BSP_logf("%s for id=%hu\n", __func__, ai);
if (nr_of_subs == M_DIM(subscriptions)) return false;

Subscription *sub = &subscriptions[nr_of_subs++];
sub->ai = ai;
sub->encoding = enc;
sub->notify = notify;
sub->target = target;
return true;
}


void Attribute_changed(AttributeId ai, uint8_t const *data, uint16_t size)
{
// BSP_logf("%s(%hu)\n", __func__, ai);
Subscription const *sub = findSubForId(ai);
if (sub != NULL) {
sub->notify(sub->target, ai, sub->encoding, data, size);
}
}
45 changes: 35 additions & 10 deletions firmware/src/controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
#include "bsp_dbg.h"
#include "bsp_app.h"
#include "matter.h"
#include "attributes.h"
#include "app_event.h"

// This module implements:
Expand All @@ -29,10 +30,6 @@ typedef struct {
uint8_t message[0];
} PacketHeader;

typedef enum {
AI_ALL_PATTERN_NAMES = 5, AI_CURRENT_PATTERN_NAME, AI_INTENSITY_PERCENT, AI_PLAY_PAUSE_STOP
} AttributeId;

typedef struct {
uint16_t transaction_id;
uint8_t opcode;
Expand All @@ -43,7 +40,6 @@ typedef struct {


typedef void *(*StateFunc)(Controller *, AOEvent const *);

struct _Controller {
EventQueue event_queue; // This MUST be the first member.
uint8_t event_storage[400];
Expand All @@ -56,13 +52,17 @@ struct _Controller {
static uint8_t const welcome_msg[] = "Push the button to play or pause :-)\n";


static void initResponsePacket(PacketHeader *ph, AttributeAction const *req_aa)
static void initResponsePacket(PacketHeader *ph)
{
ph->flags = 0x00;
ph->dst_address = ph->src_address;
ph->src_address = 0x0000; // TODO Use our real address.
ph->reserved = 0x00;
AttributeAction *rsp_aa = (AttributeAction *)ph->message;
}


static void initAttributeAction(AttributeAction *rsp_aa, AttributeAction const *req_aa)
{
*rsp_aa = *req_aa; // Copy the request.
rsp_aa->opcode = OC_REPORT_DATA; // Only change the opcode.
}
Expand All @@ -77,7 +77,8 @@ static void readPatternNames(Controller *me, AttributeAction const *aa)
uint16_t packet_size = nbtw + Matter_encodedStringArrayLength(pattern_names, nr_of_patterns);
// TODO Ensure packet_size does not exceed max frame payload size.
uint8_t packet[packet_size];
initResponsePacket((PacketHeader *)packet, aa);
initResponsePacket((PacketHeader *)packet);
initAttributeAction((AttributeAction *)(packet + sizeof(PacketHeader)), aa);
nbtw += Matter_encodeStringArray(packet + nbtw, pattern_names, nr_of_patterns);
DataLink_sendDatagram(me->datalink, packet, nbtw);
}
Expand All @@ -89,7 +90,8 @@ static void readCurrentPatternName(Controller *me, AttributeAction const *aa)
uint16_t nbtw = sizeof(PacketHeader) + sizeof(AttributeAction);
uint16_t packet_size = nbtw + Matter_encodedStringLength(cpn);
uint8_t packet[packet_size];
initResponsePacket((PacketHeader *)packet, aa);
initResponsePacket((PacketHeader *)packet);
initAttributeAction((AttributeAction *)(packet + sizeof(PacketHeader)), aa);
nbtw += Matter_encodeString(packet + nbtw, cpn);
DataLink_sendDatagram(me->datalink, packet, nbtw);
}
Expand All @@ -101,12 +103,31 @@ static void readIntensityPercentage(Controller *me, AttributeAction const *aa)
uint16_t nbtw = sizeof(PacketHeader) + sizeof(AttributeAction);
uint16_t packet_size = nbtw + Matter_encodedIntegerLength(sizeof intensity);
uint8_t packet[packet_size];
initResponsePacket((PacketHeader *)packet, aa);
initResponsePacket((PacketHeader *)packet);
initAttributeAction((AttributeAction *)(packet + sizeof(PacketHeader)), aa);
nbtw += Matter_encodeUnsignedInteger(packet + nbtw, &intensity, sizeof intensity);
DataLink_sendDatagram(me->datalink, packet, nbtw);
}


static void attributeChanged(Controller *me, AttributeId ai, ElementEncoding enc, uint8_t const *data, uint16_t data_size)
{
// BSP_logf("Controller_%s(%hu) size=%hu\n", __func__, ai, data_size);
uint16_t nbtw = sizeof(PacketHeader) + sizeof(AttributeAction);
uint16_t packet_size = nbtw + Matter_encodedDataLength(enc, data_size);
uint8_t packet[packet_size];
initResponsePacket((PacketHeader *)packet);
AttributeAction *aa = (AttributeAction *)(packet + sizeof(PacketHeader));
aa->transaction_id = 0;
aa->opcode = OC_REPORT_DATA;
aa->reserved = 0;
aa->attribute_id = ai;
// TODO Add subscription Id?
nbtw += Matter_encodeData(packet + nbtw, enc, data, data_size);
DataLink_sendDatagram(me->datalink, packet, nbtw);
}


static void handleReadRequest(Controller *me, AttributeAction const *aa)
{
switch (aa->attribute_id)
Expand Down Expand Up @@ -262,6 +283,10 @@ void Controller_start(Controller *me)
me->state(me, AOEvent_newEntryEvent());
DataLink_open(me->datalink, &me->event_queue);
DataLink_waitForSync(me->datalink);
// In practice these subscriptions will be made by the controlling client.
Attribute_subscribe(AI_CURRENT_PATTERN_NAME, EE_UTF8_1LEN, (AttrNotifier)&attributeChanged, me);
Attribute_subscribe(AI_INTENSITY_PERCENT, EE_UNSIGNED_INT_1, (AttrNotifier)&attributeChanged, me);
Attribute_subscribe(AI_PLAY_PAUSE_STOP, EE_UNSIGNED_INT_1, (AttrNotifier)&attributeChanged, me);
BSP_logf("Starting NeoDK!\n%s", welcome_msg);
}

Expand Down
43 changes: 21 additions & 22 deletions firmware/src/debug_cli.c
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@

typedef struct {
uint8_t buf[20];
EventQueue *delegate_queue;
EventQueue *delegate;
Sequencer *sequencer;
DataLink *datalink;
uint16_t V_prim_mV;
uint8_t state;
uint8_t len;
} CmndInterp;
Expand All @@ -44,20 +44,18 @@ static void gatherInputCharacters(CmndInterp *me, char ch)
}


static void setPrimaryVoltage_mV(CmndInterp *me, uint16_t mV)
static void setIntensity(CmndInterp *me, uint8_t intensity_perc)
{
me->V_prim_mV = BSP_setPrimaryVoltage_mV(mV);
uint8_t pulse_width = 40 + me->V_prim_mV / 100;
EventQueue_postEvent(me->delegate_queue, ET_SET_PULSE_WIDTH, &pulse_width, sizeof pulse_width);
EventQueue_postEvent(me->delegate, ET_SET_INTENSITY, &intensity_perc, sizeof intensity_perc);
}


static void changePrimaryVoltage_mV(CmndInterp *me, int16_t delta_mV)
static void changeIntensity(CmndInterp *me, int8_t delta_perc)
{
int32_t soll_mV = (int32_t)me->V_prim_mV + delta_mV;
if (soll_mV < 1000) soll_mV = 1000;
else if (soll_mV > 10200) soll_mV = 10200;
setPrimaryVoltage_mV(me, soll_mV);
int16_t soll_perc = (int16_t)Sequencer_getIntensityPercentage(me->sequencer) + delta_perc;
if (soll_perc < 10) soll_perc = 10;
else if (soll_perc > 100) soll_perc = 100;
setIntensity(me, soll_perc);
}

/**
Expand All @@ -72,38 +70,38 @@ static void interpretCommand(CmndInterp *me, char ch)
break;
case '0':
BSP_primaryVoltageEnable(false);
setPrimaryVoltage_mV(me, 0);
setIntensity(me, 0);
break;
case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9':
setPrimaryVoltage_mV(me, (ch - '0') * 1000U);
setIntensity(me, (ch - '0') * 10); // 0..90%.
BSP_primaryVoltageEnable(true); // Turn on the buck converter.
break;
case 'a':
BSP_triggerADC();
break;
case 'b': // Simulate a button press.
EventQueue_postEvent(me->delegate_queue, ET_BUTTON_PUSHED, NULL, 0);
EventQueue_postEvent(me->delegate_queue, ET_BUTTON_RELEASED, NULL, 0);
EventQueue_postEvent(me->delegate, ET_BUTTON_PUSHED, NULL, 0);
EventQueue_postEvent(me->delegate, ET_BUTTON_RELEASED, NULL, 0);
break;
case 'd': // Intensity down.
changePrimaryVoltage_mV(me, -100);
changeIntensity(me, -2);
break;
case 'l':
BSP_toggleTheLED();
break;
case 'n':
EventQueue_postEvent(me->delegate_queue, ET_SELECT_NEXT_PATTERN, NULL, 0);
EventQueue_postEvent(me->delegate, ET_SELECT_NEXT_PATTERN, 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);
EventQueue_postEvent(me->delegate, ET_POSIX_SIGNAL, (uint8_t const *)&sig, sizeof sig);
break;
}
case 'u': // Intensity up.
changePrimaryVoltage_mV(me, +100);
changeIntensity(me, +2);
break;
case 'v':
CLI_logf("Firmware v0.32-beta\n");
CLI_logf("Firmware v0.33-beta\n");
break;
case 'w': // Allow rediscovery by Dweeb.
DataLink_waitForSync(me->datalink);
Expand Down Expand Up @@ -143,9 +141,10 @@ static void vLogToUser(CmndInterp *me, char const *fmt, va_list args)
* Below are the functions implementing this module's interface.
*/

void CLI_init(EventQueue *dq, DataLink *datalink)
void CLI_init(EventQueue *dq, Sequencer *sequencer, DataLink *datalink)
{
my.delegate_queue = dq;
my.delegate = dq;
my.sequencer = sequencer;
my.datalink = datalink;
}

Expand Down
Loading

0 comments on commit 2d7c368

Please sign in to comment.