static u16 channel_id_to_papd(u16 ch_id) { if (WARN_ON(!is_valid_channel(ch_id))) return 0xff; if (1 <= ch_id && ch_id <= 14) return 0; if (36 <= ch_id && ch_id <= 64) return 1; if (100 <= ch_id && ch_id <= 140) return 2; return 3; }
static u8 ch_id_to_ch_index(u16 ch_id) { if (WARN_ON(!is_valid_channel(ch_id))) return 0xff; if (ch_id <= 14) return ch_id - 1; if (ch_id <= 64) return (ch_id + 20) / 4; if (ch_id <= 140) return (ch_id - 12) / 4; return (ch_id - 13) / 4; }
static uint8_t ch_id_to_ch_index(uint16_t ch_id) { if (!is_valid_channel(ch_id)) return 0xff; if (ch_id <= 14) return ch_id - 1; if (ch_id <= 64) return (ch_id + 20) / 4; if (ch_id <= 140) return (ch_id - 12) / 4; return (ch_id - 13) / 4; }
static uint16_t channel_id_to_papd(uint16_t ch_id) { if (!is_valid_channel(ch_id)) return 0xff; if (1 <= ch_id && ch_id <= 14) return 0; if (36 <= ch_id && ch_id <= 64) return 1; if (100 <= ch_id && ch_id <= 140) return 2; return 3; }
uint8_t execute_pdu(pdu_type *pdu) { switch (pdu->opcode) { case OPCODE_GET_TYPE: { pdu->number_of_arguments = 1; pdu->arguments[0] = MODULE_TYPE; break; } case OPCODE_GET_ID: { pdu->number_of_arguments = 1; pdu->arguments[0] = get_module_id(); break; } case OPCODE_GET_FW_VERSION: { pdu->number_of_arguments = 3; pdu->arguments[0] = FIRMWARE_MAJOR; pdu->arguments[1] = FIRMWARE_MINOR; pdu->arguments[2] = FIRMWARE_PATCHLEVEL; break; } case OPCODE_GET_NR_CHANNELS: { pdu->number_of_arguments = 1; pdu->arguments[0] = NUM_CHANNELS; break; } case OPCODE_GET_FEATURES: { pdu->number_of_arguments = 1; pdu->arguments[0] = 0; break; } case OPCODE_GET_SW_THRESHOLD: { pdu->number_of_arguments = 1; pdu->arguments[0] = get_switch_threshold(); break; } case OPCODE_GET_DIMMER_THRESHOLD: { pdu->number_of_arguments = 1; pdu->arguments[0] = get_long_press_threshold(); break; } case OPCODE_GET_DIMMER_DELAY: { pdu->number_of_arguments = 1; pdu->arguments[0] = get_dimmer_delay(); break; } case OPCODE_GET_SW_TIMER: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint16_t channel_timer = get_switch_timer(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = channel_timer; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_GET_CHANNEL_MAPPING: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t channel_mapping = get_switch_mapping(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = channel_mapping; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_GET_DEFAULT_STATE: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t channel_state = get_default_channel_state(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = channel_state; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_GET_DEFAULT_PERCENTAGE: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t percentage = get_default_dimmer_percentage(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = percentage; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_GET_DEFAULT_DIMMER_DIRECTION: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t direction = get_default_dimmer_direction(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = direction; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_SW_THRESHOLD: { if (pdu->number_of_arguments == 1) { uint16_t threshold = pdu->arguments[0]; set_switch_threshold(threshold); pdu->number_of_arguments = 0; } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_DIMMER_DELAY: { if (pdu->number_of_arguments == 1) { uint8_t delay = pdu->arguments[0]; set_dimmer_delay(delay); pdu->number_of_arguments = 0; } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_DIMMER_THRESHOLD: { if (pdu->number_of_arguments == 1) { uint16_t threshold = pdu->arguments[0]; set_long_press_threshold(threshold); pdu->number_of_arguments = 0; } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_SW_TIMER: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; uint16_t timer = pdu->arguments[1]; if (is_valid_channel(channel_number)) { set_switch_timer(channel_number, timer); pdu->number_of_arguments = 0; } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_CHANNEL_MAPPING: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; uint8_t mapping = pdu->arguments[1]; if (is_valid_channel(channel_number) && is_valid_channel(mapping)) { set_switch_mapping(channel_number, mapping); pdu->number_of_arguments = 0; } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_DEFAULT_STATE: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; uint8_t default_state = pdu->arguments[1]; if (is_valid_channel(channel_number)) { if (default_state == 0 || default_state == 1) { set_default_channel_state(channel_number, default_state); pdu->number_of_arguments = 0; } else { return ERROR_INVALID_STATE; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_DEFAULT_PERCENTAGE: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; uint8_t default_percentage = pdu->arguments[1]; if (is_valid_channel(channel_number)) { if (default_percentage >= 0 || default_percentage <= 100) { set_default_dimmer_percentage(channel_number, default_percentage); pdu->number_of_arguments = 0; } else { return ERROR_INVALID_PERCENTAGE; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SET_DEFAULT_DIMMER_DIRECTION: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; uint8_t default_direction = pdu->arguments[1]; if (is_valid_channel(channel_number)) { if (default_direction == 0 || default_direction == 1) { set_default_dimmer_direction(channel_number, default_direction); pdu->number_of_arguments = 0; } else { return ERROR_INVALID_STATE; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_RELOAD_CONFIGURATION: { configuration_load(); pdu->number_of_arguments = 0; break; } case OPCODE_SAVE_CONFIGURATION: { configuration_save(); pdu->number_of_arguments = 0; break; } case OPCODE_GET_OUTPUT_STATE: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t output_state = get_output_state(channel_number); pdu->number_of_arguments = 2; pdu->arguments[0] = output_state; pdu->arguments[1] = get_percentage(channel_number); } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_GET_INPUT_STATE: { if (pdu->number_of_arguments == 1) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t switch_state = get_switch_state(channel_number); pdu->number_of_arguments = 1; pdu->arguments[0] = switch_state; } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_SWITCH_OUTPUT: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t new_state = pdu->arguments[1]; if (new_state == STATE_OFF || new_state == STATE_ON) { switch_output(channel_number, new_state); pdu->number_of_arguments = 0; } else { return ERROR_INVALID_STATE; } } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } case OPCODE_DIM: { if (pdu->number_of_arguments == 2) { uint8_t channel_number = pdu->arguments[0]; if (is_valid_channel(channel_number)) { uint8_t percentage = pdu->arguments[1]; if (percentage >= 0 || percentage <= 100) { dim(channel_number, percentage); pdu->number_of_arguments = 0; } else { return ERROR_INVALID_PERCENTAGE; } } else { return ERROR_INVALID_CHANNEL_NUMBER; } } else { return ERROR_WRONG_NUMBER_OF_ARGUMENTS; } break; } default: { return ERROR_INVALID_OPCODE; } } return 0; }