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);
}
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 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);
}
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);
}
uint8_t *AddStatusMessageToResponse(uint8_t *ptr,
                                    const StatusMessage *message) {
  ptr = PushUInt16(ptr, message->sub_device);
  *ptr++ = message->status_type;
  ptr = PushUInt16(ptr, message->message_id);
  ptr = PushUInt16(ptr, message->data_value1);
  ptr = PushUInt16(ptr, message->data_value2);
  return ptr;
}
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_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);
}
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);
}
// 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_GetPresetStatus(const RDMHeader *header,
                                UNUSED const uint8_t *param_data) {
  const uint16_t scene_index = ExtractUInt16(&param_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);
}
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;
}
Beispiel #12
0
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_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);
}