int DimmerModel_CapturePreset(const RDMHeader *header,
                              const uint8_t *param_data) {
  if (header->param_data_length != 4 * sizeof(uint16_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t scene_index = ExtractUInt16(&param_data[0]);
  const uint16_t up_fade_time = ExtractUInt16(&param_data[2]);
  const uint16_t down_fade_time = ExtractUInt16(&param_data[4]);
  const uint16_t wait_time = ExtractUInt16(&param_data[6]);

  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];

  if (scene->programmed_state == PRESET_PROGRAMMED_READ_ONLY) {
    return RDMResponder_BuildNack(header, NR_WRITE_PROTECT);
  }

  scene->up_fade_time = up_fade_time;
  scene->down_fade_time = down_fade_time;
  scene->wait_time = wait_time;
  scene->programmed_state = PRESET_PROGRAMMED;
  return RDMResponder_BuildSetAck(header);
}
示例#2
0
int MovingLightModel_SetClock(const RDMHeader *header,
                              const uint8_t *param_data) {
  if (header->param_data_length != sizeof(uint16_t) + 5 * sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t year = ExtractUInt16(param_data);
  const uint8_t month = param_data[2];
  if (year < 2003u || month == 0u || month > 12u) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  const uint8_t day = param_data[3];
  const uint8_t hour = param_data[4];
  const uint8_t minute = param_data[5];
  const uint8_t second = param_data[6];

  // We don't support leap seconds for now.
  if (day == 0u || day > DaysInMonth(year, month) || hour > 24u ||
      minute > 59u || second > 59u) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_moving_light.year = year;
  g_moving_light.month = month;
  g_moving_light.day = day;
  g_moving_light.hour = hour;
  g_moving_light.minute = minute;
  g_moving_light.second = second;
  return RDMResponder_BuildSetAck(header);
}
int DimmerModel_SetMinimumLevel(const RDMHeader *header,
                                const uint8_t *param_data) {
  if (header->param_data_length != 2u * sizeof(uint16_t) + sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t min_level_increasing = ExtractUInt16(&param_data[0]);
  const uint16_t min_level_decreasing = ExtractUInt16(&param_data[2]);
  const uint8_t on_below_min = param_data[4];

  if (on_below_min > 1) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_active_device->min_level_increasing = min_level_increasing;
  g_active_device->min_level_decreasing = min_level_decreasing;
  g_active_device->on_below_min = on_below_min;
  return RDMResponder_BuildSetAck(header);
}
int DimmerModel_SetLockPin(const RDMHeader *header,
                           const uint8_t *param_data) {
  if (header->param_data_length != 2u * sizeof(uint16_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t new_pin = ExtractUInt16(param_data);
  const uint16_t old_pin = ExtractUInt16(&param_data[2]);
  if (new_pin > MAX_PIN_CODE) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  if (old_pin != g_root_device.pin_code) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_root_device.pin_code = new_pin;
  return RDMResponder_BuildSetAck(header);
}
int DimmerModel_SetDMXStartupMode(const RDMHeader *header,
                                  const uint8_t *param_data) {
  if (header->param_data_length != 3u * sizeof(uint16_t) + sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t scene_index = ExtractUInt16(param_data);
  const uint16_t loss_of_signal_delay = ExtractUInt16(&param_data[2]);
  const uint16_t hold_time = ExtractUInt16(&param_data[4]);
  if (scene_index > NUMBER_OF_SCENES && scene_index != PRESET_PLAYBACK_ALL) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_root_device.startup_scene = scene_index;
  g_root_device.startup_delay = loss_of_signal_delay;
  g_root_device.startup_hold = hold_time;
  g_root_device.startup_level = param_data[6];

  return RDMResponder_BuildSetAck(header);
}
int DimmerModel_SetPresetStatus(const RDMHeader *header,
                                const uint8_t *param_data) {
  if (header->param_data_length != 4u * sizeof(uint16_t) + sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t scene_index = ExtractUInt16(&param_data[0]);
  const uint16_t up_fade_time = ExtractUInt16(&param_data[2]);
  const uint16_t down_fade_time = ExtractUInt16(&param_data[4]);
  const uint16_t wait_time = ExtractUInt16(&param_data[6]);
  const uint8_t clear_preset = param_data[8];

  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];
  if (scene->programmed_state == PRESET_PROGRAMMED_READ_ONLY) {
    return RDMResponder_BuildNack(header, NR_WRITE_PROTECT);
  }

  if (clear_preset > 1u) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  if (clear_preset == 1u) {
    scene->up_fade_time = 0u;
    scene->down_fade_time = 0u;
    scene->wait_time = 0u;
    scene->programmed_state = PRESET_NOT_PROGRAMMED;
  } else {
    // don't change the state here, if we haven't been programmed, just update
    // the timing params
    scene->up_fade_time = up_fade_time;
    scene->down_fade_time = down_fade_time;
    scene->wait_time = wait_time;
  }
  return RDMResponder_BuildSetAck(header);
}
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_SetLockState(const RDMHeader *header,
                             const uint8_t *param_data) {
  if (header->param_data_length != sizeof(uint16_t) + sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t pin = ExtractUInt16(param_data);
  const uint8_t lock_state = param_data[2];
  if (pin != g_root_device.pin_code || lock_state >= NUMBER_OF_LOCK_STATES) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_root_device.lock_state = lock_state;
  return RDMResponder_BuildSetAck(header);
}
int DimmerModel_SetPresetPlayback(const RDMHeader *header,
                                  const uint8_t *param_data) {
  if (header->param_data_length != sizeof(uint16_t) + sizeof(uint8_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  const uint16_t playback_mode = ExtractUInt16(param_data);
  if (playback_mode > NUMBER_OF_SCENES &&
      playback_mode != PRESET_PLAYBACK_ALL) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  g_root_device.playback_mode = playback_mode;
  g_root_device.playback_level = param_data[2];

  return RDMResponder_BuildSetAck(header);
}
示例#10
0
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);
}
示例#11
0
int DimmerModel_SetDMXBlockAddress(const RDMHeader *header,
                                   const uint8_t *param_data) {
  if (header->param_data_length != sizeof(uint16_t)) {
    return RDMResponder_BuildNack(header, NR_FORMAT_ERROR);
  }

  uint16_t start_address = ExtractUInt16(param_data);
  if (start_address == 0u || start_address > MAX_DMX_START_ADDRESS) {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }

  bool ok = ResetToBlockAddress(start_address);
  if (ok) {
    return RDMResponder_BuildSetAck(header);
  } else {
    return RDMResponder_BuildNack(header, NR_DATA_OUT_OF_RANGE);
  }
}