Shift Device/Action enums to avclan.h

This commit is contained in:
Allen Hill
2026-07-06 15:50:09 -07:00
parent 25e425a601
commit 554fca0582
9 changed files with 261 additions and 210 deletions
+3 -1
View File
@@ -3,7 +3,9 @@ cmake_minimum_required(VERSION 3.24)
project(avclan-mockingboard VERSION 1.1 LANGUAGES C CXX)
set(CMAKE_C_STANDARD 23)
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_CXX_STANDARD 23)
set(CMAKE_C_STANDARD_REQUIRED ON)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
add_compile_options(
+97 -3
View File
@@ -7,12 +7,105 @@
#ifdef __cplusplus
#define AVCLAN_ENUM_CLASS class
namespace avclan::detail {
struct Error {
#include <type_traits>
#include <utility>
namespace avclan {
#if defined(__cpp_lib_to_underlying) && __cpp_lib_to_underlying >= 202102L
using std::to_underlying;
#else
template <class Enum>
requires std::is_enum_v<Enum>
constexpr std::underlying_type_t<Enum> to_underlying(Enum e) noexcept {
return static_cast<std::underlying_type_t<Enum>>(e);
}
#endif
#else
#define AVCLAN_ENUM_CLASS
#endif
enum AVCLAN_ENUM_CLASS Action : uint8_t {
// LAN related
List_Functions_Req = 0x00,
List_Functions_Resp = 0x10,
Restart_Lan = 0x01,
// Lan_Startup_Complete = 0x58,
Lancheck_End_Req = 0x08,
Lancheck_End_Resp = 0x18,
Lancheck_Scan_Req = 0x0a,
Lancheck_Scan_Resp = 0x1a,
Lancheck_Req = 0x0c,
Lancheck_Resp = 0x1c,
// Lancheck_UNK_Req = 0x0d,
// Lancheck_UNK_Resp = 0x1d,
Ping_Req = 0x20,
Ping_Resp = 0x30,
// Device switching
Enable_Function_Req = 0x42,
Enable_Function_Resp = 0x52,
Disable_Function_Req = 0x43,
Disable_Function_Resp = 0x53,
Current_Function = 0x45,
General_Query = 0x46,
// Events
Insertion = 0x50,
Ejection = 0x51,
// Physical interface
Backlight_Adjust = 0x59,
Beep = 0x60,
Eject = 0x80,
Disc_Up = 0x90,
Disc_Down = 0x91,
Track_Seek_Up = 0x94,
Track_Seek_Down = 0x95,
Track_Fast_Forward = 0x98,
Track_Rewind = 0x99,
Pwrvol_Knob_Righthand_Turn = 0x9c,
Pwrvol_Knob_Lefthand_Turn = 0x9d,
CD_Enable_Repeat = 0xa0,
CD_Disable_Repeat = 0xa1,
CD_Enable_Disk_Repeat = 0xa3,
CD_Disable_Disk_Repeat = 0xa4,
CD_Enable_Scan = 0xa6,
CD_Disable_Scan = 0xa7,
CD_Enable_Disk_Scan = 0xa9,
CD_Disable_Disk_Scan = 0xaa,
CD_Enable_Random = 0xb0,
CD_Disable_Random = 0xb1,
CD_Enable_Disk_Random = 0xb3,
CD_Disable_Disk_Random = 0xb4,
// Requests and Response pairs
Initial_Report_Request = 0xe0,
Initial_Report_Response = 0xf0,
Playback_Request = 0xe2,
Playback_Report = 0xf2,
Loading_Request2 = 0xe4,
Loading_Response2 = 0xf4,
Request_Track_Name = 0xed,
Report_Track_Name = 0xfd,
// Reports
Status_Report = 0xf1, // Typically unprompted, sent to Device::STATUS
Loading_Status_Report = 0xf3, // Typically unprompted, sent to Device::STATUS
Report_TOC = 0xf9,
};
#ifdef __cplusplus
namespace detail {
struct Error {
#endif
// Error enums are ordered such that a lower numeric value corresponds to
// more progress/success before an error occured, with 0 being no errors
enum AVCLAN_ENUM_CLASS Read : uint8_t {
@@ -49,7 +142,8 @@ enum AVCLAN_ENUM_CLASS Bit : uint8_t {
};
#ifdef __cplusplus
} // namespace avclan::detail
} // namespace detail
} // namespace avclan
#endif
#undef AVCLAN_ENUM_CLASS
-105
View File
@@ -1,105 +0,0 @@
// copyright (C) 2006 Marcin Slonicki <marcin@softservice.com.pl>
// copyright (C) 2007 Louis Frigon
// Copyright (C) 2015 Allen Hill <allenofthehills@gmail.com>
// SPDX-License-Identifier: GPL-3.0-or-later
// Shared cross-cutting AVC-LAN definitions used by two or more layers
// (phy / frame / protocol / cdchanger). This is a leaf header: it must not
// include any other project header.
#pragma once
#include <stdint.h>
typedef enum : uint8_t {
dev_LAN = 0x00,
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 : uint8_t {
// LAN related
List_Functions_Req = 0x00,
List_Functions_Resp = 0x10,
Restart_Lan = 0x01,
// Lan_Startup_Complete = 0x58,
Lancheck_End_Req = 0x08,
Lancheck_End_Resp = 0x18,
Lancheck_Scan_Req = 0x0a,
Lancheck_Scan_Resp = 0x1a,
Lancheck_Req = 0x0c,
Lancheck_Resp = 0x1c,
// Lancheck_UNK_Req = 0x0d,
// Lancheck_UNK_Resp = 0x1d,
Ping_Req = 0x20,
Ping_Resp = 0x30,
// Device switching
Enable_Function_Req = 0x42,
Enable_Function_Resp = 0x52,
Disable_Function_Req = 0x43,
Disable_Function_Resp = 0x53,
Current_Function = 0x45,
General_Query = 0x46,
// Events
Insertion = 0x50,
Ejection = 0x51,
// Physical interface
Backlight_Adjust = 0x59,
Beep = 0x60,
Eject = 0x80,
Disc_Up = 0x90,
Disc_Down = 0x91,
Track_Seek_Up = 0x94,
Track_Seek_Down = 0x95,
Track_Fast_Forward = 0x98,
Track_Rewind = 0x99,
Pwrvol_Knob_Righthand_Turn = 0x9c,
Pwrvol_Knob_Lefthand_Turn = 0x9d,
CD_Enable_Repeat = 0xa0,
CD_Disable_Repeat = 0xa1,
CD_Enable_Disk_Repeat = 0xa3,
CD_Disable_Disk_Repeat = 0xa4,
CD_Enable_Scan = 0xa6,
CD_Disable_Scan = 0xa7,
CD_Enable_Disk_Scan = 0xa9,
CD_Disable_Disk_Scan = 0xaa,
CD_Enable_Random = 0xb0,
CD_Disable_Random = 0xb1,
CD_Enable_Disk_Random = 0xb3,
CD_Disable_Disk_Random = 0xb4,
// Requests and Response pairs
Initial_Report_Request = 0xe0,
Initial_Report_Response = 0xf0,
Playback_Request = 0xe2,
Playback_Report = 0xf2,
Loading_Request2 = 0xe4,
Loading_Response2 = 0xf4,
Request_Track_Name = 0xed,
Report_Track_Name = 0xfd,
// Reports
Status_Report = 0xf1, // Typically unprompted, sent to dev_STATUS
Loading_Status_Report = 0xf3, // Typically unprompted, sent to dev_STATUS
Report_TOC = 0xf9,
} actions;
+73 -53
View File
@@ -6,24 +6,27 @@
#include <cstdint>
#include <cstring>
#include "avclan_defs.h"
#include "avclan.h"
#include "cdchanger.hpp"
#include "device.hpp"
#include "frame.hpp"
#include "mediacontrol.h"
#include "statustimer.h"
namespace {
using namespace avclan;
constexpr uint8_t cdloading_resp[] = {dev_CD_CHANGER,
dev_STATUS,
Loading_Status_Report,
0x00,
0x01,
0x00,
0x01,
0x00,
0x01,
0x02};
constexpr uint8_t cdloading_resp[] = {
to_underlying(Device::CD_CHANGER),
to_underlying(Device::STATUS),
to_underlying(Action::Loading_Status_Report),
0x00,
0x01,
0x00,
0x01,
0x00,
0x01,
0x02};
constexpr int WIRE_SIZE = 8; // cd state report size in bytes
constexpr int TIME_SKIP = 15; // seconds
@@ -56,20 +59,23 @@ void CDChanger::init() {
void CDChanger::handle(const Frame *in, Frame *out) {
const uint8_t *data = &in->data[1];
const auto from = static_cast<devices>(*data++);
const auto from = static_cast<Device>(*data++);
/* const auto to = */ data++;
const auto action = *data++;
const auto action = static_cast<Action>(*data++);
static const uint8_t function_change_resp[] = {0x00, dev_CD_CHANGER, from,
0xFF, 0x01};
static const uint8_t function_change_resp[] = {
0x00, to_underlying(Device::CD_CHANGER), to_underlying(from), 0xFF, 0x01};
using enum Action;
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wswitch-enum"
// Unicast to CD changer: bytes are (0x00, from, to, action, [extra...]).
switch (action) {
case Enable_Function_Req:
out->is_unicast = true;
out->length = sizeof(function_change_resp);
memcpy(out->data, function_change_resp, sizeof(function_change_resp));
out->data[3] = Enable_Function_Resp;
out->data[3] = to_underlying(Enable_Function_Resp);
state = 0;
flags2 = 0x80;
out->reaction = r_StatusReport;
@@ -80,7 +86,7 @@ void CDChanger::handle(const Frame *in, Frame *out) {
stopPlaying();
out->length = sizeof(function_change_resp);
memcpy(out->data, function_change_resp, sizeof(function_change_resp));
out->data[3] = Disable_Function_Resp;
out->data[3] = to_underlying(Disable_Function_Resp);
state = 0;
flags2 = 0x80;
out->is_unicast = true;
@@ -90,8 +96,9 @@ void CDChanger::handle(const Frame *in, Frame *out) {
case Eject: {
// "Eject" label is multiply wrong; proper meaning unclear:
// - First observed on initial multiple presses of "CD" button,
// triggering (after {0x00, dev_CD_CHANGER, dev_COMM_v1, Insertion,
// 0x01} response) proper activation of mockingboard/cd-changer.
// triggering (after {0x00, Device::CD_CHANGER, Device::COMM_v1,
// Insertion, 0x01} response) proper activation of
// mockingboard/cd-changer.
// - Subsequently observed when pressing (technically
// releasing?) the fast-forward button and rewind
if (static_cast<bool>(state & SEEKING)) { // FF/RW button released
@@ -99,8 +106,9 @@ void CDChanger::handle(const Frame *in, Frame *out) {
} else {
out->is_unicast = true;
{
const uint8_t msg[] = {0x00, dev_CD_CHANGER, dev_CMD_SW, Insertion,
0x01};
const uint8_t msg[] = {0x00, to_underlying(Device::CD_CHANGER),
to_underlying(Device::CMD_SW),
to_underlying(Insertion), 0x01};
out->length = sizeof(msg);
memcpy(out->data, msg, sizeof(msg));
}
@@ -112,8 +120,15 @@ void CDChanger::handle(const Frame *in, Frame *out) {
out->is_unicast = true;
// No knowledge/understanding of field meaning/interpretation
const uint8_t cdinitreport_resp[] = {
0x00, dev_CD_CHANGER, from, Initial_Report_Response, 0x01, 0x31,
0x10, 0x01, 0x01};
0x00,
to_underlying(Device::CD_CHANGER),
to_underlying(from),
to_underlying(Initial_Report_Response),
0x01,
0x31,
0x10,
0x01,
0x01};
out->length = sizeof(cdinitreport_resp);
memcpy(out->data, cdinitreport_resp, sizeof(cdinitreport_resp));
out->reaction = r_SendOnly;
@@ -121,9 +136,9 @@ void CDChanger::handle(const Frame *in, Frame *out) {
}
case Playback_Request:
out->data[0] = 0x00;
out->data[1] = dev_CD_CHANGER;
out->data[2] = from;
out->data[3] = Playback_Report;
out->data[1] = to_underlying(Device::CD_CHANGER);
out->data[2] = to_underlying(from);
out->data[3] = to_underlying(Playback_Report);
out->length = WIRE_SIZE + 4;
serialize(&out->data[4]);
out->is_unicast = true;
@@ -133,8 +148,8 @@ void CDChanger::handle(const Frame *in, Frame *out) {
out->data[0] = 0x00;
out->length = sizeof(cdloading_resp) + 1;
memcpy(&out->data[1], cdloading_resp, sizeof(cdloading_resp));
out->data[2] = from;
out->data[3] = Loading_Response2;
out->data[2] = to_underlying(from);
out->data[3] = to_underlying(Loading_Response2);
out->is_unicast = true;
out->reaction = r_SendOnly;
break;
@@ -147,7 +162,7 @@ void CDChanger::handle(const Frame *in, Frame *out) {
mins = 0xff;
secs = 0x7f;
flags2 = 0xc0;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
AVCLAN_mediaFunction(MEDIA_SKIP_FORWARD);
out->reaction = r_TrackChange;
break;
@@ -163,7 +178,7 @@ void CDChanger::handle(const Frame *in, Frame *out) {
mins = 0xff;
secs = 0x7f;
flags2 = 0xc0;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
AVCLAN_mediaFunction(MEDIA_SKIP_BACKWARD);
out->reaction = r_TrackChange;
break;
@@ -174,7 +189,7 @@ void CDChanger::handle(const Frame *in, Frame *out) {
secs -= 60;
++mins;
}
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
AVCLAN_mediaFunction(MEDIA_SKIP_FORWARD);
statustimer_reset(); // Skipped to a whole/round sec; ensure next tick
// is ~1 sec from now
@@ -194,7 +209,7 @@ void CDChanger::handle(const Frame *in, Frame *out) {
}
} else
secs -= TIME_SKIP;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
AVCLAN_mediaFunction(MEDIA_SKIP_BACKWARD);
statustimer_reset(); // Skipped to a whole/round sec; ensure next tick
// is ~1 sec from now
@@ -203,46 +218,47 @@ void CDChanger::handle(const Frame *in, Frame *out) {
}
case CD_Enable_Random:
flags |= RANDOM;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Disable_Random:
flags &= ~RANDOM;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Enable_Repeat:
flags |= REPEAT;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Disable_Repeat:
flags &= ~REPEAT;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Enable_Disk_Random:
flags |= DISK_RANDOM;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Disable_Disk_Random:
flags &= ~DISK_RANDOM;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Enable_Disk_Repeat:
flags |= DISK_REPEAT;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
case CD_Disable_Disk_Repeat:
flags &= ~DISK_REPEAT;
generateStatus(out, true, dev_CMD_SW);
generateStatus(out, true, Device::CMD_SW);
out->reaction = r_StatusReport;
break;
default: break;
}
#pragma GCC diagnostic pop
}
void CDChanger::react(Frame *out, detail::Error::Send err) {
@@ -258,8 +274,12 @@ void CDChanger::react(Frame *out, detail::Error::Send err) {
}
break;
case r_Ejection: {
const uint8_t play[] = {0x00, dev_COMM_CTRL, dev_COMM_v1,
Insertion, dev_CD_CHANGER, 0x01};
const uint8_t play[] = {0x00,
to_underlying(Device::COMM_CTRL),
to_underlying(Device::COMM_v1),
to_underlying(Action::Insertion),
to_underlying(Device::CD_CHANGER),
0x01};
out->length = sizeof(play);
memcpy(out->data, play, sizeof(play));
}
@@ -270,8 +290,8 @@ void CDChanger::react(Frame *out, detail::Error::Send err) {
out->peripheral_addr = 0x1FF;
out->length = sizeof(cdloading_resp) + 1;
memcpy(out->data, cdloading_resp, sizeof(cdloading_resp));
out->data[1] = dev_STATUS;
out->data[2] = Loading_Status_Report;
out->data[1] = to_underlying(Device::STATUS);
out->data[2] = to_underlying(Action::Loading_Status_Report);
out->reaction = r_SendOnly;
break;
case r_TrackChange:
@@ -281,12 +301,12 @@ void CDChanger::react(Frame *out, detail::Error::Send err) {
[[fallthrough]];
case r_NormalizeState:
normalizeState();
generateStatus(out, true, dev_STATUS);
generateStatus(out, true, Device::STATUS);
out->reaction = r_SendOnly;
break;
case r_StartPlaying:
normalizeState();
generateStatus(out, true, dev_STATUS);
generateStatus(out, true, Device::STATUS);
out->reaction = r_BeganPlaying;
break;
case r_BeganPlaying:
@@ -294,7 +314,7 @@ void CDChanger::react(Frame *out, detail::Error::Send err) {
out->reaction = r_Nothing;
break;
case r_StatusReport:
generateStatus(out, true, dev_STATUS);
generateStatus(out, true, Device::STATUS);
out->reaction = r_SendOnly;
break;
case r_SendOnly: [[fallthrough]];
@@ -311,7 +331,7 @@ void CDChanger::enable(Frame *out) {
secs = 0;
state = SEEKING | SEEKING_TRACK;
flags2 = 0xc0;
generateStatus(out, true, dev_STATUS);
generateStatus(out, true, Device::STATUS);
out->reaction = r_StartPlaying;
}
}
@@ -321,7 +341,7 @@ void CDChanger::resolvepending() { statustimer_clearTick(); }
void CDChanger::emit(Frame *out, uint16_t peripheral) {
out->peripheral_addr = peripheral;
generateStatus(out, true, dev_STATUS);
generateStatus(out, true, Device::STATUS);
out->reaction = r_StateReport;
}
@@ -379,7 +399,7 @@ void CDChanger::incrementTime() {
// Used for changed status messages
void CDChanger::generateStatus(Frame *status, bool is_unicast,
devices to) const {
Device to) const {
status->is_unicast = is_unicast;
if (!is_unicast)
status->peripheral_addr = 0x1FF;
@@ -389,9 +409,9 @@ void CDChanger::generateStatus(Frame *status, bool is_unicast,
uint8_t *data = status->data;
if (is_unicast)
*data++ = 0x00;
*data++ = dev_CD_CHANGER;
*data++ = to;
*data++ = Status_Report;
*data++ = to_underlying(Device::CD_CHANGER);
*data++ = to_underlying(to);
*data++ = to_underlying(Action::Status_Report);
serialize(data);
}
+3 -3
View File
@@ -8,7 +8,7 @@
#include <cstdint>
#include "avclan.h"
#include "avclan_defs.h"
#include "device.hpp"
#include "frame.hpp"
namespace avclan {
@@ -57,7 +57,7 @@ public:
r_StateReport, // *IS* a status report (follow-up or unprompted)
};
static constexpr uint8_t id = dev_CD_CHANGER;
static constexpr Device id = Device::CD_CHANGER;
void init();
void handle(const Frame *in, Frame *out);
@@ -75,7 +75,7 @@ private:
void stopPlaying();
void serialize(uint8_t *dst) const;
void setTime(uint8_t mins, uint8_t secs);
void generateStatus(Frame *status, bool is_unicast, devices to) const;
void generateStatus(Frame *status, bool is_unicast, Device to) const;
void normalizeState();
bool playing = false;
+35 -14
View File
@@ -3,23 +3,44 @@
#pragma once
#include "avclan.h"
#include "frame.hpp"
#include <concepts>
#include <cstdint>
#include "avclan.h"
#include "frame.hpp"
namespace avclan {
enum class Device : uint8_t {
LAN = 0x00,
COMM_CTRL = 0x01,
COMM_v1 = 0x11,
COMM_v2 = 0x12,
SW = 0x21,
SW_NAME = 0x23,
SW_CONVERTING = 0x24,
CMD_SW = 0x25,
STATUS = 0x31,
BEEP_HU = 0x28,
BEEP_SPEAKERS = 0x29,
TUNER = 0x60,
TAPE_DECK = 0x61,
CD = 0x62,
CD_CHANGER = 0x63,
AUDIO_AMP = 0x74,
};
template <class T>
concept Device = requires { std::integral_constant<uint8_t, T::id>{}; } &&
requires(T dev, const Frame *in, Frame *out,
detail::Error::Send err, uint16_t peripheral) {
dev.init();
dev.handle(in, out);
dev.enable(out);
dev.react(out, err);
{ dev.pending() } -> std::convertible_to<bool>;
dev.resolvepending();
dev.emit(out, peripheral);
};
concept DeviceInterface =
requires { std::integral_constant<Device, T::id>{}; } &&
requires(T dev, const Frame *in, Frame *out, detail::Error::Send err,
uint16_t peripheral) {
dev.init();
dev.handle(in, out);
dev.enable(out);
dev.react(out, err);
{ dev.pending() } -> std::convertible_to<bool>;
dev.resolvepending();
dev.emit(out, peripheral);
};
} // namespace avclan
+3 -1
View File
@@ -8,6 +8,8 @@
#include <cstdint>
namespace avclan {
enum class Device : uint8_t;
struct Frame {
struct Print {
bool print : 1 = false; // print at all
@@ -27,7 +29,7 @@ struct Frame {
void print(Print print) const;
uint8_t reaction;
uint8_t owning_device;
Device owning_device;
bool is_unicast;
uint16_t controller_addr; // formerly "master"
uint16_t peripheral_addr; // formerly "slave"
+35 -25
View File
@@ -4,7 +4,7 @@
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include "avclan_defs.h"
#include "avclan.h"
#include "bus.hpp"
#include "device.hpp"
#include "frame.hpp"
@@ -14,7 +14,7 @@
#include <tuple>
namespace avclan {
template <Device... Devs> class Peripheral {
template <DeviceInterface... Devs> class Peripheral {
public:
using Error = detail::Error;
@@ -38,6 +38,8 @@ public:
#define PACK3(a, b, c) (((uint32_t)(a) << 16) | ((uint32_t)(b) << 8) | (c))
void route(const Frame *in, Frame *out) {
using enum Device;
using enum Action;
out->reaction = 0;
if (AVCLAN_ismuted() || in->length < 3)
@@ -45,8 +47,8 @@ public:
// 0xFF placeholders are variant bytes filled by writing directly to
// out->data[N] after memcpy.
static const uint8_t lancheck_resp[] = {0x00, dev_COMM_CTRL, dev_LAN, 0xFF,
0xFF};
static const uint8_t lancheck_resp[] = {0x00, to_underlying(COMM_CTRL),
to_underlying(LAN), 0xFF, 0xFF};
out->peripheral_addr = controller_;
@@ -62,51 +64,58 @@ public:
// Broadcast: bytes are (from, to, action, [extra...]).
// peripheral_addr unchecked — always 0xFFF or 0x1FF in known traffic.
switch (PACK3(b0, b1, b2)) {
case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_Scan_Req):
case PACK3(LAN, COMM_CTRL, to_underlying(Lancheck_Scan_Req)):
out->length = sizeof(lancheck_resp);
out->is_unicast = true;
memcpy(out->data, lancheck_resp, sizeof(lancheck_resp));
out->data[3] = Lancheck_Scan_Resp;
out->data[3] = to_underlying(Lancheck_Scan_Resp);
out->data[4] = 0x01;
out->reaction = 1;
break;
case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_Req):
case PACK3(LAN, COMM_CTRL, to_underlying(Lancheck_Req)):
out->length = sizeof(lancheck_resp);
out->is_unicast = true;
memcpy(out->data, lancheck_resp, sizeof(lancheck_resp));
out->data[3] = Lancheck_Resp;
out->data[3] = to_underlying(Lancheck_Resp);
out->data[4] = 0x00;
out->reaction = 1;
break;
case PACK3(dev_LAN, dev_COMM_CTRL, Lancheck_End_Req):
case PACK3(LAN, COMM_CTRL, to_underlying(Lancheck_End_Req)):
out->is_unicast = true;
out->length = sizeof(lancheck_resp) - 1;
memcpy(out->data, lancheck_resp, out->length);
out->data[3] = Lancheck_End_Resp;
out->data[3] = to_underlying(Lancheck_End_Resp);
out->reaction = 1;
break;
case PACK3(dev_COMM_v1, dev_COMM_CTRL, Current_Function):
case PACK3(dev_COMM_v2, dev_COMM_CTRL, Current_Function):
((Devs::id == b3 ? std::get<Devs>(devices_).enable(out), 0 : 0), ...);
case PACK3(COMM_v1, COMM_CTRL, to_underlying(Current_Function)):
case PACK3(COMM_v2, COMM_CTRL, to_underlying(Current_Function)):
((Devs::id == static_cast<Device>(b3)
? std::get<Devs>(devices_).enable(out),
0 : 0),
...);
break;
case PACK3(dev_COMM_v1, dev_COMM_CTRL, Ping_Req):
case PACK3(dev_COMM_v2, dev_COMM_CTRL, Ping_Req): {
case PACK3(COMM_v1, COMM_CTRL, to_underlying(Ping_Req)):
case PACK3(COMM_v2, COMM_CTRL, to_underlying(Ping_Req)): {
out->is_unicast = true;
const uint8_t ping_resp[] = {0x00, dev_COMM_CTRL, dev_COMM_v1,
Ping_Resp, 0xFF, b3};
const uint8_t ping_resp[] = {0x00,
to_underlying(COMM_CTRL),
to_underlying(COMM_v1),
to_underlying(Ping_Resp),
0xFF,
b3};
out->length = sizeof(ping_resp);
memcpy(out->data, ping_resp, sizeof(ping_resp));
out->reaction = 1;
break;
}
case PACK3(dev_COMM_v1, dev_COMM_CTRL, List_Functions_Req):
case PACK3(dev_COMM_v2, dev_COMM_CTRL, List_Functions_Req): {
case PACK3(COMM_v1, COMM_CTRL, to_underlying(List_Functions_Req)):
case PACK3(COMM_v2, COMM_CTRL, to_underlying(List_Functions_Req)): {
controller_ = in->controller_addr;
out->peripheral_addr = controller_;
out->is_unicast = true;
const uint8_t list_functions_resp[] = {
0x00, dev_COMM_CTRL, dev_COMM_v1, List_Functions_Resp,
dev_CD_CHANGER};
0x00, to_underlying(COMM_CTRL), to_underlying(COMM_v1),
to_underlying(List_Functions_Resp), to_underlying(CD_CHANGER)};
out->length = sizeof(list_functions_resp);
memcpy(out->data, list_functions_resp, sizeof(list_functions_resp));
out->reaction = 1;
@@ -115,8 +124,9 @@ public:
// case Restart_Lan: not handled
}
} else if (in->peripheral_addr == address_ && b0 == 0x00) {
((Devs::id == b2 ? device_preroute(std::get<Devs>(devices_), in, out),
0 : 0),
((Devs::id == static_cast<Device>(b2)
? device_preroute(std::get<Devs>(devices_), in, out),
0 : 0),
...);
}
}
@@ -143,11 +153,11 @@ private:
out->control = 0xF;
}
template <Device Dev, class F> void poller(Dev &dev, F &&fun) {
template <DeviceInterface Dev, class F> void poller(Dev &dev, F &&fun) {
if (dev.pending() && fun(dev))
dev.resolvepending();
}
template <Device Dev>
template <DeviceInterface Dev>
void device_preroute(Dev &dev, const Frame *in, Frame *out) {
out->owning_device = Dev::id;
dev.handle(in, out);
+12 -5
View File
@@ -66,6 +66,8 @@ int main() {
uint8_t seqIdx = 0; // current index in data_tmp
Bus phy;
using enum Action;
using enum Device;
Peripheral<CDChanger> peripheral(phy, 0x360);
using Error = decltype(peripheral)::Error;
using Print = Frame::Print;
@@ -139,22 +141,27 @@ int main() {
out->is_unicast = true;
out->peripheral_addr = peripheral.controller();
{
const uint8_t beep[] = {0x00, dev_CD_CHANGER, dev_BEEP_SPEAKERS,
0x60, 0x01};
const uint8_t beep[] = {0x00, to_underlying(CD_CHANGER),
to_underlying(BEEP_SPEAKERS), 0x60, 0x01};
out->length = sizeof(beep);
memcpy(out->data, beep, sizeof(beep));
}
out->reaction = 1;
outgoing.push(std::move(out));
}
} else
RS232_Print("!! Cache empty; unable to queue beep request");
break;
case 'P':
if (auto out = cache.pop()) {
out->is_unicast = true;
out->peripheral_addr = peripheral.controller();
{
const uint8_t play[] = {0x00, dev_COMM_CTRL, dev_COMM_v1,
Ejection, dev_CD_CHANGER, 0x01};
const uint8_t play[] = {0x00,
to_underlying(COMM_CTRL),
to_underlying(COMM_v1),
to_underlying(Ejection),
to_underlying(CD_CHANGER),
0x01};
out->length = sizeof(play);
memcpy(out->data, play, sizeof(play));
}