Skip to content

Commit

Permalink
feat: Support for RDM_PID_SUPPORTED_PARAMETERS
Browse files Browse the repository at this point in the history
  • Loading branch information
arneboe committed Aug 19, 2023
1 parent abd31d1 commit 3f37297
Show file tree
Hide file tree
Showing 5 changed files with 139 additions and 1 deletion.
7 changes: 7 additions & 0 deletions src/dmx/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,13 @@ extern "C" {
#define RDM_RESPONDER_PIDS_MAX (8 + 16)
#endif

/** @brief The maximum number of additional parameters that is supported.
*
* According to ANSI-E1-20-2010 we can support up to 115 additional parameters.
* In practice we will never need that many, thus we limit it to save memory.
*/
#define RDM_MAX_NUM_ADDITIONAL_PARAMETERS 25

/** @brief Directs the DMX driver to use spinlocks in critical sections. This is
* needed for devices which have multiple cores.*/
#define DMX_USE_SPINLOCK
Expand Down
1 change: 1 addition & 0 deletions src/dmx/hal.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ bool dmx_driver_install(dmx_port_t dmx_num, const dmx_config_t *config,
.sub_device_count = 0, // Sub-devices must be registered
.sensor_count = 0, // Sensors must be registered
};
rdm_register_supported_parameters(dmx_num, NULL, NULL);
rdm_register_disc_unique_branch(dmx_num, NULL, NULL);
rdm_register_disc_un_mute(dmx_num, NULL, NULL);
rdm_register_disc_mute(dmx_num, NULL, NULL);
Expand Down
71 changes: 71 additions & 0 deletions src/rdm/responder.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,46 @@ static int rdm_simple_response_cb(dmx_port_t dmx_num,
return RDM_RESPONSE_TYPE_ACK;
}

static int rdm_supported_params_response_cb(dmx_port_t dmx_num,
const rdm_header_t *header, void *pd,
uint8_t *pdl_out, void *param,
const rdm_pid_description_t *desc,
const char *param_str)
{
DMX_CHECK(dmx_num < DMX_NUM_MAX, RDM_RESPONSE_TYPE_NONE, "dmx_num error");
DMX_CHECK(dmx_driver_is_installed(dmx_num), RDM_RESPONSE_TYPE_NONE, "driver is not installed");

// Return early if the sub-device is out of range
if (header->sub_device != RDM_SUB_DEVICE_ROOT) {
*pdl_out = rdm_pd_emplace_word(pd, RDM_NR_SUB_DEVICE_OUT_OF_RANGE);
return RDM_RESPONSE_TYPE_NACK_REASON;
}

if (header->cc != RDM_CC_GET_COMMAND) {
//the supported params list is read-only
ESP_LOGE(TAG, "RDM_PID_SUPPORTED_PARAMETERS is read-only");
*pdl_out = rdm_pd_emplace_word(pd, RDM_NR_WRITE_PROTECT);
return RDM_RESPONSE_TYPE_NACK_REASON;
}

uint16_t *params = (uint16_t*)param;

int i = 0;
for(; i < RDM_MAX_NUM_ADDITIONAL_PARAMETERS; i++) {
if(params[i] == 0) {
break;
}
rdm_pd_emplace_word(pd, params[i]);
pd += sizeof(uint16_t);
}
*pdl_out = i * sizeof(uint16_t);

ESP_LOGE(TAG, "NUM OF ADDITIONAL PARAMS: %d\n", i);

return RDM_RESPONSE_TYPE_ACK;
}


bool rdm_register_device_info(dmx_port_t dmx_num,
rdm_device_info_t *device_info,
rdm_responder_cb_t cb, void *context) {
Expand Down Expand Up @@ -322,6 +362,37 @@ bool rdm_register_identify_device(dmx_port_t dmx_num, rdm_responder_cb_t cb,
rdm_simple_response_cb, param, cb, context);
}


bool rdm_register_supported_parameters(dmx_port_t dmx_num, rdm_responder_cb_t cb,
void *context)
{
DMX_CHECK(dmx_num < DMX_NUM_MAX, false, "dmx_num error");
DMX_CHECK(dmx_driver_is_installed(dmx_num), false, "driver is not installed");

const uint16_t size = RDM_MAX_NUM_ADDITIONAL_PARAMETERS * sizeof(uint16_t);
uint16_t *param = rdm_pd_find(dmx_num, RDM_PID_SUPPORTED_PARAMETERS);
if (param == NULL) {
param = rdm_pd_alloc(dmx_num, size);
if (param == NULL) {
return false;
}
memset(param, 0, size);
}

const rdm_pid_description_t desc = {.pid = RDM_PID_SUPPORTED_PARAMETERS,
.pdl_size = size,
.data_type = RDM_DS_NOT_DEFINED,
.cc = RDM_CC_GET,
.unit = RDM_UNITS_NONE,
.prefix = RDM_PREFIX_NONE,
.min_value = 0,
.max_value = 0,
.default_value = 0,
.description = "Supported Parameters"};
return rdm_register_parameter(dmx_num, RDM_SUB_DEVICE_ROOT, &desc, NULL,
rdm_supported_params_response_cb, param, NULL, NULL);
}

bool rdm_register_dmx_start_address(dmx_port_t dmx_num, rdm_responder_cb_t cb,
void *context) {
DMX_CHECK(dmx_num < DMX_NUM_MAX, false, "dmx_num error");
Expand Down
4 changes: 4 additions & 0 deletions src/rdm/responder.h
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,10 @@ bool rdm_register_software_version_label(dmx_port_t dmx_num,
bool rdm_register_identify_device(dmx_port_t dmx_num, rdm_responder_cb_t cb,
void *context);


bool rdm_register_supported_parameters(dmx_port_t dmx_num, rdm_responder_cb_t cb,
void *context);

/**
* @brief Registers the default response to RDM_PID_DMX_START_ADDRESS requests.
* This response is required by all RDM-capable devices which use a DMX address.
Expand Down
57 changes: 56 additions & 1 deletion src/rdm_utils.c
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,34 @@ void *rdm_pd_find(dmx_port_t dmx_num, rdm_pid_t pid) {
return ret;
}

static bool rdm_add_supported_parameter(dmx_port_t dmx_num, uint16_t pid)
{
uint16_t *param = rdm_pd_find(dmx_num, RDM_PID_SUPPORTED_PARAMETERS);
if (param == NULL) {
ESP_LOGE(TAG, "RDM_PID_SUPPORTED_PARAMETERS needs to be added first");
return false;
}

//find next free slot in parameter list and insert the pid
for(int i = 0; i < RDM_MAX_NUM_ADDITIONAL_PARAMETERS; i++)
{
if(param[i] == pid)
{
// Parameter already in parameter list, nothing to do
return true;
}

if(param[i] == 0)
{
param[i] = pid;
}
return true;
}

ESP_LOGE(TAG, "Not space left in parameter list. Increase RDM_MAX_NUM_ADDITIONAL_PARAMETERS and recompile");
return false;
}

bool rdm_register_parameter(dmx_port_t dmx_num, rdm_sub_device_t sub_device,
const rdm_pid_description_t *desc,
const char *param_str, rdm_driver_cb_t driver_cb,
Expand Down Expand Up @@ -267,8 +295,35 @@ bool rdm_register_parameter(dmx_port_t dmx_num, rdm_sub_device_t sub_device,
driver->rdm_cbs[i].user_cb = user_cb;
driver->rdm_cbs[i].driver_cb = driver_cb;
driver->rdm_cbs[i].desc = *desc;
++driver->num_rdm_cbs;

if(i == driver->num_rdm_cbs) //only if this is a new parameter
{
// If this parameter lies outside the minimum required parameter set, we
// need to put it into the supported_parameters list to let rdm masters know
// about it.
switch(desc->pid)
{
// minimum required parameters
case RDM_PID_DISC_UNIQUE_BRANCH:
case RDM_PID_DISC_MUTE:
case RDM_PID_DISC_UN_MUTE:
case RDM_PID_SUPPORTED_PARAMETERS:
case RDM_PID_PARAMETER_DESCRIPTION:
case RDM_PID_DEVICE_INFO:
case RDM_PID_SOFTWARE_VERSION_LABEL:
case RDM_PID_DMX_START_ADDRESS:
case RDM_PID_IDENTIFY_DEVICE:
break;
default:
if(!rdm_add_supported_parameter(dmx_num, desc->pid))
{
ESP_LOGE(TAG, "Failed to add parmeter %d to parmeter list.", desc->pid);
}
ESP_LOGE("RDM", "Added parameter: %d\n", desc->pid); //TODO remove this line after debug
}
}

++driver->num_rdm_cbs;
return true;
}

Expand Down

0 comments on commit 3f37297

Please sign in to comment.