summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTobias Jahnke <tobias.jahnke@microchip.com>2019-10-15 15:14:30 +0200
committerTobias Jahnke <tobias.jahnke@microchip.com>2019-10-16 06:11:37 +0000
commite91eaa18befd14446d280311c9bd5c05f29801f0 (patch)
treec8921df433cacd724a7ade71f74be2aa962adff0
parent6854f72cb81b10e1add164e754aba1952df5b269 (diff)
unicens-controller: add DOA feature
Introduce a new API to retrieve the current direction of audio (DOA) recognized by the microphone. Bug-AGL: SPEC-2899 Signed-off-by: Tobias Jahnke <tobias.jahnke@microchip.com> Change-Id: I387efaeaf0cffd06b3d88efbeeaf2ef7eb23c780
-rw-r--r--README.md8
-rw-r--r--binding/binding.c7
-rw-r--r--binding/microphone/microphone.c71
-rw-r--r--binding/microphone/microphone.h2
-rw-r--r--binding/wrap-unicens/wrap-unicens.c50
-rw-r--r--binding/wrap-unicens/wrap-unicens.h3
-rw-r--r--htdocs/ucs-controller.html7
7 files changed, 143 insertions, 5 deletions
diff --git a/README.md b/README.md
index aeeac99..6fdd75d 100644
--- a/README.md
+++ b/README.md
@@ -9,10 +9,10 @@ The name of the provided API is `unicens-controller`.
## Verbs
| Name | Description | JSON Parameters |
|-----------------------------|-----------------------------------------------|-------------------------------------------------------------------|
-| slimamp_master_volume_set | Set master volume of the slim amplifer. | *Request:* { "value": 0 } <br>Valid range for `value`: 0..100 |
-| amplifier_master_volume_set | Set master volume of the Fiberdyne amplifer. | *Request:* { "value": 0 } <br>Valid range for `value`: 0..100 |
-| microphone_mode_set | Set LED mode of microphone | See section *Verb microphone_mode_set* |
-
+| slimamp_master_volume_set | Set master volume of the slim amplifer. | *Request:* { "value": 0 }<br>Valid range for `value`: 0..100 |
+| amplifier_master_volume_set | Set master volume of the Fiberdyne amplifer. | *Request:* { "value": 0 }<br>Valid range for `value`: 0..100 |
+| microphone_mode_set | Set LED mode of microphone. | See section *Verb microphone_mode_set* |
+| microphone_doa_get | Get the direction of audio. | *Request:* {}<br>*Response*: { "value": 45 }<br>Valid range for `value`: 0..359 |
### Verb microphone_mode_set
You can set an LED signaling mode with the following parameters.
diff --git a/binding/binding.c b/binding/binding.c
index cebc54a..1d19fdb 100644
--- a/binding/binding.c
+++ b/binding/binding.c
@@ -38,6 +38,7 @@ static int init(afb_api_t api) {
AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: INIT");
wrap_ucs_init(api);
wrap_ucs_subscribe_sync();
+ wrap_ucs_subscriberx_sync();
return 0;
}
@@ -47,10 +48,15 @@ static void on_availability_cb(uint16_t node, bool available) {
microphone_availablility_changed(node, available);
}
+static void on_message_rx_cb(uint16_t node, uint16_t msg_id, uint16_t data_sz, uint8_t *data_ptr) {
+ microphone_message_received(node, msg_id, data_sz, data_ptr);
+}
+
/* callback for handling events */
static void onevent(afb_api_t api, const char *event, struct json_object *object) {
AFB_API_NOTICE(afbBindingRoot, "UNICENS-CONTROLLER: Event: %s object: %s", event, json_object_get_string(object));
wrap_ucs_interpret_event(event, object, &on_availability_cb);
+ wrap_ucs_interpretrx_event(event, object, &on_message_rx_cb);
}
static void ping(afb_req_t request) {
@@ -63,6 +69,7 @@ static const afb_verb_t verbs[] = {
{.verb = "slimamp_master_volume_set", .session = AFB_SESSION_NONE, .callback = slimamp_master_vol_set_api, .auth = NULL},
{.verb = "amplifier_master_volume_set", .session = AFB_SESSION_NONE, .callback = amplifier_master_vol_set_api, .auth = NULL},
{.verb = "microphone_mode_set", .session = AFB_SESSION_NONE, .callback = microphone_mode_set_api, .auth = NULL},
+ {.verb = "microphone_doa_get", .session = AFB_SESSION_NONE, .callback = microphone_doa_get_api, .auth = NULL},
{NULL}
};
diff --git a/binding/microphone/microphone.c b/binding/microphone/microphone.c
index dc43cd3..344fbd7 100644
--- a/binding/microphone/microphone.c
+++ b/binding/microphone/microphone.c
@@ -49,6 +49,8 @@ enum microphone_mode
*/
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
@@ -56,11 +58,15 @@ static int microphone_mode_set(enum microphone_mode mode);
#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
@@ -70,6 +76,23 @@ 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;
}
}
@@ -93,6 +116,40 @@ static int microphone_mode_set(enum microphone_mode mode) {
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
@@ -150,4 +207,16 @@ extern void microphone_mode_set_api(afb_req_t request) {
else {
afb_req_fail(request, "missing argument 'value'", NULL);
}
-} \ No newline at end of file
+}
+
+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);
+ }
+}
diff --git a/binding/microphone/microphone.h b/binding/microphone/microphone.h
index 01fbcb2..27ee4ea 100644
--- a/binding/microphone/microphone.h
+++ b/binding/microphone/microphone.h
@@ -22,5 +22,7 @@
/* notification */
extern void microphone_availablility_changed(uint16_t node_id, bool available);
+extern void microphone_message_received(uint16_t node, uint16_t msg_id, uint16_t data_sz, uint8_t *data_ptr);
/* JSON API */
extern void microphone_mode_set_api(afb_req_t request);
+extern void microphone_doa_get_api(afb_req_t request);
diff --git a/binding/wrap-unicens/wrap-unicens.c b/binding/wrap-unicens/wrap-unicens.c
index e5d4570..84b94cd 100644
--- a/binding/wrap-unicens/wrap-unicens.c
+++ b/binding/wrap-unicens/wrap-unicens.c
@@ -66,6 +66,56 @@ extern int wrap_ucs_subscribe_sync(void) {
return 0;
}
+/*
+ * Subscribes to unicens2-binding RX message events.
+ * \return Returns 0 if successful, otherwise != 0".
+ */
+extern int wrap_ucs_subscriberx_sync(void) {
+ int err;
+
+ json_object *j_response, *j_query = NULL;
+ char *error, *info;
+
+ /* Build an empty JSON object */
+ if((err = wrap_json_pack(&j_query, "{}"))) {
+ AFB_API_ERROR(api_handle_, "Failed to create subscribe RX json object");
+ return err;
+ }
+
+ if((err = afb_api_call_sync(api_handle_, "UNICENS", "subscriberx", j_query, &j_response, &error, &info))) {
+ AFB_API_ERROR(api_handle_, "Fail subscribing to UNICENS RX events");
+ return err;
+ }
+ else {
+ AFB_API_NOTICE(api_handle_, "Subscribed to UNICENS RX events, res=%s", json_object_to_json_string(j_response));
+ json_object_put(j_response);
+ }
+
+ return 0;
+}
+
+extern int wrap_ucs_interpretrx_event(const char *event, struct json_object *object, wrap_ucs_rx_message_cb_t callback) {
+ int node_id = 0;
+ int msg_id = 0;
+ uint8_t *data_ptr = NULL;
+ size_t data_sz = 0;
+
+ if (strcmp(event, "UNICENS/rx-message") != 0) {
+ return -1; // unhandled event
+ }
+
+ if (wrap_json_unpack(object, "{s:i, s:i, s?Y}", "node", &node_id, "msgid", &msg_id, "data", &data_ptr, &data_sz) != 0) {
+ AFB_API_NOTICE(api_handle_, "Parsing rx-message failed.");
+ return -2;
+ }
+
+ if (callback != NULL) {
+ callback((uint16_t)node_id, (uint16_t)msg_id, (uint16_t)data_sz, data_ptr);
+ }
+
+ return 0;
+}
+
extern int wrap_ucs_interpret_event(const char *event, struct json_object *object, wrap_ucs_availability_cb_t callback) {
int node_id = 0;
int available = false;
diff --git a/binding/wrap-unicens/wrap-unicens.h b/binding/wrap-unicens/wrap-unicens.h
index a6e2f43..781f6cc 100644
--- a/binding/wrap-unicens/wrap-unicens.h
+++ b/binding/wrap-unicens/wrap-unicens.h
@@ -28,6 +28,7 @@ extern int wrap_ucs_init(afb_api_t apiHandle);
/* Asynchronous API: result callback */
typedef void (*wrap_ucs_availability_cb_t)(uint16_t node, bool available);
+typedef void (*wrap_ucs_rx_message_cb_t)(uint16_t node, uint16_t msg_id, uint16_t data_sz, uint8_t *data_ptr);
typedef void (*wrap_ucs_result_cb_t)(uint8_t result, void *user_ptr);
/* Asynchronous API: functions */
@@ -39,6 +40,8 @@ extern int wrap_ucs_i2cwrite(uint16_t node,
/* Synchronous API: functions */
extern int wrap_ucs_subscribe_sync(void);
+extern int wrap_ucs_subscriberx_sync(void);
extern int wrap_ucs_interpret_event(const char *event, struct json_object *object, wrap_ucs_availability_cb_t callback);
+extern int wrap_ucs_interpretrx_event(const char *event, struct json_object *object, wrap_ucs_rx_message_cb_t callback);
extern int wrap_ucs_i2cwrite_sync(uint16_t node, uint8_t *data_ptr, uint8_t data_sz);
extern int wrap_ucs_sendmessage_sync(uint16_t src_addr, uint16_t msg_id, uint8_t *data_ptr, uint8_t data_sz);
diff --git a/htdocs/ucs-controller.html b/htdocs/ucs-controller.html
index f1b9ed8..0de6c57 100644
--- a/htdocs/ucs-controller.html
+++ b/htdocs/ucs-controller.html
@@ -98,6 +98,13 @@ limitations under the License.
<li><button onclick="callbinder('unicens-controller','microphone_mode_set', {'value': 'unknown'})">Unknown</button></li>
</ol>
</div>
+
+ <h3>DOA</h3>
+ <div>
+ <ol>
+ <li><button onclick="callbinder('unicens-controller','microphone_doa_get', {})">Get direction of audio (DOA)</button></li>
+ </ol>
+ </div>
<h1>Events</h1>
<br>