1
0
mirror of https://github.com/halleysfifthinc/Toyota-AVC-LAN synced 2025-06-06 15:36:47 +00:00

Refactor frame handling and response code

This commit is contained in:
Allen Hill 2023-10-28 14:41:56 -04:00
parent 18ae9a48cc
commit fadd2c4259
3 changed files with 336 additions and 318 deletions

View File

@ -94,7 +94,9 @@
#include <avr/sfr_defs.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
#define VAR_DECLS
#include "avclandrv.h"
#include "com232.h"
@ -131,6 +133,7 @@
#define TCB_CNTMODE TCB_CNTMODE_PW_gc
#endif
#define MAX_SEND_ATTEMPTS 3
uint8_t printAllFrames;
uint8_t verbose;
@ -153,79 +156,19 @@ uint16_t period = 0;
uint16_t pulsewidth;
#define SW_ID 0x11 // 11 For my stereo
// commands
const uint8_t stat1[] = {0x00, 0x00, 0x01, 0x0A};
const uint8_t stat2[] = {0x00, 0x00, 0x01, 0x08};
const uint8_t stat3[] = {0x00, 0x00, 0x01, 0x0D};
const uint8_t stat4[] = {0x00, 0x00, 0x01, 0x0C};
// broadcast
const uint8_t lan_stat1[] = {0x00, 0x01, 0x0A};
const uint8_t lan_reg[] = {SW_ID, 0x01, 0x00};
const uint8_t lan_init[] = {SW_ID, 0x01, 0x01};
const uint8_t lan_check[] = {SW_ID, 0x01, 0x20};
const uint8_t lan_playit[] = {SW_ID, 0x01, 0x45, 0x63};
const uint8_t play_req1[] = {0x00, 0x25, 0x63, 0x80};
#ifdef __AVENSIS__
const uint8_t play_req2[] = {0x00, SW_ID, 0x63, 0x42};
#else
const uint8_t play_req2[] = {0x00, SW_ID, 0x63, 0x42, 0x01, 0x00};
#endif
const uint8_t play_req3[] = {0x00, SW_ID, 0x63, 0x42, 0x41};
const uint8_t stop_req[] = {0x00, SW_ID, 0x63, 0x43, 0x01};
const uint8_t stop_req2[] = {0x00, SW_ID, 0x63, 0x43, 0x41};
// answers
const AVCLAN_KnownMessage_t CMD_REGISTER = {
UNICAST, 5, {0x00, 0x01, SW_ID, 0x10, 0x63}};
const AVCLAN_KnownMessage_t CMD_STATUS1 = {
UNICAST, 4, {0x00, 0x01, 0x00, 0x1A}};
const AVCLAN_KnownMessage_t CMD_STATUS2 = {
UNICAST, 4, {0x00, 0x01, 0x00, 0x18}};
const AVCLAN_KnownMessage_t CMD_STATUS3 = {
UNICAST, 4, {0x00, 0x01, 0x00, 0x1D}};
const AVCLAN_KnownMessage_t CMD_STATUS4 = {
UNICAST, 5, {0x00, 0x01, 0x00, 0x1C, 0x00}};
AVCLAN_KnownMessage_t CMD_CHECK = {
UNICAST, 6, {0x00, 0x01, SW_ID, 0x30, 0x00, 0x00}};
uint8_t lancheck_resp[] = {0x00, 0x01, 0x00, 0xFF};
const uint8_t list_functions_resp[] = {0x00, dev_COMM_CTRL, dev_COMM_v1,
List_Functions_Resp, dev_CD_CHANGER};
uint8_t ping_resp[] = {0x00, dev_COMM_CTRL, dev_COMM_v1, Ping_Resp, 0xFF, 0x00};
uint8_t function_change_resp[] = {0x00, dev_CD_CHANGER, dev_COMM_v1, 0xFF,
0x01};
uint8_t cdstatus_resp[] = {
dev_CD_CHANGER, dev_STATUS, Report, 0x01, cd_SEEKING_TRACK, 0x01, 0x00,
0xFF, 0x7F, 0x00, 0xc0};
const AVCLAN_KnownMessage_t CMD_STATUS5 = {
UNICAST, 5, {0x00, 0x5C, 0x12, 0x53, 0x02}};
const AVCLAN_KnownMessage_t CMD_STATUS5A = {
BROADCAST, 5, {0x5C, 0x31, 0xF1, 0x00, 0x00}};
const AVCLAN_KnownMessage_t CMD_STATUS6 = {
UNICAST, 6, {0x00, 0x5C, 0x32, 0xF0, 0x02, 0x00}};
const AVCLAN_KnownMessage_t CMD_PLAY_OK1 = {
UNICAST, 5, {0x00, 0x63, SW_ID, 0x50, 0x01}};
const AVCLAN_KnownMessage_t CMD_PLAY_OK2 = {
UNICAST, 5, {0x00, 0x63, SW_ID, 0x52, 0x01}};
const AVCLAN_KnownMessage_t CMD_PLAY_OK3 = {
BROADCAST,
11,
{0x63, 0x31, 0xF1, 0x01, 0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x00, 0x80}};
AVCLAN_KnownMessage_t CMD_PLAY_OK4 = {
BROADCAST,
11,
{0x63, 0x31, 0xF1, 0x01, 0x28, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80}};
const AVCLAN_KnownMessage_t CMD_STOP1 = {
UNICAST, 5, {0x00, 0x63, SW_ID, 0x53, 0x01}};
AVCLAN_KnownMessage_t CMD_STOP2 = {
BROADCAST,
11,
{0x63, 0x31, 0xF1, 0x00, 0x30, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80}};
const AVCLAN_KnownMessage_t CMD_BEEP = {
UNICAST, 5, {0x00, 0x63, 0x29, 0x60, 0x02}};
uint8_t CheckCmd(const AVCLAN_frame_t *frame, const uint8_t *cmd, uint8_t l);
uint8_t AVCLAN_handleframe(const AVCLAN_frame_t *frame);
void AVCLAN_updateCDStatus();
void AVCLAN_init() {
// Pull-ups are disabled by default
@ -274,16 +217,17 @@ void AVCLAN_init() {
cd_status.disc = 1;
cd_status.cd2 = cd_status.cd3 = cd_status.cd4 = cd_status.cd5 =
cd_status.cd6 = 0;
cd_status.state = cd_LOADING;
cd_status.state = cd_SEEKING_TRACK;
cd_status.disk_random = 0;
cd_status.random = 0;
cd_status.disk_repeat = 0;
cd_status.repeat = 0;
cd_status.scan = 0;
cd_status.flags2 = 0xC0;
cd_status.track = 1;
cd_status.mins = 0;
cd_status.secs = 0;
cd_status.mins = 0xFF;
cd_status.secs = 0x7F;
cd_Track = &cd_status.track;
cd_Time_Min = &cd_status.mins;
@ -707,74 +651,8 @@ uint8_t AVCLAN_readframe() {
if (printAllFrames)
AVCLAN_printframe(&frame, printBinary);
if (!AVCLAN_ismuted()) {
if (shouldACK) {
if (CheckCmd(&frame, stat1, sizeof(stat1))) {
answerReq = cm_Status1;
return 1;
}
if (CheckCmd(&frame, stat2, sizeof(stat2))) {
answerReq = cm_Status2;
return 1;
}
if (CheckCmd(&frame, stat3, sizeof(stat3))) {
answerReq = cm_Status3;
return 1;
}
if (CheckCmd(&frame, stat4, sizeof(stat4))) {
answerReq = cm_Status4;
return 1;
}
// if (CheckCmd((uint8_t*)stat5)) {
// answerReq = cm_Status5;
// return 1;
// }
if (CheckCmd(&frame, play_req1, sizeof(play_req1))) {
answerReq = cm_PlayReq1;
return 1;
}
if (CheckCmd(&frame, play_req2, sizeof(play_req2))) {
answerReq = cm_PlayReq2;
return 1;
}
if (CheckCmd(&frame, play_req3, sizeof(play_req3))) {
answerReq = cm_PlayReq3;
return 1;
}
if (CheckCmd(&frame, stop_req, sizeof(stop_req))) {
answerReq = cm_StopReq;
return 1;
}
if (CheckCmd(&frame, stop_req2, sizeof(stop_req2))) {
answerReq = cm_StopReq2;
return 1;
}
} else { // broadcast check
if (CheckCmd(&frame, lan_playit, sizeof(lan_playit))) {
answerReq = cm_PlayIt;
return 1;
}
if (CheckCmd(&frame, lan_check, sizeof(lan_check))) {
answerReq = cm_Check;
CMD_CHECK.data[4] = frame.data[3];
return 1;
}
if (CheckCmd(&frame, lan_reg, sizeof(lan_reg))) {
answerReq = cm_Register;
return 1;
}
if (CheckCmd(&frame, lan_init, sizeof(lan_init))) {
answerReq = cm_Init;
return 1;
}
if (CheckCmd(&frame, lan_stat1, sizeof(lan_stat1))) {
answerReq = cm_Status1;
return 1;
}
}
}
if (!AVCLAN_ismuted())
AVCLAN_handleframe(&frame);
answerReq = cm_Null;
return 1;
@ -786,10 +664,9 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
STOPEvent;
// wait for free line
uint8_t line_busy = 1;
uint8_t parity = 0;
// wait for free line
TCB1.CNT = 0;
while (BUS_IS_IDLE) {
// Wait for 120% of a bit length
@ -876,114 +753,211 @@ uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame) {
return 0;
}
uint8_t AVCLAN_responseNeeded() { return (answerReq != 0); }
const AVCLAN_frame_t *frameQueue[4];
static inline uint8_t qFull() {
return ((qWrite - qRead) == sizeof(frameQueue));
}
static inline uint8_t qMask(uint8_t pos) {
return pos & (sizeof(frameQueue) - 1);
}
uint8_t qPush(const AVCLAN_frame_t *frame) {
if (qFull())
return 1;
frameQueue[qMask(qWrite++)] = frame;
return 0;
}
const AVCLAN_frame_t *qPeek() {
if (qEmpty())
return NULL;
return frameQueue[qMask(qRead)];
}
const AVCLAN_frame_t *qPop() {
if (qEmpty())
return NULL;
return frameQueue[qMask(qRead++)];
}
uint8_t AVCLAN_handleframe(const AVCLAN_frame_t *frame) {
uint8_t respond = 0;
AVCLAN_frame_t *resp = malloc(sizeof(AVCLAN_frame_t));
if (!resp)
return NULL;
resp->controller_addr = DEVICE_ADDR;
resp->control = 0xF;
if (!frame->broadcast) {
// peripheral_addr will be 0xFFF or 0x1FF based on all currently known
// examples
// if (frame->peripheral_addr == 0xFFF || frame->peripheral_addr == 0x1FF) {
if (frame->data[0] == 0) {
if (frame->data[1] == dev_COMM_CTRL) {
switch (frame->data[2]) {
case Lancheck_Scan_Req:
lancheck_resp[3] = Lancheck_Scan_Resp;
goto GROUPED;
case Lancheck_Req:
lancheck_resp[3] = Lancheck_Resp;
goto GROUPED;
case Lancheck_End_Req:
lancheck_resp[3] = Lancheck_End_Resp;
goto GROUPED;
default:
break;
GROUPED:
resp->broadcast = UNICAST;
resp->peripheral_addr = HU_ADDR;
resp->length = sizeof(lancheck_resp);
resp->data = (uint8_t *)lancheck_resp;
respond = 1;
}
}
} else if (frame->data[0] == dev_COMM_v1) {
if (frame->data[1] == dev_COMM_CTRL) {
switch (frame->data[2]) {
case Advertise_Function:
if (frame->data[3] == dev_CD_CHANGER)
CD_Mode = stPlay;
else
CD_Mode = stStop;
break;
case Ping_Req:
resp->broadcast = UNICAST;
resp->peripheral_addr = HU_ADDR;
resp->length = sizeof(ping_resp);
ping_resp[4] = frame->data[3];
resp->data = (uint8_t *)&ping_resp;
respond = 1;
break;
case List_Functions_Req:
resp->broadcast = UNICAST;
resp->peripheral_addr = HU_ADDR;
resp->length = sizeof(list_functions_resp);
resp->data = (uint8_t *)&list_functions_resp;
respond = 1;
break;
// case Restart_Lan:
// break;
default:
}
}
}
// }
} else if (frame->peripheral_addr == DEVICE_ADDR) { // unicast to CD changer
if (frame->data[0] == 0) {
switch (frame->data[1]) {
case dev_COMM_v1:
switch (frame->data[2]) {
case dev_CD_CHANGER:
switch (frame->data[3]) {
case Enable_Function_Req:
function_change_resp[3] = Enable_Function_Resp;
cd_status.state = cd_SEEKING;
cd_status.flags2 = 0x80;
*cd_Time_Min = 0x00;
*cd_Time_Sec = 0x00;
CD_Mode = stPlay;
answerReq = cm_CDStatus;
goto GROUPED2;
case Disable_Function_Req:
function_change_resp[3] = Disable_Function_Resp;
CD_Mode = stStop;
cd_status.state = 0;
*cd_Time_Min = 0x00;
*cd_Time_Sec = 0x00;
answerReq = cm_CDStatus;
goto GROUPED2;
// case 0x80:
// act = Inserted_CD;
// goto GROUPED;
default:
break;
GROUPED2:
resp->broadcast = UNICAST;
resp->peripheral_addr = HU_ADDR;
resp->length = sizeof(function_change_resp);
resp->data = (uint8_t *)function_change_resp;
respond = 1;
}
default:
}
break;
case dev_CMD_SW:
case dev_STATUS:
if (frame->data[2] == dev_CD_CHANGER) {
switch (frame->data[3]) {
case Request_Report:
cdstatus_resp[2] = Report;
goto GROUPED3;
case Request_Report2:
cdstatus_resp[2] = Report2;
goto GROUPED3;
case Request_Loader2:
cdstatus_resp[2] = Report_Loader2;
goto GROUPED3;
default:
break;
GROUPED3:
memcpy(&cdstatus_resp[3], &cd_status, sizeof(cd_status));
resp->broadcast = BROADCAST;
resp->peripheral_addr = 0x1FF;
resp->length = sizeof(function_change_resp);
resp->data = (uint8_t *)function_change_resp;
respond = 1;
}
}
break;
default:
}
}
}
if (!respond) {
free(resp);
} else {
qPush(resp);
}
return respond;
}
uint8_t AVCLAN_respond() {
uint8_t r = 0;
AVCLAN_frame_t frame = {.broadcast = UNICAST,
.controller_addr = CD_ID,
.peripheral_addr = HU_ID,
.control = 0xF,
.length = 0};
switch (answerReq) {
case cm_Status1:
frame.broadcast = CMD_STATUS1.broadcast;
frame.length = CMD_STATUS1.length;
frame.data = (uint8_t *)&CMD_STATUS1.data[0];
r = AVCLAN_sendframe(&frame);
break;
case cm_Status2:
frame.broadcast = CMD_STATUS2.broadcast;
frame.length = CMD_STATUS2.length;
frame.data = (uint8_t *)&CMD_STATUS2.data[0];
r = AVCLAN_sendframe(&frame);
break;
case cm_Status3:
frame.broadcast = CMD_STATUS3.broadcast;
frame.length = CMD_STATUS3.length;
frame.data = (uint8_t *)&CMD_STATUS3.data[0];
r = AVCLAN_sendframe(&frame);
break;
case cm_Status4:
frame.broadcast = CMD_STATUS4.broadcast;
frame.length = CMD_STATUS4.length;
frame.data = (uint8_t *)&CMD_STATUS4.data[0];
r = AVCLAN_sendframe(&frame);
break;
case cm_Register:
frame.broadcast = CMD_REGISTER.broadcast;
frame.length = CMD_REGISTER.length;
frame.data = (uint8_t *)&CMD_REGISTER.data[0];
r = AVCLAN_sendframe(&frame);
break;
// case cm_Init: // RS232_Print("INIT\n");
// r = AVCLan_SendInitCommands();
// break;
case cm_Check:
frame.broadcast = CMD_CHECK.broadcast;
frame.length = CMD_CHECK.length;
frame.data = CMD_CHECK.data;
r = AVCLAN_sendframe(&frame);
CMD_CHECK.data[6]++;
RS232_Print("AVCCHK\n");
break;
case cm_PlayReq1:
frame.broadcast = CMD_PLAY_OK1.broadcast;
frame.length = CMD_PLAY_OK1.length;
frame.data = (uint8_t *)&CMD_PLAY_OK1.data;
r = AVCLAN_sendframe(&frame);
break;
case cm_PlayReq2:
case cm_PlayReq3:
frame.broadcast = CMD_PLAY_OK2.broadcast;
frame.length = CMD_PLAY_OK2.length;
frame.data = (uint8_t *)&CMD_PLAY_OK2.data;
r = AVCLAN_sendframe(&frame);
if (!r) {
frame.broadcast = CMD_PLAY_OK3.broadcast;
frame.length = CMD_PLAY_OK3.length;
frame.data = (uint8_t *)&CMD_PLAY_OK3.data;
r = AVCLAN_sendframe(&frame);
if (!qEmpty()) {
const AVCLAN_frame_t *resp = qPeek();
for (uint8_t i = 0; i < MAX_SEND_ATTEMPTS; i++) {
r = AVCLAN_sendframe(resp);
if (!r) { // Send succeeded
resp = qPop();
free((AVCLAN_frame_t *)resp);
break;
}
CD_Mode = stPlay;
break;
case cm_PlayIt:
RS232_Print("PLAY\n");
frame.broadcast = CMD_PLAY_OK4.broadcast;
frame.length = CMD_PLAY_OK4.length;
frame.data = (uint8_t *)&CMD_PLAY_OK4.data;
CMD_PLAY_OK4.data[8] = *cd_Track;
CMD_PLAY_OK4.data[9] = *cd_Time_Min;
CMD_PLAY_OK4.data[10] = *cd_Time_Sec;
r = AVCLAN_sendframe(&frame);
CD_Mode = stPlay;
case cm_CDStatus:
if (!r)
AVCLan_Send_Status();
break;
case cm_StopReq:
case cm_StopReq2:
CD_Mode = stStop;
frame.broadcast = CMD_STOP1.broadcast;
frame.length = CMD_STOP1.length;
frame.data = (uint8_t *)&CMD_STOP1.data;
r = AVCLAN_sendframe(&frame);
}
if (r) { // Sending failed all attempts; give up sending frame
resp = qPop();
free((AVCLAN_frame_t *)resp);
}
} else if (!answerReq) {
AVCLAN_frame_t frame = {.broadcast = UNICAST,
.controller_addr = DEVICE_ADDR,
.peripheral_addr = HU_ADDR,
.control = 0xF,
.length = 0};
CMD_STOP2.data[8] = *cd_Track;
CMD_STOP2.data[9] = *cd_Time_Min;
CMD_STOP2.data[10] = *cd_Time_Sec;
frame.broadcast = CMD_STOP2.broadcast;
frame.length = CMD_STOP2.length;
frame.data = (uint8_t *)&CMD_STOP2.data;
r = AVCLAN_sendframe(&frame);
break;
case cm_Beep:
frame.broadcast = CMD_BEEP.broadcast;
frame.length = CMD_BEEP.length;
frame.data = (uint8_t *)&CMD_BEEP.data;
r = AVCLAN_sendframe(&frame);
break;
switch (answerReq) {
case cm_CDStatus:
AVCLAN_updateCDStatus();
}
}
answerReq = cm_Null;
@ -1070,45 +1044,27 @@ AVCLAN_frame_t *AVCLAN_parseframe(const uint8_t *bytes, uint8_t len) {
return frame;
}
uint8_t CheckCmd(const AVCLAN_frame_t *frame, const uint8_t *cmd, uint8_t l) {
for (uint8_t i = 0; i < l; i++) {
if (frame->data[i] != *cmd++)
return 0;
void AVCLAN_updateCDStatus() {
if (CD_Mode) {
if (cd_status.state != cd_PLAYBACK) {
cd_status.state = cd_PLAYBACK;
answerReq = cm_CDStatus;
}
if (answerReq == cm_CDStatus) {
cdstatus_resp[2] = Report;
memcpy(&cdstatus_resp[3], &cd_status, sizeof(cd_status));
AVCLAN_frame_t status = {.broadcast = BROADCAST,
.controller_addr = DEVICE_ADDR,
.peripheral_addr = 0x1FF,
.control = 0xF,
.length = sizeof(cdstatus_resp),
.data = (uint8_t *)&cdstatus_resp};
AVCLAN_sendframe(&status);
}
}
return 1;
}
void AVCLan_Send_Status() {
uint8_t STATUS[] = {0x63, 0x31, 0xF1, 0x01, 0x10, 0x01,
0x01, 0x00, 0x00, 0x00, 0x80};
STATUS[6] = *cd_Track;
STATUS[7] = *cd_Time_Min;
STATUS[8] = *cd_Time_Sec;
STATUS[9] = 0;
AVCLAN_frame_t status = {.broadcast = UNICAST,
.controller_addr = CD_ID,
.peripheral_addr = HU_ID,
.control = 0xF,
.length = 11,
.data = &STATUS[0]};
AVCLAN_sendframe(&status);
}
void AVCLan_Register() {
AVCLAN_frame_t register_frame = {.broadcast = CMD_REGISTER.broadcast,
.controller_addr = CD_ID,
.peripheral_addr = HU_ID,
.control = 0xF,
.length = CMD_REGISTER.length,
.data = (uint8_t *)CMD_REGISTER.data};
RS232_Print("REG_ST\n");
AVCLAN_sendframe(&register_frame);
RS232_Print("REG_END\n");
// AVCLan_Command( cm_Register );
answerReq = cm_Init;
AVCLAN_respond();
}
#ifdef SOFTWARE_DEBUG

View File

@ -49,29 +49,85 @@ extern uint8_t printBinary;
typedef enum {
cm_Null = 0,
cm_Status1 = 1,
cm_Status2 = 2,
cm_Status3 = 3,
cm_Status4 = 4,
cm_PlayReq1 = 5,
cm_PlayReq2 = 6,
cm_PlayReq3 = 7,
cm_StopReq = 8,
cm_StopReq2 = 9,
cm_Register = 100,
cm_Init = 101,
cm_Check = 102,
cm_PlayIt = 103,
cm_Beep = 110,
cm_NextTrack = 120,
cm_PrevTrack = 121,
cm_NextDisc = 122,
cm_PrevDisc = 123,
cm_ScanModeOn = 130,
cm_ScanModeOff = 131,
cm_CDStatus,
} commands;
typedef enum {
dev_COMM_CTRL = 0x01,
dev_COMM_v1 = 0x11,
dev_COMM_v2 = 0x12,
dev_SW = 0x21,
dev_SW_NAME = 0x23,
dev_SW_CONVERTING = 0x24,
dev_CMD_SW = 0x25,
dev_STATUS = 0x31,
dev_BEEP_HU = 0x28,
dev_BEEP_SPEAKERS = 0x29,
dev_TUNER = 0x60,
dev_TAPE_DECK = 0x61,
dev_CD = 0x62,
dev_CD_CHANGER = 0x63,
dev_AUDIO_AMP = 0x74,
} devices;
typedef enum {
// LAN related
List_Functions_Req = 0x00,
List_Functions_Resp = 0x10,
Restart_Lan = 0x01,
Lancheck_End_Req = 0x08,
Lancheck_End_Resp = 0x18,
Lancheck_Scan_Req = 0x0a,
Lancheck_Scan_Resp = 0x1a,
Lancheck_Req = 0x0c,
Lancheck_Resp = 0x1c,
Ping_Req = 0x20,
Ping_Resp = 0x30,
// Device switching
Enable_Function_Req = 0x42,
Enable_Function_Resp = 0x52,
Disable_Function_Req = 0x43,
Disable_Function_Resp = 0x53,
Advertise_Function = 0x45,
General_Query = 0x46,
// Physical interface
Eject = 0x80,
Disc_Up = 0x90,
Disc_Down = 0x91,
Pwrvol_Knob_Righthand_Turn = 0x9c,
Pwrvol_Knob_Lefthand_Turn = 0x9d,
Track_Seek_Up = 0x94,
Track_Seek_Down = 0x95,
CD_Enable_Scan = 0xa6,
CD_Disable_Scan = 0xa7,
CD_Enable_Repeat = 0xa0,
CD_Disable_Repeat = 0xa1,
CD_Enable_Random = 0xb0,
CD_Disable_Random = 0xb1,
// CD functions
// Events
Inserted_CD = 0x50,
Removed_CD = 0x51,
// Requests
Request_Report = 0xe0,
Request_Report2 = 0xe2,
Request_Loader2 = 0xe4,
Request_Track_Name = 0xed,
// Reports
Report = 0xf1,
Report2 = 0xf2,
Report_Loader = 0xf3,
Report_Loader2 = 0xf4,
Report_TOC = 0xf9,
Report_Track_Name = 0xfd,
} actions;
typedef enum {
cd_OPEN = 0x01,
cd_ERR1 = 0x02,
@ -89,7 +145,7 @@ typedef struct AVCLAN_CD_Status {
_Bool cd5 : 1;
_Bool cd6 : 1;
int : 2;
cd_state state;
uint8_t state;
uint8_t disc;
uint8_t track;
uint8_t mins;
@ -101,7 +157,7 @@ typedef struct AVCLAN_CD_Status {
_Bool repeat : 1;
_Bool disk_scan : 1;
_Bool scan : 1;
int : 2;
int : 1;
uint8_t flags2;
} AVCLAN_CD_Status_t;
@ -109,12 +165,6 @@ typedef enum { stStop = 0, stPlay = 1 } cd_modes;
typedef enum MSG_TYPE { BROADCAST = 0, UNICAST = 1 } MSG_TYPE_t;
typedef struct AVCLAN_KnownMessage_struct {
MSG_TYPE_t broadcast;
uint8_t length;
uint8_t data[11];
} AVCLAN_KnownMessage_t;
typedef struct AVCLAN_frame_struct {
MSG_TYPE_t broadcast; // 0 for broadcast messages
uint16_t controller_addr; // formerly "master"
@ -130,7 +180,21 @@ void AVCLAN_muteDevice(uint8_t mute);
uint8_t AVCLAN_readframe();
uint8_t AVCLAN_sendframe(const AVCLAN_frame_t *frame);
uint8_t AVCLAN_responseNeeded();
// To allow inlining qEmpty and AVCLAN_responseNeeded
#ifndef VAR_DECLS
#define _DECL extern
#define _INIT(x)
#else
#define _DECL
#define _INIT(x) = x
#endif
_DECL uint8_t answerReq _INIT(0);
_DECL uint8_t qWrite _INIT(0);
_DECL uint8_t qRead _INIT(0);
inline uint8_t qEmpty() { return (qWrite == qRead); }
inline uint8_t AVCLAN_responseNeeded() { return (answerReq != 0) || !qEmpty(); }
uint8_t AVCLAN_respond();
void AVCLAN_printframe(const AVCLAN_frame_t *frame, uint8_t binary);

View File

@ -62,10 +62,8 @@ int main() {
if (!BUS_IS_IDLE) {
AVCLAN_readframe();
} else {
// check command from HU
if (AVCLAN_responseNeeded())
AVCLAN_respond();
} else if (AVCLAN_responseNeeded()) {
AVCLAN_respond();
}
// Key handler