1 /*
2 * Copyright (c) 2022 Rodrigo Peixoto <rodrigopex@gmail.com>
3 * SPDX-License-Identifier: Apache-2.0
4 */
5 #include "messages.h"
6
7 #include <stdint.h>
8 #include <string.h>
9
10 #include <zephyr/drivers/uart.h>
11 #include <zephyr/kernel.h>
12 #include <zephyr/logging/log.h>
13 #include <zephyr/net/buf.h>
14 #include <zephyr/zbus/zbus.h>
15 LOG_MODULE_DECLARE(zbus, CONFIG_ZBUS_LOG_LEVEL);
16
17 const static struct device *uart_dev = DEVICE_DT_GET(DT_NODELABEL(uart1));
18
19 ZBUS_CHAN_DECLARE(sensor_data_chan);
20
21 ZBUS_CHAN_DEFINE(version_chan, /* Name */
22 struct version_msg, /* Message type */
23
24 NULL, /* Validator */
25 NULL, /* User data */
26 ZBUS_OBSERVERS_EMPTY, /* observers */
27 ZBUS_MSG_INIT(.major = 0, .minor = 1,
28 .build = 1023) /* Initial value major 0, minor 1, build 1023 */
29 );
30
31 static bool start_measurement_from_bridge;
32 ZBUS_CHAN_DEFINE(start_measurement_chan, /* Name */
33 struct action_msg, /* Message type */
34
35 NULL, /* Validator */
36 &start_measurement_from_bridge, /* User data */
37 ZBUS_OBSERVERS(proxy_lis, peripheral_sub), /* observers */
38 ZBUS_MSG_INIT(false) /* Initial value */
39 );
40
encoder(const struct zbus_channel * chan)41 static uint8_t encoder(const struct zbus_channel *chan)
42 {
43 if (chan == &sensor_data_chan) {
44 return 1;
45 } else if (chan == &start_measurement_chan) {
46 return 2;
47 }
48 return 0;
49 }
50
decoder(uint8_t chan_idx)51 static const struct zbus_channel *decoder(uint8_t chan_idx)
52 {
53 if (chan_idx == 1) {
54 return &sensor_data_chan;
55 } else if (chan_idx == 2) {
56 return &start_measurement_chan;
57 }
58 return NULL;
59 }
60
proxy_callback(const struct zbus_channel * chan)61 static void proxy_callback(const struct zbus_channel *chan)
62 {
63 bool *generated_by_the_bridge = zbus_chan_user_data(chan);
64
65 if (*generated_by_the_bridge) {
66 LOG_DBG("discard loopback event (channel %s)", zbus_chan_name(chan));
67
68 *generated_by_the_bridge = false;
69 } else {
70 uart_poll_out(uart_dev, '$');
71
72 uart_poll_out(uart_dev, encoder(chan));
73
74 for (int i = 0; i < zbus_chan_msg_size(chan); ++i) {
75 uart_poll_out(uart_dev, ((unsigned char *)zbus_chan_const_msg(chan))[i]);
76 }
77
78 uart_poll_out(uart_dev, '*');
79
80 LOG_DBG("sending message to host (channel %s)", zbus_chan_name(chan));
81 }
82 }
83
84 ZBUS_LISTENER_DEFINE(proxy_lis, proxy_callback);
85
main(void)86 int main(void)
87 {
88 LOG_DBG("[Mock Proxy] Started.");
89 return 0;
90 }
91
decode_sentence(struct net_buf_simple * rx_buf)92 static void decode_sentence(struct net_buf_simple *rx_buf)
93 {
94 if (rx_buf->len <= 1) {
95 LOG_DBG("[Mock Proxy RX] Discard invalid sequence");
96 /* '*' indicates the end of a sentence. Sometimes it is
97 * necessary to flush more than on ensure sending it from
98 * the python script. The code must discard when there is no
99 * other data at the buffer.
100 */
101 } else {
102 if ('$' == net_buf_simple_pull_u8(rx_buf)) {
103 LOG_DBG("[Mock Proxy RX] Found sentence");
104
105 const struct zbus_channel *chan = decoder(net_buf_simple_pull_u8(rx_buf));
106
107 __ASSERT_NO_MSG(chan != NULL);
108
109 if (!zbus_chan_claim(chan, K_MSEC(250))) {
110 memcpy(zbus_chan_msg(chan),
111 net_buf_simple_pull_mem(rx_buf, zbus_chan_msg_size(chan)),
112 zbus_chan_msg_size(chan));
113
114 bool *generated_by_the_bridge = zbus_chan_user_data(chan);
115 *generated_by_the_bridge = true;
116
117 zbus_chan_finish(chan);
118
119 LOG_DBG("Publishing channel %s", zbus_chan_name(chan));
120
121 zbus_chan_notify(chan, K_MSEC(500));
122 }
123 }
124 net_buf_simple_init(rx_buf, 0);
125 }
126 }
127
mock_proxy_rx_thread(void)128 static void mock_proxy_rx_thread(void)
129 {
130 LOG_DBG("[Mock Proxy RX] Started.");
131
132 uint8_t byte;
133 struct net_buf_simple *rx_buf = NET_BUF_SIMPLE(64);
134
135 net_buf_simple_init(rx_buf, 0);
136
137 while (1) {
138 while (uart_poll_in(uart_dev, &byte) < 0) {
139 /* Allow other thread/workqueue to work. */
140 k_msleep(50);
141 }
142 if (byte == '*') {
143 decode_sentence(rx_buf);
144 } else {
145 net_buf_simple_add_u8(rx_buf, byte);
146 }
147 }
148 }
149
150 K_THREAD_DEFINE(mock_proxy_rx_thread_tid, 2048, mock_proxy_rx_thread, NULL, NULL, NULL, 5, 0, 1500);
151