diff --git a/projects/smoke_steering/src/main.c b/projects/smoke_steering/src/main.c index 971011724..ef58bf64c 100644 --- a/projects/smoke_steering/src/main.c +++ b/projects/smoke_steering/src/main.c @@ -12,9 +12,9 @@ { .port = GPIO_PORT_A, .pin = 4 } #define RADIO_PTT_GPIO_ADDR \ { .port = GPIO_PORT_B, .pin = 1 } -#define DRL_1_GPIO_ADDR \ +#define DRL_ON_GPIO_ADDR \ { .port = GPIO_PORT_A, .pin = 6 } -#define DRL_2_GPIO_ADDR \ +#define DRL_OFF_GPIO_ADDR \ { .port = GPIO_PORT_A, .pin = 5 } #define REGEN_BRAKE_TOGGLE_GPIO_ADDR \ { .port = GPIO_PORT_A, .pin = 7 } @@ -28,18 +28,18 @@ #define TIMER_INTERVAL_MS 1000 #define VOLTAGE_TOLERANCE_MV 10 // Check these values for the turn signal empirically -#define STEERING_CONTROL_STALK_LEFT_SIGNAL_VOLTAGE_MV 2972 -#define STEERING_CONTROL_STALK_RIGHT_SIGNAL_VOLTAGE_MV 3013 +#define STEERING_CONTROL_STALK_LEFT_SIGNAL_VOLTAGE_MV 3025 +#define STEERING_CONTROL_STALK_RIGHT_SIGNAL_VOLTAGE_MV 2984 #define STEERING_CONTROL_STALK_NO_SIGNAL_VOLTAGE_MV 3300 #define ADC_READER_GPIO_ADDR \ { .port = GPIO_PORT_A, .pin = 3 } +#define DRL_SIGNAL_VOLTAGE_MV 1500 +#define DRL_SIGNAL_VOLTAGE_TOLERANCE_MV 300 typedef enum { STEERING_DIGITAL_INPUT_HORN = 0, - STEERING_DIGITAL_INPUT_RADIO_PTT, - STEERING_DIGITAL_INPUT_DRL_1, - STEERING_DIGITAL_INPUT_DRL_2, STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE, + STEERING_DIGITAL_INPUT_RADIO_PTT, STEERING_DIGITAL_INPUT_CC_TOGGLE, STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED, STEERING_DIGITAL_INPUT_CC_DECREASE_SPEED, @@ -49,8 +49,6 @@ typedef enum { static GpioAddress s_steering_address_lookup_table[NUM_STEERING_DIGITAL_INPUTS] = { [STEERING_DIGITAL_INPUT_HORN] = HORN_GPIO_ADDR, [STEERING_DIGITAL_INPUT_RADIO_PTT] = RADIO_PTT_GPIO_ADDR, - [STEERING_DIGITAL_INPUT_DRL_1] = DRL_1_GPIO_ADDR, - [STEERING_DIGITAL_INPUT_DRL_2] = DRL_2_GPIO_ADDR, [STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE] = REGEN_BRAKE_TOGGLE_GPIO_ADDR, [STEERING_DIGITAL_INPUT_CC_TOGGLE] = CC_TOGGLE_GPIO_ADDR, [STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED] = CC_INCREASE_SPEED_GPIO_ADDR, @@ -60,8 +58,6 @@ static GpioAddress s_steering_address_lookup_table[NUM_STEERING_DIGITAL_INPUTS] static char *s_steering_input_lookup_table[NUM_STEERING_DIGITAL_INPUTS] = { [STEERING_DIGITAL_INPUT_HORN] = "Horn", [STEERING_DIGITAL_INPUT_RADIO_PTT] = "Radio PTT (formerly lane assist)", - [STEERING_DIGITAL_INPUT_DRL_1] = "DRL 1 (formerly high beam forward)", - [STEERING_DIGITAL_INPUT_DRL_2] = "DRL 2 (formerly high beam rear)", [STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE] = "Regenerative Braking", [STEERING_DIGITAL_INPUT_CC_TOGGLE] = "Cruise Control", [STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED] = "Increase Speed Cruise Control", @@ -84,6 +80,22 @@ void prv_callback_log_adc(uint16_t data, PeriodicReaderId id, void *context) { LOG_DEBUG("Turn Signal ADC value: %d\n", data); } +void prv_callback_log_drl_on(uint16_t data, PeriodicReaderId id, void *context) { + if (data > DRL_SIGNAL_VOLTAGE_MV - DRL_SIGNAL_VOLTAGE_TOLERANCE_MV && + data < DRL_SIGNAL_VOLTAGE_MV + DRL_SIGNAL_VOLTAGE_TOLERANCE_MV) { + LOG_DEBUG("DRL ON signal triggered\n"); + } + LOG_DEBUG("DRL ON Signal ADC value: %d\n", data); +} + +void prv_callback_log_drl_off(uint16_t data, PeriodicReaderId id, void *context) { + if (data > DRL_SIGNAL_VOLTAGE_MV - DRL_SIGNAL_VOLTAGE_TOLERANCE_MV && + data < DRL_SIGNAL_VOLTAGE_MV + DRL_SIGNAL_VOLTAGE_TOLERANCE_MV) { + LOG_DEBUG("DRL OFF signal triggered\n"); + } + LOG_DEBUG("DRL OFF Signal ADC value: %d\n", data); +} + void prv_init_buttons() { GpioSettings digital_input_settings = { .direction = GPIO_DIR_IN, // @@ -117,8 +129,20 @@ void prv_init_stalk() { .address = ADC_READER_GPIO_ADDR, .callback = prv_callback_log_adc, }; + AdcPeriodicReaderSettings drl_on_settings = { + .address = DRL_ON_GPIO_ADDR, + .callback = prv_callback_log_drl_on, + }; + AdcPeriodicReaderSettings drl_off_settings = { + .address = DRL_OFF_GPIO_ADDR, + .callback = prv_callback_log_drl_off, + }; adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_0, &reader_settings); adc_periodic_reader_start(PERIODIC_READER_ID_0); + adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_1, &drl_on_settings); + adc_periodic_reader_start(PERIODIC_READER_ID_1); + adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_2, &drl_off_settings); + adc_periodic_reader_start(PERIODIC_READER_ID_2); } int main(void) { diff --git a/projects/steering/inc/steering_control_stalk.h b/projects/steering/inc/steering_control_stalk.h index beb68d323..efce11998 100644 --- a/projects/steering/inc/steering_control_stalk.h +++ b/projects/steering/inc/steering_control_stalk.h @@ -5,10 +5,19 @@ #include "event_queue.h" #include "status.h" -#define VOLTAGE_TOLERANCE_MV 100 -#define STEERING_CONTROL_STALK_LEFT_SIGNAL_VOLTAGE_MV 1000 -#define STEERING_CONTROL_STALK_RIGHT_SIGNAL_VOLTAGE_MV 2000 +#define VOLTAGE_TOLERANCE_MV 20 +#define STEERING_CONTROL_STALK_LEFT_SIGNAL_VOLTAGE_MV 3025 +#define STEERING_CONTROL_STALK_RIGHT_SIGNAL_VOLTAGE_MV 2984 +#define DRL_SIGNAL_VOLTAGE_MV 1500 +#define DRL_SIGNAL_VOLTAGE_TOLERANCE_MV 300 + +#define DRL_ON_GPIO_ADDR \ + { .port = GPIO_PORT_A, .pin = 6 } +#define DRL_OFF_GPIO_ADDR \ + { .port = GPIO_PORT_A, .pin = 5 } StatusCode control_stalk_init(); void control_stalk_callback(uint16_t data, PeriodicReaderId id, void *context); +void drl_on_callback(uint16_t data, PeriodicReaderId id, void *context); +void drl_off_callback(uint16_t data, PeriodicReaderId id, void *context); diff --git a/projects/steering/inc/steering_digital_input.h b/projects/steering/inc/steering_digital_input.h index 342ac162f..1c7a8be36 100644 --- a/projects/steering/inc/steering_digital_input.h +++ b/projects/steering/inc/steering_digital_input.h @@ -9,10 +9,6 @@ { .port = GPIO_PORT_A, .pin = 4 } #define RADIO_PPT_GPIO_ADDR \ { .port = GPIO_PORT_B, .pin = 1 } -#define DRL_1_GPIO_ADDR \ - { .port = GPIO_PORT_A, .pin = 6 } -#define DRL_2_GPIO_ADDR \ - { .port = GPIO_PORT_A, .pin = 5 } #define REGEN_BRAKE_TOGGLE_GPIO_ADDR \ { .port = GPIO_PORT_A, .pin = 7 } #define CC_TOGGLE_GPIO_ADDR \ @@ -25,8 +21,6 @@ typedef enum { STEERING_DIGITAL_INPUT_HORN = 0, STEERING_DIGITAL_INPUT_RADIO_PPT, - STEERING_DIGITAL_INPUT_DRL_1, - STEERING_DIGITAL_INPUT_DRL_2, STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE, STEERING_DIGITAL_INPUT_CC_TOGGLE, STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED, diff --git a/projects/steering/inc/steering_events.h b/projects/steering/inc/steering_events.h index 5e6774f49..830a5b784 100644 --- a/projects/steering/inc/steering_events.h +++ b/projects/steering/inc/steering_events.h @@ -4,8 +4,6 @@ typedef enum { // Digital STEERING_INPUT_HORN_EVENT = 0, STEERING_RADIO_PPT_EVENT, - STEERING_DRL_1_EVENT, - STEERING_DRL_2_EVENT, STEERING_REGEN_BRAKE_EVENT, STEERING_DIGITAL_INPUT_CC_TOGGLE_PRESSED_EVENT, STEERING_CC_INCREASE_SPEED_EVENT, @@ -16,10 +14,12 @@ typedef enum { // Analog STEERING_CONTROL_STALK_EVENT_LEFT_SIGNAL = STEERING_CC_DECREASE_SPEED_EVENT + 1, STEERING_CONTROL_STALK_EVENT_RIGHT_SIGNAL, + STEERING_DRL_ON_EVENT, + STEERING_DRL_OFF_EVENT, } SteeringAnalogEvent; typedef enum { - STEERING_CAN_EVENT_RX = STEERING_CONTROL_STALK_EVENT_RIGHT_SIGNAL + 1, + STEERING_CAN_EVENT_RX = STEERING_DRL_OFF_EVENT + 1, STEERING_CAN_EVENT_TX, STEERING_CAN_FAULT, NUM_TOTAL_STEERING_EVENTS, diff --git a/projects/steering/src/steering_can.c b/projects/steering/src/steering_can.c index b11674ebf..79593e1ed 100644 --- a/projects/steering/src/steering_can.c +++ b/projects/steering/src/steering_can.c @@ -1,4 +1,5 @@ #include "steering_can.h" + #include "can.h" #include "can_transmit.h" #include "event_queue.h" @@ -7,16 +8,18 @@ #include "steering_digital_input.h" #include "steering_events.h" +static bool turning = false; + StatusCode steering_can_process_event(Event *e) { switch (e->id) { case STEERING_INPUT_HORN_EVENT: CAN_TRANSMIT_HORN((EEHornState)e->data); break; - case STEERING_DRL_1_EVENT: - CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_DRL, (EELightState)e->data); + case STEERING_DRL_ON_EVENT: + if (turning == false) CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_DRL, EE_LIGHT_STATE_ON); break; - case STEERING_DRL_2_EVENT: - CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_DRL, (EELightState)e->data); + case STEERING_DRL_OFF_EVENT: + CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_DRL, EE_LIGHT_STATE_OFF); break; case STEERING_DIGITAL_INPUT_CC_TOGGLE_PRESSED_EVENT: CAN_TRANSMIT_CRUISE_CONTROL_COMMAND(EE_CRUISE_CONTROL_COMMAND_TOGGLE); @@ -29,9 +32,11 @@ StatusCode steering_can_process_event(Event *e) { break; case STEERING_CONTROL_STALK_EVENT_LEFT_SIGNAL: CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_SIGNAL_LEFT, (EELightState)e->data); + turning = ((EELightState)e->data == EE_LIGHT_STATE_ON); break; case STEERING_CONTROL_STALK_EVENT_RIGHT_SIGNAL: CAN_TRANSMIT_LIGHTS(EE_LIGHT_TYPE_SIGNAL_RIGHT, (EELightState)e->data); + turning = ((EELightState)e->data == EE_LIGHT_STATE_ON); break; case STEERING_REGEN_BRAKE_EVENT: CAN_TRANSMIT_REGEN_BRAKING_TOGGLE_REQUEST(); diff --git a/projects/steering/src/steering_control_stalk.c b/projects/steering/src/steering_control_stalk.c index d122ee077..d85bb9bfa 100644 --- a/projects/steering/src/steering_control_stalk.c +++ b/projects/steering/src/steering_control_stalk.c @@ -6,6 +6,10 @@ AdcPeriodicReaderSettings reader_settings = { .address = { .port = GPIO_PORT_A, .pin = 3 }, .callback = control_stalk_callback }; +AdcPeriodicReaderSettings drl_on_settings = { .address = DRL_ON_GPIO_ADDR, + .callback = drl_on_callback }; +AdcPeriodicReaderSettings drl_off_settings = { .address = DRL_OFF_GPIO_ADDR, + .callback = drl_off_callback }; // Stores event id of the previous event that was just raised static SteeringAnalogEvent prev = 0; @@ -24,8 +28,26 @@ void control_stalk_callback(uint16_t data, PeriodicReaderId id, void *context) { } } +void drl_on_callback(uint16_t data, PeriodicReaderId id, void *context) { + if (data > DRL_SIGNAL_VOLTAGE_MV - DRL_SIGNAL_VOLTAGE_TOLERANCE_MV && + data < DRL_SIGNAL_VOLTAGE_MV + DRL_SIGNAL_VOLTAGE_TOLERANCE_MV) { + event_raise((EventId)STEERING_DRL_ON_EVENT, data); + } +} + +void drl_off_callback(uint16_t data, PeriodicReaderId id, void *context) { + if (data > DRL_SIGNAL_VOLTAGE_MV - DRL_SIGNAL_VOLTAGE_TOLERANCE_MV && + data < DRL_SIGNAL_VOLTAGE_MV + DRL_SIGNAL_VOLTAGE_TOLERANCE_MV) { + event_raise((EventId)STEERING_DRL_OFF_EVENT, data); + } +} + StatusCode control_stalk_init() { status_ok_or_return(adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_0, &reader_settings)); status_ok_or_return(adc_periodic_reader_start(PERIODIC_READER_ID_0)); + status_ok_or_return(adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_1, &drl_on_settings)); + status_ok_or_return(adc_periodic_reader_start(PERIODIC_READER_ID_1)); + status_ok_or_return(adc_periodic_reader_set_up_reader(PERIODIC_READER_ID_2, &drl_off_settings)); + status_ok_or_return(adc_periodic_reader_start(PERIODIC_READER_ID_2)); return STATUS_CODE_OK; } diff --git a/projects/steering/src/steering_digital_input.c b/projects/steering/src/steering_digital_input.c index e0dfedf8c..949967454 100644 --- a/projects/steering/src/steering_digital_input.c +++ b/projects/steering/src/steering_digital_input.c @@ -10,8 +10,6 @@ static GpioAddress s_steering_address_lookup_table[NUM_STEERING_DIGITAL_INPUTS] = { [STEERING_DIGITAL_INPUT_HORN] = HORN_GPIO_ADDR, [STEERING_DIGITAL_INPUT_RADIO_PPT] = RADIO_PPT_GPIO_ADDR, - [STEERING_DIGITAL_INPUT_DRL_1] = DRL_1_GPIO_ADDR, - [STEERING_DIGITAL_INPUT_DRL_2] = DRL_2_GPIO_ADDR, [STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE] = REGEN_BRAKE_TOGGLE_GPIO_ADDR, [STEERING_DIGITAL_INPUT_CC_TOGGLE] = CC_TOGGLE_GPIO_ADDR, [STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED] = CC_INCREASE_SPEED_GPIO_ADDR, @@ -21,8 +19,6 @@ static GpioAddress s_steering_address_lookup_table[NUM_STEERING_DIGITAL_INPUTS] static EventId s_steering_event_lookup_table[NUM_STEERING_DIGITAL_INPUTS] = { [STEERING_DIGITAL_INPUT_HORN] = STEERING_INPUT_HORN_EVENT, [STEERING_DIGITAL_INPUT_RADIO_PPT] = STEERING_RADIO_PPT_EVENT, - [STEERING_DIGITAL_INPUT_DRL_1] = STEERING_DRL_1_EVENT, - [STEERING_DIGITAL_INPUT_DRL_2] = STEERING_DRL_2_EVENT, [STEERING_DIGITAL_INPUT_REGEN_BRAKE_TOGGLE] = STEERING_REGEN_BRAKE_EVENT, [STEERING_DIGITAL_INPUT_CC_TOGGLE] = STEERING_DIGITAL_INPUT_CC_TOGGLE_PRESSED_EVENT, [STEERING_DIGITAL_INPUT_CC_INCREASE_SPEED] = STEERING_CC_INCREASE_SPEED_EVENT, diff --git a/projects/steering/test/test_control_stalk.c b/projects/steering/test/test_control_stalk.c index 01250baf4..b6a90faa9 100644 --- a/projects/steering/test/test_control_stalk.c +++ b/projects/steering/test/test_control_stalk.c @@ -34,6 +34,13 @@ static CanStorage s_can_storage; static int count = 0; +StatusCode prv_test_high_beam_rx_cb_handler(const CanMessage *msg, void *context, + CanAckStatus *ack_reply) { + TEST_ASSERT_EQUAL(SYSTEM_CAN_MESSAGE_LIGHTS, msg->msg_id); + count++; + return STATUS_CODE_OK; +} + StatusCode prv_test_signal_rx_cb_handler(const CanMessage *msg, void *context, CanAckStatus *ack_reply) { TEST_ASSERT_EQUAL(SYSTEM_CAN_MESSAGE_LIGHTS, msg->msg_id); @@ -68,6 +75,34 @@ void test_control_stalk_left_signal() { TEST_ASSERT_EQUAL(1, count); } +void test_drl() { + TEST_ASSERT_OK( + can_register_rx_handler(SYSTEM_CAN_MESSAGE_LIGHTS, prv_test_high_beam_rx_cb_handler, NULL)); + // Manually call the callback function with DRL_SIGNAL voltage + drl_on_callback(DRL_SIGNAL_VOLTAGE_MV, PERIODIC_READER_ID_1, NULL); + Event e = { 0 }; + MS_TEST_HELPER_ASSERT_NEXT_EVENT(e, (EventId)STEERING_DRL_ON_EVENT, + (uint16_t)DRL_SIGNAL_VOLTAGE_MV); + MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); + TEST_ASSERT_OK(steering_can_process_event(&e)); + MS_TEST_HELPER_CAN_TX_RX(STEERING_CAN_EVENT_TX, STEERING_CAN_EVENT_RX); + TEST_ASSERT_EQUAL(2, count); + + // Manually call the callback function with 0 voltage + drl_on_callback(0, PERIODIC_READER_ID_1, NULL); + MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); + TEST_ASSERT_EQUAL(2, count); + + // Manually call the callback function with DRL_SIGNAL voltage + drl_off_callback(DRL_SIGNAL_VOLTAGE_MV, PERIODIC_READER_ID_2, NULL); + MS_TEST_HELPER_ASSERT_NEXT_EVENT(e, (EventId)STEERING_DRL_OFF_EVENT, + (uint16_t)DRL_SIGNAL_VOLTAGE_MV); + MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); + TEST_ASSERT_OK(steering_can_process_event(&e)); + MS_TEST_HELPER_CAN_TX_RX(STEERING_CAN_EVENT_TX, STEERING_CAN_EVENT_RX); + TEST_ASSERT_EQUAL(3, count); +} + void test_control_stalk_right_signal_with_simultaneous_calls() { TEST_ASSERT_OK( can_register_rx_handler(SYSTEM_CAN_MESSAGE_LIGHTS, prv_test_signal_rx_cb_handler, NULL)); @@ -85,7 +120,7 @@ void test_control_stalk_right_signal_with_simultaneous_calls() { MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); TEST_ASSERT_OK(steering_can_process_event(&e)); MS_TEST_HELPER_CAN_TX_RX(STEERING_CAN_EVENT_TX, STEERING_CAN_EVENT_RX); - TEST_ASSERT_EQUAL(2, count); + TEST_ASSERT_EQUAL(4, count); } void test_invalid_voltage() { diff --git a/projects/steering/test/test_steering_digital_input.c b/projects/steering/test/test_steering_digital_input.c index 865199d8b..c8a36a196 100644 --- a/projects/steering/test/test_steering_digital_input.c +++ b/projects/steering/test/test_steering_digital_input.c @@ -36,13 +36,6 @@ StatusCode prv_test_horn_rx_cb_handler(const CanMessage *msg, void *context, return STATUS_CODE_OK; } -StatusCode prv_test_high_beam_rx_cb_handler(const CanMessage *msg, void *context, - CanAckStatus *ack_reply) { - TEST_ASSERT_EQUAL(SYSTEM_CAN_MESSAGE_LIGHTS, msg->msg_id); - count++; - return STATUS_CODE_OK; -} - StatusCode prv_test_cc_toggle_rx_cb_handler(const CanMessage *msg, void *context, CanAckStatus *ack_reply) { TEST_ASSERT_EQUAL(SYSTEM_CAN_MESSAGE_CRUISE_CONTROL_COMMAND, msg->msg_id); @@ -73,19 +66,6 @@ void test_steering_digital_input_horn() { TEST_ASSERT_EQUAL(1, count); } -void test_steering_digital_input_drl_1() { - TEST_ASSERT_OK( - can_register_rx_handler(SYSTEM_CAN_MESSAGE_LIGHTS, prv_test_high_beam_rx_cb_handler, NULL)); - GpioAddress drl_1_address = DRL_1_GPIO_ADDR; - TEST_ASSERT_OK(gpio_it_trigger_interrupt(&drl_1_address)); - Event e = { 0 }; - MS_TEST_HELPER_ASSERT_NEXT_EVENT(e, (EventId)STEERING_DRL_1_EVENT, (uint16_t)GPIO_STATE_LOW); - MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); - TEST_ASSERT_OK(steering_can_process_event(&e)); - MS_TEST_HELPER_CAN_TX_RX(STEERING_CAN_EVENT_TX, STEERING_CAN_EVENT_RX); - TEST_ASSERT_EQUAL(2, count); -} - void test_steering_digital_input_cc_toggle() { TEST_ASSERT_OK(can_register_rx_handler(SYSTEM_CAN_MESSAGE_CRUISE_CONTROL_COMMAND, prv_test_cc_toggle_rx_cb_handler, NULL)); @@ -97,7 +77,7 @@ void test_steering_digital_input_cc_toggle() { MS_TEST_HELPER_ASSERT_NO_EVENT_RAISED(); TEST_ASSERT_OK(steering_can_process_event(&e)); MS_TEST_HELPER_CAN_TX_RX(STEERING_CAN_EVENT_TX, STEERING_CAN_EVENT_RX); - TEST_ASSERT_EQUAL(3, count); + TEST_ASSERT_EQUAL(2, count); } void test_invalid_can_message() {