Skip to content

Commit

Permalink
Merge pull request #90 from arneboe/rdm_supported_parameters
Browse files Browse the repository at this point in the history
Implement RDM_PID_SUPPORTED_PARAMETERS
  • Loading branch information
someweisguy authored Aug 23, 2023
2 parents 5acc293 + 3e33082 commit 0662963
Show file tree
Hide file tree
Showing 6 changed files with 139 additions and 9 deletions.
6 changes: 3 additions & 3 deletions Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ menu "DMX/RDM Configuration"
instructs the DMX driver to allocate the needed memory on the stack
instead of heap allocating it.

config RDM_RESPONDER_MAX_PARAMETERS
int "Max RDM responder PIDs"
config RDM_RESPONDER_MAX_OPTIONAL_PARAMETERS
int "Max RDM responder optional PIDs"
range 0 512
default 16
help
This is the maximum number of RDM parameter responses that the DMX
This is the maximum number of optional RDM parameter responses that the DMX
driver supports. Increasing this number increases the size of the
DMX driver.

Expand Down
14 changes: 9 additions & 5 deletions src/dmx/config.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,15 +58,19 @@ extern "C" {
#define RDM_UID_DEVICE_ID (0xffffffff)
#endif

#ifdef CONFIG_RDM_RESPONDER_MAX_PARAMETERS
/** @brief The maximum number of parameters that the RDM responder can
#define RDM_RESPONDER_NUM_PIDS_REQUIRED 9

#ifdef CONFIG_RDM_RESPONDER_MAX_OPTIONAL_PARAMETERS
/** @brief The maximum number of optional parameters that the RDM responder can
* support. This value is editable in the Kconfig.*/
#define RDM_RESPONDER_PIDS_MAX (8 + CONFIG_RDM_RESPONDER_MAX_PARAMETERS)
#define RDM_RESPONDER_NUM_PIDS_OPTIONAL (CONFIG_RDM_RESPONDER_MAX_OPTIONAL_PARAMETERS)
#else
#define RDM_RESPONDER_NUM_PIDS_OPTIONAL 25
#endif

/** @brief The maximum number of parameters that the RDM responder can
* support.*/
#define RDM_RESPONDER_PIDS_MAX (8 + 16)
#endif
#define RDM_RESPONDER_PIDS_MAX (RDM_RESPONDER_NUM_PIDS_REQUIRED + RDM_RESPONDER_NUM_PIDS_OPTIONAL)

/** @brief Directs the DMX driver to use spinlocks in critical sections. This is
* needed for devices which have multiple cores.*/
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
66 changes: 66 additions & 0 deletions src/rdm/responder.c
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,41 @@ 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)
{
// 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_RESPONDER_NUM_PIDS_OPTIONAL; i++) {
if(params[i] == 0) {
break;
}
rdm_pd_emplace_word(pd, params[i]);
pd += sizeof(uint16_t);
}
*pdl_out = i * sizeof(uint16_t);

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 +357,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_RESPONDER_NUM_PIDS_OPTIONAL * 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_UNSIGNED_WORD,
.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_RESPONDER_NUM_PIDS_OPTIONAL; 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 @@ -269,11 +297,38 @@ bool rdm_register_parameter(dmx_port_t dmx_num, rdm_sub_device_t sub_device,
driver->rdm_cbs[i].desc = *desc;

bool newCallback = i == driver->num_rdm_cbs;

if(newCallback)
{
// 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
}
}

if(newCallback)
{
++driver->num_rdm_cbs;
}

return true;
}

Expand Down

0 comments on commit 0662963

Please sign in to comment.