Another suggestion to improve Control Chain library

…or, in fact, the cc_slave core.

I’ve been looking into the code, and noticed that a hardware serial rx interrupt initiates a rather long chain of calls:
in ReUART.cpp

  1. ISR on an USART0_RX_vect vector calls _rx_complete_irq()
  2. _rx_complete_irq() calls uart_byte_recv()
  3. uart_byte_recv() calls cc_parse() from core.c, and, if the incoming message is complete,
  4. cc_parse() calls parcer(), also in core.c

I think this last step is a bit too much to be processed in an interrupt, so what I’ve done is I’ve included a simple flag into cc_handle_t:

typedef struct cc_handle_t {
void (*response_cb)(void *arg);
void (*events_cb)(void *arg);
    int comm_state, msg_state;
    cc_msg_t *msg_rx, *msg_tx;
    int device_id;
	int msg_rx_ok; // <-- ADDED
} cc_handle_t;

that in cc_parser I set to 1 if a message is received, and let the code finish processing the interrupt without calling the parser():

// crc
case 6:
  if (crc8(msg->header, CC_MSG_HEADER_SIZE + msg->data_size) == byte)
    //parser(handle); // commented this out, we'll do this later
    handle->msg_rx_ok = 1; // ADDED for quicker exit out of an interrupt
    msg_ok = 1;

and then I process the received message with parcer() in cc_process(), basically in the loop() of a main sketch, right before we get to checking the actuators’ states!

void cc_process(void)
  // see if we have an incoming message to process
  cc_handle_t *handle = &g_cc_handle;
  if (handle->msg_rx_ok) {
    handle->msg_rx_ok = 0;
  // process each actuator going through all assignments
  // data update messages will be queued and sent in the next frame

It seems to work smoothly. This even has allowed me to do some more heavy coding in the parcer(), like introducing new events and calling callbacks on those with output to LCD - for debugging purposes et al, which in case of the original code was not possible, e.g.:

  raise_event(handle, CC_EV_HANDSHAKE_INITIATED, 0);
  raise_event(handle, CC_EV_HANDSHAKE_SUCCESSFULL, 0);
  raise_event(handle, CC_EV_DEBUG, 0);

@jon, if you guys can also look into this, if it makes sense for the future incarnations of the code?


P.S. Ooh, now that I’m on a break form my band, I’m having so much fun digging this code!
P.P.S. But I can’t, for the life of me, get the library running on Arduino Mega. I hope this little change helps me debugging it.


I think it makes way more sense to discuss this on Github and not here on the forum.
Perhaps the discussions tab on the repository can be enabled for such things.


I will map this on our requests list, but simultaneously I will ping the developers. You included here pretty detailed info and a solution option, so - out of my ignorance - I would say if it fits and makes sense it can be pretty much implemented as it is when the update is processed. But don’t take my words as a guarantee :slight_smile:


No worries, @jon! I’m just sayin’ ))

1 Like

UPDATE: Got the library working on Arduino Mega 2560. Phew, it took me a couple of nights, it turned out that the silk on the board was marking pins incorrectly, TX1 and RX1 pins were mixed up. :man_facepalming: One look at the pinout on the Arduino site, et voila! RTFM, kids!


Jokes on you, I can’t read :slight_smile:


Hi, @jon! On a second thought, I withdraw this suggestion of mine. Although it does shorten the time of interrupt processing, it introduces unwanted delays into response time of an Arduino-based device, and it seems that control chain protocol is very much timeout-sensitive.
I’ve found other workarounds for my device, like pushing LCD screen updates out of processing of inbound messages into a separate queue to be later processed in a main cycle.
Apologies for inconvenience.


No worries :wink:
I actually talked with @Jan about this and he mentioned that this was not that easy to do because it would break other stuff (or something along these lines :wink: )


Yes, well, I’ve learned this the hard way :wink:

1 Like