/* * Copyright 2019 Microchip Technology Inc. and its subsidiaries * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #define _GNU_SOURCE #ifndef AFB_BINDING_VERSION # define AFB_BINDING_VERSION 3 #endif #include #include #include #include #include "wrap-unicens.h" #include "microphone.h" /***************************************************************************** * types */ enum microphone_mode { MICROPHONE_MODE_NONE = 0, MICROPHONE_MODE_DOA = 1, MICROPHONE_MODE_THINKING = 2, MICROPHONE_MODE_SPEAKING = 3, MICROPHONE_MODE_ERROR = 4, MICROPHONE_MODE_WAKING = 5, MICROPHONE_MODE_ENDING = 6, MICROPHONE_MODE_CYLON = 7, MICROPHONE_MODE_RAINBOW = 8, MICROPHONE_MODE_WHEEL = 9, MICROPHONE_MODE_UNKNOWN = 10 }; /***************************************************************************** * local prototypes */ static int microphone_mode_set(enum microphone_mode mode); static int microphone_doa_get(void); static void microphone_doa_status(uint16_t data_sz, uint8_t *data_ptr); /***************************************************************************** * local variables and definitions */ #define NODE_ID ((uint16_t)0x520U) #define MSG_ID_MODE 0x1001U #define MSG_ID_DOA 0x1003U #define MSG_OP_SET 0x00U #define MSG_OP_GET 0x01U #define MSG_MAX_PAYLOAD_SZ 2U static uint8_t _tx_payload[MSG_MAX_PAYLOAD_SZ]; static bool _available = false; static bool _doa_running = false; static afb_req_t _req_doa_get = NULL; /***************************************************************************** * functions */ extern void microphone_availablility_changed(uint16_t node_id, bool available) { if (node_id == NODE_ID) { AFB_API_DEBUG(afbBindingRoot, "%s: amplifier new availability=%d", __func__, available); _available = available; _doa_running = false; } } extern void microphone_message_received(uint16_t node, uint16_t msg_id, uint16_t data_sz, uint8_t *data_ptr) { if (node != NODE_ID) { return; } switch (msg_id) { case MSG_ID_DOA: microphone_doa_status(data_sz, data_ptr); break; default: AFB_API_NOTICE(afbBindingRoot, "microphone_message_received node=%d, msg_id=%d, data_sz=%d", node, msg_id, data_sz); break; } } static int microphone_mode_set(enum microphone_mode mode) { AFB_API_NOTICE(afbBindingRoot, "microphone_mode_set value=%d", mode); if (_available == false) { AFB_API_NOTICE(afbBindingRoot, "%s: node is not available", __func__); return -1; } if (mode < MICROPHONE_MODE_UNKNOWN) { _tx_payload[0] = MSG_OP_SET; _tx_payload[1] = (uint8_t)mode; wrap_ucs_sendmessage_sync(NODE_ID, MSG_ID_MODE, _tx_payload, MSG_MAX_PAYLOAD_SZ); } else { AFB_API_NOTICE(afbBindingRoot, "%s: given mode is unknown", __func__); return -1; } return 0; } static int microphone_doa_get(void) { AFB_API_NOTICE(afbBindingRoot, "microphone_doa_get started"); if (_available == false) { AFB_API_NOTICE(afbBindingRoot, "%s: node is not available", __func__); return -1; } if (_doa_running) { AFB_API_NOTICE(afbBindingRoot, "%s: request is still running", __func__); return -2; } _tx_payload[0] = MSG_OP_GET; wrap_ucs_sendmessage_sync(NODE_ID, MSG_ID_DOA, _tx_payload, 1U); return 0; } static void microphone_doa_status(uint16_t data_sz, uint8_t *data_ptr) { uint16_t angle = 0U; if ((data_sz == 3U) && (data_ptr[0] == 0x0CU)) { angle = (uint16_t)((uint16_t)data_ptr[1] << 8 | (uint16_t)data_ptr[2]); AFB_API_NOTICE(afbBindingRoot, "microphone_doa_status: angle=%d", angle); if (_req_doa_get != NULL) { struct json_object* j_resp; j_resp = json_object_new_object(); wrap_json_pack(&j_resp, "{s:i}", "value", angle); afb_req_reply(_req_doa_get, j_resp, NULL, "response successful"); afb_req_unref(_req_doa_get); _req_doa_get = NULL; } } } /***************************************************************************** * JSON API */ extern void microphone_mode_set_api(afb_req_t request) { char *str_mode = NULL; struct json_object* j_obj = afb_req_json(request); AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: %s:%s", __func__, json_object_get_string(j_obj)); if (wrap_json_unpack(j_obj, "{s:s}", "value", &str_mode) == 0) { AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: decoded value=%s", str_mode); enum microphone_mode mic_mode = MICROPHONE_MODE_UNKNOWN; if (strcmp(str_mode, "none") == 0) { mic_mode = MICROPHONE_MODE_NONE; } else if (strcmp(str_mode, "doa") == 0) { mic_mode = MICROPHONE_MODE_DOA; } else if (strcmp(str_mode, "thinking") == 0) { mic_mode = MICROPHONE_MODE_THINKING; } else if (strcmp(str_mode, "speaking") == 0) { mic_mode = MICROPHONE_MODE_SPEAKING; } else if (strcmp(str_mode, "error") == 0) { mic_mode = MICROPHONE_MODE_ERROR; } else if (strcmp(str_mode, "waking") == 0) { mic_mode = MICROPHONE_MODE_WAKING; } else if (strcmp(str_mode, "ending") == 0) { mic_mode = MICROPHONE_MODE_ENDING; } else if (strcmp(str_mode, "cylon") == 0) { mic_mode = MICROPHONE_MODE_CYLON; } else if (strcmp(str_mode, "rainbow") == 0) { mic_mode = MICROPHONE_MODE_RAINBOW; } else if (strcmp(str_mode, "wheel") == 0) { mic_mode = MICROPHONE_MODE_WHEEL; } if (mic_mode < MICROPHONE_MODE_UNKNOWN) { microphone_mode_set(mic_mode); afb_req_success(request, NULL, NULL); } else { afb_req_fail(request, "argument 'value' is not set to a known value", NULL); } } else { afb_req_fail(request, "missing argument 'value'", NULL); } } extern void microphone_doa_get_api(afb_req_t request) { struct json_object* j_obj = afb_req_json(request); if (microphone_doa_get() != 0) { AFB_API_NOTICE(afbBindingRoot, "function call failed: %s:%s", __func__, json_object_get_string(j_obj)); afb_req_fail(request, "function call failed", NULL); } else { _req_doa_get = afb_req_addref(request); } }