Flatten msg triage switches to dispatch on first 3 bytes together (as uint32_t)

This commit is contained in:
Allen Hill
2026-05-16 00:32:45 +00:00
parent 79516796d5
commit 9fbaa7a55f
+131 -200
View File
@@ -887,6 +887,8 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame, log_t print) {
return err.errno; return err.errno;
} }
#define PACK3(a, b, c) (((uint32_t)(a) << 16) | ((uint32_t)(b) << 8) | (c))
response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) { response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) {
response_t respond = r_Nothing; response_t respond = r_Nothing;
@@ -896,7 +898,6 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) {
out->controller_addr = DEVICE_ADDR; out->controller_addr = DEVICE_ADDR;
out->control = 0xF; out->control = 0xF;
const uint16_t peripheral_addr = in->peripheral_addr;
const uint8_t *data = in->data; const uint8_t *data = in->data;
const uint8_t b0 = *data++; const uint8_t b0 = *data++;
const uint8_t b1 = *data++; const uint8_t b1 = *data++;
@@ -904,217 +905,147 @@ response_t AVCLAN_handleframe(const AVCLAN_frame_t *in, AVCLAN_frame_t *out) {
uint8_t b3 = 0; uint8_t b3 = 0;
if (in->length > 3) // the shortest known/valid messages are 3 bytes long if (in->length > 3) // the shortest known/valid messages are 3 bytes long
b3 = *data++; b3 = *data++;
uint8_t from;
// BROADCAST
if (!in->is_unicast) { if (!in->is_unicast) {
// skip confirming peripheral_addr, because it will be 0xFFF or 0x1FF based // Broadcast: bytes are (from, to, action, [extra...]).
// on all currently known examples // peripheral_addr unchecked — always 0xFFF or 0x1FF in known traffic.
switch (b0 /* "from" device */) { switch (PACK3(b0, b1, b2)) {
case dev_LAN: case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_Scan_Req):
switch (b1 /* "to" device */) { out->length = sizeof(lancheck_resp);
case dev_COMM_CTRL: out->is_unicast = true;
switch (b2 /* device action */) { out->peripheral_addr = HU_ADDR;
case Lancheck_Scan_Req: memcpy(out->data, lancheck_resp, sizeof(lancheck_resp));
out->length = sizeof(lancheck_resp); out->data[3] = Lancheck_Scan_Resp;
memcpy(out->data, lancheck_resp, sizeof(lancheck_resp)); out->data[4] = 0x01;
out->data[3] = Lancheck_Scan_Resp; respond = r_Handled;
out->data[4] = 0x01; break;
goto LAN_RESPONSE; case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_Req):
case Lancheck_Req: out->length = sizeof(lancheck_resp);
out->length = sizeof(lancheck_resp); out->is_unicast = true;
memcpy(out->data, lancheck_resp, sizeof(lancheck_resp)); out->peripheral_addr = HU_ADDR;
out->data[3] = Lancheck_Resp; memcpy(out->data, lancheck_resp, sizeof(lancheck_resp));
out->data[4] = 0x00; out->data[3] = Lancheck_Resp;
goto LAN_RESPONSE; out->data[4] = 0x00;
case Lancheck_End_Req: respond = r_Handled;
out->length = sizeof(lancheck_resp) - 1; break;
memcpy(out->data, lancheck_resp, out->length); case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_End_Req):
out->data[3] = Lancheck_End_Resp; out->is_unicast = true;
goto LAN_RESPONSE; out->peripheral_addr = HU_ADDR;
default: out->length = sizeof(lancheck_resp) - 1;
break; memcpy(out->data, lancheck_resp, out->length);
LAN_RESPONSE: out->data[3] = Lancheck_End_Resp;
out->is_unicast = true; respond = r_Handled;
out->peripheral_addr = HU_ADDR; break;
respond = r_Handled; case PACK3(dev_COMM_v1, dev_COMM_CTRL, Current_Function):
} case PACK3(dev_COMM_v2, dev_COMM_CTRL, Current_Function):
break; if ((b3 == dev_CD_CHANGER) && !AVCLAN_isPlaying()) {
default: cd_status.state = cd_SEEKING | cd_SEEKING_TRACK;
cd_status.flags2 = 0x80;
AVCLAN_startPlaying();
AVCLAN_generateStatus(out);
respond = r_NormalizeState;
} }
break; break;
case dev_COMM_v1: case PACK3(dev_COMM_v1, dev_COMM_CTRL, Ping_Req):
case dev_COMM_v2: case PACK3(dev_COMM_v2, dev_COMM_CTRL, Ping_Req):
if (b1 /* "to" device */ == dev_COMM_CTRL) { out->is_unicast = true;
switch (b2 /* device action */) { out->peripheral_addr = HU_ADDR;
case Current_Function: out->length = sizeof(ping_resp);
if ((b3 == dev_CD_CHANGER) && !AVCLAN_isPlaying()) { memcpy(out->data, ping_resp, sizeof(ping_resp));
cd_status.state = cd_SEEKING | cd_SEEKING_TRACK; out->data[4] = b3;
cd_status.flags2 = 0x80; respond = r_Handled;
AVCLAN_startPlaying();
AVCLAN_generateStatus(out);
respond = r_NormalizeState;
}
break;
case Ping_Req:
out->is_unicast = true;
out->peripheral_addr = HU_ADDR;
out->length = sizeof(ping_resp);
memcpy(out->data, ping_resp, sizeof(ping_resp));
out->data[4] = b3;
respond = r_Handled;
break;
case List_Functions_Req:
out->is_unicast = true;
out->peripheral_addr = HU_ADDR;
out->length = sizeof(list_functions_resp);
memcpy(out->data, list_functions_resp,
sizeof(list_functions_resp));
respond = r_Handled;
break;
// case Restart_Lan:
// break;
default:
}
}
break; break;
default: case PACK3(dev_COMM_v1, dev_COMM_CTRL, List_Functions_Req):
case PACK3(dev_COMM_v2, dev_COMM_CTRL, List_Functions_Req):
out->is_unicast = true;
out->peripheral_addr = HU_ADDR;
out->length = sizeof(list_functions_resp);
memcpy(out->data, list_functions_resp, sizeof(list_functions_resp));
respond = r_Handled;
break;
// case Restart_Lan: not handled
} }
} else if (peripheral_addr == DEVICE_ADDR) { // unicast to CD changer } else if (in->peripheral_addr == DEVICE_ADDR && b0 == 0x00) {
if (b0 == 0) { // unicasts begin with a zero-byte // Unicast to CD changer: bytes are (0x00, from, to, action, [extra...]).
from = b1; switch (PACK3(b1, b2, b3)) {
switch (from) { case PACK3(dev_COMM_v1, dev_CD_CHANGER, Enable_Function_Req):
case dev_COMM_v1: case PACK3(dev_COMM_v2, dev_CD_CHANGER, Enable_Function_Req):
case dev_COMM_v2: out->is_unicast = true;
switch (b2 /* "to" device */) { out->peripheral_addr = HU_ADDR;
case dev_CD_CHANGER: out->length = sizeof(function_change_resp);
switch (b3 /* device action */) { memcpy(out->data, function_change_resp, sizeof(function_change_resp));
case Enable_Function_Req: out->data[3] = Enable_Function_Resp;
out->length = sizeof(function_change_resp); cd_status.state = cd_SEEKING | cd_SEEKING_TRACK;
memcpy(out->data, function_change_resp, cd_status.flags2 = 0xc0;
sizeof(function_change_resp)); AVCLAN_startPlaying();
out->data[3] = Enable_Function_Resp; respond = r_StartPlaying;
cd_status.state = cd_SEEKING | cd_SEEKING_TRACK; break;
cd_status.flags2 = 0xc0; case PACK3(dev_COMM_v1, dev_CD_CHANGER, Disable_Function_Req):
// *cd_Time_Min = 0xff; case PACK3(dev_COMM_v2, dev_CD_CHANGER, Disable_Function_Req):
// *cd_Time_Sec = 0x7f; AVCLAN_stopPlaying();
AVCLAN_startPlaying(); out->length = sizeof(function_change_resp);
respond = r_StartPlaying; memcpy(out->data, function_change_resp, sizeof(function_change_resp));
goto FUNCTION_CHANGE_RESPONSE; out->data[3] = Disable_Function_Resp;
case Disable_Function_Req: cd_status.state = cd_PLAYBACK | cd_SEEKING_TRACK;
AVCLAN_stopPlaying(); cd_status.flags2 = 0x80;
out->length = sizeof(function_change_resp); out->is_unicast = true;
memcpy(out->data, function_change_resp, out->peripheral_addr = HU_ADDR;
sizeof(function_change_resp)); respond = r_StatusReport;
out->data[3] = Disable_Function_Resp; break;
cd_status.state = cd_PLAYBACK | cd_SEEKING_TRACK; case PACK3(dev_CMD_SW, dev_CD_CHANGER, Initial_Report_Request):
// *cd_Time_Min = 0x00; case PACK3(dev_STATUS, dev_CD_CHANGER, Initial_Report_Request):
// *cd_Time_Sec = 0x00; out->length = sizeof(cdinitreport_resp);
cd_status.flags2 = 0x80; memcpy(out->data, cdinitreport_resp, sizeof(cdinitreport_resp));
respond = r_StatusReport; out->data[1] = b1; // respond to device that requested
goto FUNCTION_CHANGE_RESPONSE; out->is_unicast = true;
default: out->peripheral_addr = HU_ADDR;
break; break;
FUNCTION_CHANGE_RESPONSE: case PACK3(dev_CMD_SW, dev_CD_CHANGER, Playback_Request):
out->is_unicast = true; case PACK3(dev_STATUS, dev_CD_CHANGER, Playback_Request):
out->peripheral_addr = HU_ADDR; out->data[1] = b1;
} out->data[2] = Playback_Report;
break; out->length = sizeof(cdstatus_resp);
default: serializeCDStatus(&out->data[3]);
} out->is_unicast = true;
break; out->peripheral_addr = HU_ADDR;
case dev_CMD_SW: break;
switch (b2 /* "to" device */) { case PACK3(dev_CMD_SW, dev_CD_CHANGER, Loading_Request2):
case dev_CD_CHANGER: case PACK3(dev_STATUS, dev_CD_CHANGER, Loading_Request2):
switch (b3 /* device action */) { out->length = sizeof(cdloading_resp);
case Initial_Report_Request: memcpy(out->data, cdloading_resp, sizeof(cdloading_resp));
out->length = sizeof(cdinitreport_resp); out->data[1] = b1;
memcpy(out->data, cdinitreport_resp, out->data[2] = Loading_Response2;
sizeof(cdinitreport_resp)); out->is_unicast = true;
out->data[1] = from; // respond to device that requested out->peripheral_addr = HU_ADDR;
goto CMD_SW_RESPONSE; break;
case Playback_Request: case PACK3(dev_CMD_SW, dev_CD_CHANGER, Track_Seek_Up):
out->data[1] = from; // respond to device that requested cd_status.state = cd_SEEKING_TRACK;
out->data[2] = Playback_Report; (*cd_Track)++;
out->length = sizeof(cdstatus_resp); *cd_Time_Min = 0xff;
serializeCDStatus(&out->data[3]); *cd_Time_Sec = 0x7f;
goto CMD_SW_RESPONSE; cd_status.flags |= cd_SCAN;
case Loading_Request2: cd_status.flags2 = 0xc0;
out->length = sizeof(cdloading_resp); AVCLAN_generateStatus(out);
memcpy(out->data, cdloading_resp, sizeof(cdloading_resp)); respond = r_TrackChange;
out->data[1] = from; break;
out->data[2] = Loading_Response2; case PACK3(dev_CMD_SW, dev_CD_CHANGER, Track_Seek_Down):
goto CMD_SW_RESPONSE; cd_status.state = cd_SEEKING_TRACK;
case Track_Seek_Up: (*cd_Track)--;
cd_status.state = cd_SEEKING_TRACK; *cd_Time_Min = 0xff;
(*cd_Track)++; *cd_Time_Sec = 0x7f;
*cd_Time_Min = 0xff; cd_status.flags |= cd_SCAN;
*cd_Time_Sec = 0x7f; cd_status.flags2 = 0xc0;
cd_status.flags |= cd_SCAN; AVCLAN_generateStatus(out);
cd_status.flags2 = 0xc0; respond = r_TrackChange;
respond = r_TrackChange; break;
AVCLAN_generateStatus(out);
break;
case Track_Seek_Down:
cd_status.state = cd_SEEKING_TRACK;
(*cd_Track)--;
*cd_Time_Min = 0xff;
*cd_Time_Sec = 0x7f;
cd_status.flags |= cd_SCAN;
cd_status.flags2 = 0xc0;
respond = r_TrackChange;
AVCLAN_generateStatus(out);
break;
default:
break;
CMD_SW_RESPONSE:
out->is_unicast = true;
out->peripheral_addr = HU_ADDR;
}
break;
default:
}
break;
case dev_STATUS:
switch (b2 /* "to" device */) {
case dev_CD_CHANGER:
switch (b3 /* device action */) {
case Initial_Report_Request:
out->length = sizeof(cdinitreport_resp);
memcpy(out->data, cdinitreport_resp,
sizeof(cdinitreport_resp));
out->data[1] = from; // respond to device that requested
goto STATUS_RESPONSE;
case Playback_Request:
out->data[1] = from; // respond to device that requested
out->data[2] = Playback_Report;
out->length = sizeof(cdstatus_resp);
serializeCDStatus(&out->data[3]);
goto STATUS_RESPONSE;
case Loading_Request2:
out->length = sizeof(cdloading_resp);
memcpy(out->data, cdloading_resp, sizeof(cdloading_resp));
out->data[1] = from;
out->data[2] = Loading_Response2;
goto STATUS_RESPONSE;
default:
break;
STATUS_RESPONSE:
out->is_unicast = true;
out->peripheral_addr = HU_ADDR;
}
break;
default:
}
break;
default:
}
} }
} }
return respond; return respond;
} }
#undef PACK3
uint8_t AVCLAN_tryrespond(const AVCLAN_frame_t *resp) { uint8_t AVCLAN_tryrespond(const AVCLAN_frame_t *resp) {
uint8_t r = 0; uint8_t r = 0;
for (uint8_t i = 0; i < MAX_SEND_ATTEMPTS; i++) { for (uint8_t i = 0; i < MAX_SEND_ATTEMPTS; i++) {