int DimmerModel_GetDMXBlockAddress(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint16_t total_footprint = 0u; uint16_t expected_start_address = 0u; bool is_contiguous = true; unsigned int i = 0u; for (; i < NUMBER_OF_SUB_DEVICES; i++) { RDMResponder *responder = &g_subdevices[i].responder; uint16_t sub_device_footprint = responder->def ->personalities[responder->current_personality - 1u].slot_count; total_footprint += sub_device_footprint; if (expected_start_address && expected_start_address != responder->dmx_start_address) { is_contiguous = false; } else if (expected_start_address) { expected_start_address += sub_device_footprint; } else { expected_start_address = responder->dmx_start_address + sub_device_footprint; } } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, total_footprint); ptr = PushUInt16( ptr, is_contiguous ? g_subdevices[0].responder.dmx_start_address : INVALID_DMX_START_ADDRESS); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
static int GetModelList(const RDMHeader *header) { uint8_t our_uid[UID_LENGTH]; RDMHandler_GetUID(our_uid); if (RDMUtil_UIDCompare(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } uint16_t sub_device = ntohs(header->sub_device); // No subdevice support for now. if (sub_device != SUBDEVICE_ROOT) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } if (header->command_class != GET_COMMAND) { return RDMResponder_BuildNack(header, NR_UNSUPPORTED_COMMAND_CLASS); } if (header->param_data_length) { return RDMResponder_BuildNack(header, NR_FORMAT_ERROR); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); unsigned int i = 0u; for (; i < MAX_RDM_MODELS; i++) { if (g_models[i].model_id != NULL_MODEL_ID) { ptr = PushUInt16(ptr, g_models[i].model_id); } } return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetCurve(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = g_active_device->curve; *ptr++ = NUMBER_OF_CURVES; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetOutputResponseTime(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = g_active_device->output_response_time; *ptr++ = NUMBER_OF_OUTPUT_RESPONSE_TIMES; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetModulationFrequency(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = g_active_device->modulation_frequency; *ptr++ = NUMBER_OF_MODULATION_FREQUENCIES; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetPresetPlayback(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, g_root_device.playback_mode); *ptr++ = g_root_device.playback_level; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
// Proxy PID Handlers // ---------------------------------------------------------------------------- int ProxyModel_GetProxiedDeviceCount(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, NUMBER_OF_CHILDREN); *ptr++ = 0; // list change return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetLockState(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = g_root_device.lock_state; // We don't include the unlocked state. *ptr++ = NUMBER_OF_LOCK_STATES - 1u; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetMinimumLevel(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, g_active_device->min_level_increasing); ptr = PushUInt16(ptr, g_active_device->min_level_decreasing); *ptr++ = g_active_device->on_below_min; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int MovingLightModel_GetLanguage(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr += RDMUtil_StringCopy((char*) ptr, RDM_LANGUAGE_STRING_SIZE, LANGUAGES[g_moving_light.language_index], RDM_LANGUAGE_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetDMXFailMode(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, g_root_device.fail_scene); ptr = PushUInt16(ptr, g_root_device.fail_loss_of_signal_delay); ptr = PushUInt16(ptr, g_root_device.fail_hold_time); *ptr++ = g_root_device.fail_level; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetDMXStartupMode(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, g_root_device.startup_scene); ptr = PushUInt16(ptr, g_root_device.startup_delay); ptr = PushUInt16(ptr, g_root_device.startup_hold); *ptr++ = g_root_device.startup_level; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
static int GetSetModelId(const RDMHeader *header, const uint8_t *param_data) { uint8_t our_uid[UID_LENGTH]; RDMHandler_GetUID(our_uid); if (!RDMUtil_RequiresAction(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } uint16_t sub_device = ntohs(header->sub_device); // No subdevice support for now. if (sub_device != SUBDEVICE_ROOT && sub_device != SUBDEVICE_ALL) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } else if (sub_device == SUBDEVICE_ALL && header->command_class == GET_COMMAND) { return RDMResponder_BuildNack(header, NR_SUB_DEVICE_OUT_OF_RANGE); } if (header->command_class == GET_COMMAND) { if (header->param_data_length) { return RDMResponder_BuildNack(header, NR_FORMAT_ERROR); } if (RDMUtil_UIDCompare(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } uint16_t model_id = NULL_MODEL_ID; if (g_rdm_handler.active_model) { model_id = g_rdm_handler.active_model->model_id; } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, model_id); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); } else if (header->command_class == SET_COMMAND) { if (header->param_data_length != sizeof(uint16_t)) { return RDMResponder_BuildNack(header, NR_FORMAT_ERROR); } // take action uint16_t new_model = JoinShort(param_data[0], param_data[1]); bool ok = RDMHandler_SetActiveModel(new_model); if (RDMUtil_UIDCompare(our_uid, header->dest_uid)) { return RDM_RESPONDER_NO_RESPONSE; } if (!ok) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } return RDMResponder_BuildSetAck(header); } return RDM_RESPONDER_NO_RESPONSE; }
// PID Handlers // ---------------------------------------------------------------------------- int MovingLightModel_GetLanguageCapabilities(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); unsigned int i = 0; for (; i < NUMBER_OF_LANGUAGES; i++) { ptr += RDMUtil_StringCopy((char*) ptr, RDM_LANGUAGE_STRING_SIZE, LANGUAGES[i], RDM_LANGUAGE_STRING_SIZE); } return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int ProxyModel_GetProxiedDevices(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); unsigned int i = 0u; for (; i < NUMBER_OF_CHILDREN; i++) { memcpy(ptr, g_children[i].responder.uid, UID_LENGTH); ptr += UID_LENGTH; } return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int MovingLightModel_GetClock(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, g_moving_light.year); *ptr++ = g_moving_light.month; *ptr++ = g_moving_light.day; *ptr++ = g_moving_light.hour; *ptr++ = g_moving_light.minute; *ptr++ = g_moving_light.second; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetDimmerInfo(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, 0u); // min level lower ptr = PushUInt16(ptr, 0xfffe); // min level upper ptr = PushUInt16(ptr, 0u); // max level lower ptr = PushUInt16(ptr, 0xfffe); // max level upper *ptr++ = NUMBER_OF_CURVES; *ptr++ = 8u; // level resolution *ptr++ = 1u; // split levels supported return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetStatusIdDescription(const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint16_t status_id = ExtractUInt16(param_data); if (status_id != STS_OLP_TESTING) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, STS_OLP_TESTING_DESCRIPTION, RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetOutputResponseDescription(const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint8_t setting = param_data[0]; if (setting == 0u || setting > NUMBER_OF_OUTPUT_RESPONSE_TIMES) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = setting; ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, OUTPUT_RESPONSE_TIMES[setting - 1], RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetCurveDescription(const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint8_t curve = param_data[0]; if (curve == 0u || curve > NUMBER_OF_CURVES) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = curve; ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, DIMMER_CURVES[curve - 1], RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetLockStateDescription(const RDMHeader *header, const uint8_t *param_data) { const uint8_t lock_state = param_data[0]; if (lock_state == 0u || lock_state >= NUMBER_OF_LOCK_STATES) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = lock_state; ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, LOCK_STATES[lock_state], RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetSelfTestDescription(const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint8_t self_test_id = param_data[0]; if (self_test_id == SELF_TEST_OFF || self_test_id > NUMBER_OF_SELF_TESTS) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = self_test_id; ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, SELF_TESTS[self_test_id - 1].description, RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetModulationFrequencyDescription( const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint8_t setting = param_data[0]; if (setting == 0u || setting > NUMBER_OF_MODULATION_FREQUENCIES) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } const ModulationFrequency *frequency = &MODULATION_FREQUENCY[setting - 1]; uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = setting; ptr = PushUInt32(ptr, frequency->frequency); ptr += RDMUtil_StringCopy((char*) ptr, RDM_DEFAULT_STRING_SIZE, frequency->description, RDM_DEFAULT_STRING_SIZE); return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetPresetStatus(const RDMHeader *header, UNUSED const uint8_t *param_data) { const uint16_t scene_index = ExtractUInt16(¶m_data[0]); if (scene_index == 0u || scene_index > NUMBER_OF_SCENES) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } Scene *scene = &g_root_device.scenes[scene_index - 1u]; uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); ptr = PushUInt16(ptr, scene_index); ptr = PushUInt16(ptr, scene->up_fade_time); ptr = PushUInt16(ptr, scene->down_fade_time); ptr = PushUInt16(ptr, scene->wait_time); *ptr++ = scene->programmed_state; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
// Root PID Handlers // ---------------------------------------------------------------------------- int DimmerModel_GetStatusMessages(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t threshold = param_data[0]; if (threshold > STATUS_ERROR) { return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE); } uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); if (threshold == STATUS_GET_LAST_MESSAGE) { // Return the last set of messages. unsigned int i = 0u; for (; i < g_status_messages.count; i++) { ptr = AddStatusMessageToResponse(ptr, &g_status_messages.last[i]); } } else { // Build the list of status messages. g_status_messages.count = 0u; // Check the root if (g_root_device.status_message.is_active && MaybeDequeueStatusMessage(&g_root_device.status_message, threshold)) { ptr = AddStatusMessageToResponse( ptr, &g_status_messages.last[g_status_messages.count]); g_status_messages.count++; } // Check the sub devices. unsigned int i = 0u; for (; i < NUMBER_OF_SUB_DEVICES && g_status_messages.count < STATUS_MESSAGE_QUEUE_SIZE; i++) { DimmerSubDevice *subdevice = &g_subdevices[i]; if (MaybeDequeueStatusMessage(&subdevice->status_message, threshold)) { ptr = AddStatusMessageToResponse( ptr, &g_status_messages.last[g_status_messages.count]); g_status_messages.count++; } } } return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetPresetInfo(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = true; // level supported *ptr++ = true; // sequence supported *ptr++ = true; // split times supported *ptr++ = true; // fail infinite delay supported *ptr++ = true; // fail infinite hold supported *ptr++ = true; // startup infinite hold supported ptr = PushUInt16(ptr, NUMBER_OF_SCENES); ptr = PushUInt16(ptr, 0u); // min fade time ptr = PushUInt16(ptr, 0xfffe); // max fade time ptr = PushUInt16(ptr, 0u); // min wait time ptr = PushUInt16(ptr, 0xfffe); // max wait time ptr = PushUInt16(ptr, 0u); // min fail delay time ptr = PushUInt16(ptr, 0xfffe); // max fail delay time ptr = PushUInt16(ptr, 0u); // min fail hold time ptr = PushUInt16(ptr, 0xfffe); // max fail hold time ptr = PushUInt16(ptr, 0u); // min startup delay time ptr = PushUInt16(ptr, 0xfffe); // max startup delay time ptr = PushUInt16(ptr, 0u); // min startup hold time ptr = PushUInt16(ptr, 0xfffe); // max startup hold time return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }
int DimmerModel_GetSelfTest(const RDMHeader *header, UNUSED const uint8_t *param_data) { uint8_t *ptr = g_rdm_buffer + sizeof(RDMHeader); *ptr++ = g_root_device.running_self_test ? true : false; return RDMResponder_AddHeaderAndChecksum(header, ACK, ptr - g_rdm_buffer); }