mirror of
https://github.com/korneliuszo/lumiax-controller.git
synced 2026-06-27 13:31:15 +02:00
Initial commit
This commit is contained in:
@@ -0,0 +1,549 @@
|
||||
/*
|
||||
* bt.cpp
|
||||
*
|
||||
* Created on: Aug 16, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
#define DT_DRV_COMPAT barrot_serial
|
||||
|
||||
#include <zephyr/kernel.h>
|
||||
#include <zephyr/arch/cpu.h>
|
||||
#include <zephyr/init.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/types.h>
|
||||
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/bluetooth/conn.h>
|
||||
#include <zephyr/bluetooth/gatt.h>
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/sys/util.h>
|
||||
|
||||
#include "printt.h"
|
||||
|
||||
|
||||
struct uart_barrot_device_config {
|
||||
bt_addr_t btaddr;
|
||||
};
|
||||
|
||||
static const struct bt_uuid_16 ccc_uuid = BT_UUID_INIT_16(BT_UUID_GATT_CCC_VAL);
|
||||
|
||||
#define TX_TMP_BUFF_LEN 20
|
||||
|
||||
struct uart_barrot_data {
|
||||
uart_irq_callback_user_data_t irq_cb;
|
||||
void *irq_user_data;
|
||||
const struct device *dev;
|
||||
struct bt_conn *conn_connected;
|
||||
struct notifier_state {
|
||||
atomic_t state;
|
||||
struct bt_gatt_subscribe_params subscribe_params;
|
||||
struct bt_gatt_discover_params discover_params;
|
||||
struct bt_uuid_16 uuid;
|
||||
bt_gatt_notify_func_t notifier;
|
||||
}tx,rx;
|
||||
struct bt_gatt_discover_params tx_w_discover_params;
|
||||
uint16_t tx_w_handle;
|
||||
struct bt_uuid_16 tx_w_uuid;
|
||||
uint8_t initial_credit;
|
||||
uint8_t credit;
|
||||
const uint8_t* rxptr;
|
||||
uint8_t rxlen;
|
||||
struct k_mutex irq_mutex;
|
||||
uint8_t tx_tmp_buff[TX_TMP_BUFF_LEN];
|
||||
uint8_t tx_tmp_buff_cnt;
|
||||
bool tx_updated;
|
||||
struct bt_gatt_exchange_params mtu_exchange_params;
|
||||
};
|
||||
|
||||
static struct uart_barrot_data uart_barrot_data_0 = {};
|
||||
|
||||
static const struct uart_barrot_device_config uart_barrot_dev_cfg_0 = {
|
||||
.btaddr = {DT_INST_PROP(0, btaddr)},
|
||||
};
|
||||
|
||||
static void run_tx()
|
||||
{
|
||||
k_mutex_lock(&uart_barrot_data_0.irq_mutex, K_FOREVER);
|
||||
uart_barrot_data_0.tx_tmp_buff_cnt = 0;
|
||||
|
||||
do
|
||||
{
|
||||
uart_barrot_data_0.tx_updated=0;
|
||||
uart_barrot_data_0.irq_cb(uart_barrot_data_0.dev,
|
||||
uart_barrot_data_0.irq_user_data);
|
||||
}while(uart_barrot_data_0.tx_updated);
|
||||
|
||||
struct bt_conn *conn = NULL;
|
||||
|
||||
struct bt_conn *conn_cache = uart_barrot_data_0.conn_connected;
|
||||
|
||||
if (conn_cache) {
|
||||
/* Get a connection reference to ensure that a
|
||||
* reference is maintained in case disconnected
|
||||
* callback is called while we perform GATT Write
|
||||
* command.
|
||||
*/
|
||||
conn = bt_conn_ref(conn_cache);
|
||||
}
|
||||
|
||||
if (conn) {
|
||||
if(uart_barrot_data_0.tx_tmp_buff_cnt){
|
||||
uart_barrot_data_0.credit -= 1;
|
||||
bt_gatt_write_without_response(conn,uart_barrot_data_0.tx_w_handle,
|
||||
uart_barrot_data_0.tx_tmp_buff,
|
||||
uart_barrot_data_0.tx_tmp_buff_cnt,
|
||||
false);
|
||||
//printt("TXING %d",uart_barrot_data_0.tx_tmp_buff_cnt);
|
||||
}
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
uart_barrot_data_0.tx_tmp_buff_cnt = 0;
|
||||
k_mutex_unlock(&uart_barrot_data_0.irq_mutex);
|
||||
return;
|
||||
}
|
||||
|
||||
static void device_found(const bt_addr_le_t *addr, int8_t rssi, uint8_t type,
|
||||
struct net_buf_simple *ad)
|
||||
{
|
||||
|
||||
char dev[BT_ADDR_LE_STR_LEN];
|
||||
|
||||
bt_addr_le_to_str(addr, dev, sizeof(dev));
|
||||
printt("[DEVICE]: %s, AD evt type %u, AD data len %u, RSSI %i",
|
||||
dev, type, ad->len, rssi);
|
||||
|
||||
/* We're only interested in connectable events */
|
||||
if (type != BT_GAP_ADV_TYPE_ADV_IND &&
|
||||
type != BT_GAP_ADV_TYPE_ADV_DIRECT_IND) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* connect only to devices in close proximity */
|
||||
/*if (rssi < -70) {
|
||||
return;
|
||||
}*/
|
||||
bt_addr_le_t target_mac = {};
|
||||
target_mac.type = BT_ADDR_LE_PUBLIC;
|
||||
target_mac.a = uart_barrot_dev_cfg_0.btaddr;
|
||||
if(memcmp(&target_mac,addr,sizeof(bt_addr_le_t))!=0)
|
||||
return;
|
||||
|
||||
int err;
|
||||
|
||||
err = bt_le_scan_stop();
|
||||
if (err) {
|
||||
printt("%s: Stop LE scan failed (err %d)\n", __func__, err);
|
||||
return;
|
||||
}
|
||||
|
||||
struct bt_conn *conn;
|
||||
|
||||
err = bt_conn_le_create(addr, BT_CONN_LE_CREATE_CONN,
|
||||
BT_LE_CONN_PARAM_DEFAULT, &conn);
|
||||
if (err) {
|
||||
bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
|
||||
} else {
|
||||
bt_conn_unref(conn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static uint8_t notify_tx_func(struct bt_conn *conn,
|
||||
struct bt_gatt_subscribe_params *params,
|
||||
const void *data, uint16_t length)
|
||||
{
|
||||
struct notifier_state *state = CONTAINER_OF(params,struct notifier_state,subscribe_params);
|
||||
if (!data) {
|
||||
printt("[UNSUBSCRIBED] %u", params->ccc_handle);
|
||||
atomic_clear_bit(&state->state,0);
|
||||
params->value_handle = 0U;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
//printt("[NOTIFICATION_TX] data %p length %u", data, length);
|
||||
|
||||
struct uart_barrot_data *uart_data = CONTAINER_OF(state,struct uart_barrot_data,tx);
|
||||
|
||||
uint8_t * d = (uint8_t *)data;
|
||||
|
||||
if(length == 2 && d[0] == 0x01)
|
||||
{
|
||||
if(!uart_data->initial_credit)
|
||||
{
|
||||
uart_data->initial_credit = d[1];
|
||||
uart_data->credit = d[1];
|
||||
}
|
||||
else
|
||||
uart_data->credit += d[1];
|
||||
//printt("New credit %d",uart_data->credit);
|
||||
}
|
||||
if(uart_data->credit)
|
||||
{
|
||||
run_tx();
|
||||
}
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static uint8_t notify_rx_func(struct bt_conn *conn,
|
||||
struct bt_gatt_subscribe_params *params,
|
||||
const void *data, uint16_t length)
|
||||
{
|
||||
struct notifier_state *state = CONTAINER_OF(params,struct notifier_state,subscribe_params);
|
||||
if (!data) {
|
||||
printt("[UNSUBSCRIBED] %u", params->ccc_handle);
|
||||
atomic_clear_bit(&state->state,0);
|
||||
params->value_handle = 0U;
|
||||
params->ccc_handle = 0;
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
//printt("[NOTIFICATION_RX] data %p length %u", data, length);
|
||||
|
||||
struct uart_barrot_data *uart_data = CONTAINER_OF(state,struct uart_barrot_data,rx);
|
||||
k_mutex_lock(&uart_data->irq_mutex, K_FOREVER);
|
||||
uart_data->rxptr = data;
|
||||
uart_data->rxlen = length;
|
||||
uart_barrot_data_0.irq_cb(uart_data->dev,uart_data->irq_user_data);
|
||||
uart_data->rxptr = NULL;
|
||||
k_mutex_unlock(&uart_data->irq_mutex);
|
||||
|
||||
|
||||
return BT_GATT_ITER_CONTINUE;
|
||||
}
|
||||
|
||||
static uint8_t discover_func(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params)
|
||||
{
|
||||
|
||||
struct notifier_state *state = CONTAINER_OF(params,struct notifier_state,discover_params);
|
||||
int err;
|
||||
|
||||
if (!attr) {
|
||||
printt("Discover complete\n");
|
||||
(void)memset(params, 0, sizeof(*params));
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
printt("[ATTRIBUTE] handle %u\n", attr->handle);
|
||||
printt("[ATTRIBUTE] perm %u\n", attr->perm);
|
||||
printt("[PARMMS] type %u\n", params->type);
|
||||
|
||||
if(params->type == BT_GATT_DISCOVER_CHARACTERISTIC)
|
||||
{
|
||||
params->uuid = &ccc_uuid.uuid;
|
||||
params->start_handle = attr->handle + 2;
|
||||
params->type = BT_GATT_DISCOVER_DESCRIPTOR;
|
||||
state->subscribe_params.value_handle = bt_gatt_attr_value_handle(attr);
|
||||
err = bt_gatt_discover(conn, params);
|
||||
if (err) {
|
||||
printt("Discover failed (err %d)\n", err);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
state->subscribe_params.value = BT_GATT_CCC_NOTIFY;
|
||||
state->subscribe_params.ccc_handle = attr->handle;
|
||||
state->subscribe_params.notify = state->notifier;
|
||||
err = bt_gatt_subscribe(conn, &state->subscribe_params);
|
||||
|
||||
if (err && err != -EALREADY) {
|
||||
printt("Subscribe failed (err %d)\n", err);
|
||||
} else {
|
||||
printt("[SUBSCRIBED]\n");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
static uint8_t discover_tx_w_func(struct bt_conn *conn,
|
||||
const struct bt_gatt_attr *attr,
|
||||
struct bt_gatt_discover_params *params)
|
||||
{
|
||||
|
||||
struct uart_barrot_data *data = CONTAINER_OF(params,struct uart_barrot_data,tx_w_discover_params);
|
||||
|
||||
if (!attr) {
|
||||
printt("Discover complete\n");
|
||||
(void)memset(params, 0, sizeof(*params));
|
||||
return BT_GATT_ITER_STOP;
|
||||
}
|
||||
|
||||
printt("[ATTRIBUTE] handle %u\n", attr->handle);
|
||||
printt("[ATTRIBUTE] perm %u\n", attr->perm);
|
||||
printt("[PARMMS] type %u\n", params->type);
|
||||
|
||||
data->tx_w_handle = bt_gatt_attr_value_handle(attr);
|
||||
|
||||
return BT_GATT_ITER_STOP;
|
||||
|
||||
}
|
||||
|
||||
|
||||
static void discoverer_start(struct bt_conn *conn, struct notifier_state * state)
|
||||
{
|
||||
state->discover_params.uuid = &state->uuid.uuid;
|
||||
|
||||
state->discover_params.func = discover_func;
|
||||
state->discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
|
||||
state->discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
|
||||
state->discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
|
||||
int err = bt_gatt_discover(conn, &state->discover_params);
|
||||
if (err) {
|
||||
printt("Discover failed(err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void mtu_exchange_cb(struct bt_conn *conn, uint8_t err,
|
||||
struct bt_gatt_exchange_params *params)
|
||||
{
|
||||
printt("%s: MTU exchange %s (%u)\n", __func__,
|
||||
err == 0U ? "successful" : "failed",
|
||||
bt_gatt_get_mtu(conn));
|
||||
|
||||
struct uart_barrot_data *data = CONTAINER_OF(params,struct uart_barrot_data,mtu_exchange_params);
|
||||
discoverer_start(conn, &data->rx);
|
||||
discoverer_start(conn, &data->tx);
|
||||
data->tx_w_discover_params.uuid = &data->tx_w_uuid.uuid;
|
||||
data->tx_w_discover_params.func = discover_tx_w_func;
|
||||
data->tx_w_discover_params.start_handle = BT_ATT_FIRST_ATTRIBUTE_HANDLE;
|
||||
data->tx_w_discover_params.end_handle = BT_ATT_LAST_ATTRIBUTE_HANDLE;
|
||||
data->tx_w_discover_params.type = BT_GATT_DISCOVER_CHARACTERISTIC;
|
||||
int err2 = bt_gatt_discover(conn, &data->tx_w_discover_params);
|
||||
if (err2) {
|
||||
printt("Discover failed(err %d)\n", err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
static void connected(struct bt_conn *conn, uint8_t conn_err)
|
||||
{
|
||||
struct bt_conn_info conn_info;
|
||||
int err;
|
||||
|
||||
if (conn_err) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_barrot_data_0.conn_connected = bt_conn_ref(conn);
|
||||
|
||||
err = bt_conn_get_info(conn, &conn_info);
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
printt("%s: Current MTU = %u\n", __func__, bt_gatt_get_mtu(conn));
|
||||
|
||||
uart_barrot_data_0.mtu_exchange_params.func = mtu_exchange_cb;
|
||||
|
||||
printt("%s: Exchange MTU...\n", __func__);
|
||||
err = bt_gatt_exchange_mtu(conn, &uart_barrot_data_0.mtu_exchange_params);
|
||||
if (err) {
|
||||
printt("%s: MTU exchange failed (err %d)", __func__, err);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void disconnected(struct bt_conn *conn, uint8_t reason)
|
||||
{
|
||||
struct bt_conn_info conn_info;
|
||||
int err;
|
||||
|
||||
err = bt_conn_get_info(conn, &conn_info);
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
|
||||
uart_barrot_data_0.conn_connected = NULL;
|
||||
|
||||
bt_conn_unref(conn);
|
||||
|
||||
uart_barrot_data_0.credit = 0;
|
||||
uart_barrot_data_0.tx_w_handle = 0;
|
||||
atomic_clear_bit(&uart_barrot_data_0.tx.state,0);
|
||||
atomic_clear_bit(&uart_barrot_data_0.rx.state,0);
|
||||
|
||||
if (conn_info.role == BT_CONN_ROLE_CENTRAL) {
|
||||
bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
|
||||
}
|
||||
}
|
||||
|
||||
BT_CONN_CB_DEFINE(conn_callbacks) = {
|
||||
.connected = connected,
|
||||
.disconnected = disconnected,
|
||||
};
|
||||
|
||||
static struct bt_gatt_cb gatt_callbacks = {
|
||||
};
|
||||
|
||||
void barrot_init()
|
||||
{
|
||||
|
||||
bt_gatt_cb_register(&gatt_callbacks);
|
||||
|
||||
bt_le_scan_start(BT_LE_SCAN_ACTIVE, device_found);
|
||||
return;
|
||||
}
|
||||
|
||||
static int barrot_configure(const struct device *dev,
|
||||
const struct uart_config *cfg)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void barrot_irq_tx_enable(const struct device *dev)
|
||||
{
|
||||
atomic_set_bit(&uart_barrot_data_0.tx.state,0);
|
||||
run_tx();
|
||||
}
|
||||
|
||||
static void barrot_irq_tx_disable(const struct device *dev)
|
||||
{
|
||||
atomic_clear_bit(&uart_barrot_data_0.tx.state,0);
|
||||
}
|
||||
|
||||
static void barrot_irq_rx_enable(const struct device *dev)
|
||||
{
|
||||
atomic_set_bit(&uart_barrot_data_0.rx.state,0);
|
||||
}
|
||||
|
||||
static void barrot_irq_rx_disable(const struct device *dev)
|
||||
{
|
||||
atomic_clear_bit(&uart_barrot_data_0.tx.state,0);
|
||||
}
|
||||
|
||||
static void barrot_irq_callback_set(const struct device *dev,
|
||||
uart_irq_callback_user_data_t cb,
|
||||
void *user_data)
|
||||
{
|
||||
struct uart_barrot_data *data;
|
||||
|
||||
data = dev->data;
|
||||
data->irq_cb = cb;
|
||||
data->irq_user_data = user_data;
|
||||
}
|
||||
|
||||
static int barrot_fifo_fill(const struct device *dev,
|
||||
const uint8_t *tx_data, int size)
|
||||
{
|
||||
if(!uart_barrot_data_0.tx_w_handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if(!uart_barrot_data_0.tx.subscribe_params.ccc_handle)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t i = MIN(size,
|
||||
TX_TMP_BUFF_LEN-uart_barrot_data_0.tx_tmp_buff_cnt);
|
||||
|
||||
memcpy(&uart_barrot_data_0.tx_tmp_buff[uart_barrot_data_0.tx_tmp_buff_cnt],
|
||||
tx_data,i);
|
||||
uart_barrot_data_0.tx_tmp_buff_cnt+=i;
|
||||
uart_barrot_data_0.tx_updated = 1;
|
||||
return i;
|
||||
}
|
||||
|
||||
static int barrot_fifo_read(const struct device *dev,
|
||||
uint8_t *rx_data, const int size)
|
||||
{
|
||||
int i=0;
|
||||
|
||||
if (!uart_barrot_data_0.rxptr)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
while(i<size && uart_barrot_data_0.rxlen)
|
||||
{
|
||||
rx_data[i++] = *(uart_barrot_data_0.rxptr++);
|
||||
uart_barrot_data_0.rxlen--;
|
||||
}
|
||||
return i;
|
||||
}
|
||||
|
||||
static int barrot_irq_tx_ready(const struct device *dev)
|
||||
{
|
||||
return atomic_test_bit(&uart_barrot_data_0.tx.state,0) &&
|
||||
(uart_barrot_data_0.tx_w_handle) &&
|
||||
(uart_barrot_data_0.tx.subscribe_params.ccc_handle) &&
|
||||
(TX_TMP_BUFF_LEN > uart_barrot_data_0.tx_tmp_buff_cnt);
|
||||
}
|
||||
|
||||
static int barrot_irq_rx_ready(const struct device *dev)
|
||||
{
|
||||
return atomic_test_bit(&uart_barrot_data_0.rx.state,0) &&
|
||||
(uart_barrot_data_0.rxptr) &&
|
||||
(uart_barrot_data_0.rxlen);
|
||||
}
|
||||
|
||||
int barrot_irq_tx_complete(const struct device *dev)
|
||||
{
|
||||
return uart_barrot_data_0.initial_credit == uart_barrot_data_0.credit;
|
||||
}
|
||||
|
||||
|
||||
static int barrot_irq_is_pending(const struct device *dev)
|
||||
{
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static int barrot_irq_update(const struct device *dev)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
static const struct uart_driver_api uart_barrot_driver_api = {
|
||||
.configure = barrot_configure,
|
||||
.fifo_fill = barrot_fifo_fill,
|
||||
.fifo_read = barrot_fifo_read,
|
||||
.irq_tx_enable = barrot_irq_tx_enable,
|
||||
.irq_tx_disable = barrot_irq_tx_disable,
|
||||
.irq_tx_ready = barrot_irq_tx_ready,
|
||||
.irq_rx_enable = barrot_irq_rx_enable,
|
||||
.irq_rx_disable = barrot_irq_rx_disable,
|
||||
.irq_tx_complete = barrot_irq_tx_complete,
|
||||
.irq_rx_ready = barrot_irq_rx_ready,
|
||||
.irq_is_pending = barrot_irq_is_pending,
|
||||
.irq_update = barrot_irq_update,
|
||||
|
||||
.irq_callback_set = barrot_irq_callback_set,
|
||||
};
|
||||
|
||||
|
||||
static int uart_barrot_init(const struct device *dev)
|
||||
{
|
||||
struct uart_barrot_data *data;
|
||||
|
||||
data = dev->data;
|
||||
data->dev = dev;
|
||||
struct bt_uuid_16 txuuid = BT_UUID_INIT_16(0xff03);
|
||||
data->tx.uuid = txuuid;
|
||||
data->tx.notifier = notify_tx_func;
|
||||
struct bt_uuid_16 txwuuid = BT_UUID_INIT_16(0xff02);
|
||||
data->tx_w_uuid = txwuuid;
|
||||
struct bt_uuid_16 rxuuid = BT_UUID_INIT_16(0xff01);
|
||||
data->rx.uuid = rxuuid;
|
||||
data->rx.notifier = notify_rx_func;
|
||||
k_mutex_init(&data->irq_mutex);
|
||||
return 0;
|
||||
|
||||
}
|
||||
DEVICE_DT_INST_DEFINE(0,
|
||||
uart_barrot_init,
|
||||
NULL,
|
||||
&uart_barrot_data_0, &uart_barrot_dev_cfg_0,
|
||||
PRE_KERNEL_1, CONFIG_SERIAL_INIT_PRIORITY,
|
||||
(void *)&uart_barrot_driver_api);
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* bt.hpp
|
||||
*
|
||||
* Created on: Aug 16, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
|
||||
#ifndef BT_HPP_
|
||||
#define BT_HPP_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
bool bt_init();
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BT_HPP_ */
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* display.cpp
|
||||
*
|
||||
* Created on: Aug 21, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
|
||||
#include <zephyr/drivers/display.h>
|
||||
|
||||
#include "display.hpp"
|
||||
#include "printt.h"
|
||||
#include "font.h"
|
||||
|
||||
int Display::Init()
|
||||
{
|
||||
k_mutex_init(&mut);
|
||||
dev = DEVICE_DT_GET(DT_CHOSEN(zephyr_display));
|
||||
if (!device_is_ready(dev)) {
|
||||
printt("Device %s not ready", dev->name);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (display_set_pixel_format(dev, PIXEL_FORMAT_MONO10) != 0) {
|
||||
printt("Failed to set required pixel format");
|
||||
return 1;
|
||||
}
|
||||
printt("Initialized %s", dev->name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void Display::blank_off()
|
||||
{
|
||||
k_mutex_lock(&mut, K_FOREVER);
|
||||
display_blanking_off(dev);
|
||||
k_mutex_unlock(&mut);
|
||||
}
|
||||
|
||||
void Display::print_chr(int x, int y, char c)
|
||||
{
|
||||
int idx;
|
||||
for(idx=0;my_font_map_[idx];idx++)
|
||||
{
|
||||
if(my_font_map_[idx] == c)
|
||||
break;
|
||||
}
|
||||
if(!my_font_map_[idx])
|
||||
idx=0;
|
||||
|
||||
struct display_buffer_descriptor desc={
|
||||
.buf_size=16,
|
||||
.width=8,
|
||||
.height=16,
|
||||
.pitch=8
|
||||
};
|
||||
|
||||
|
||||
k_mutex_lock(&mut, K_FOREVER);
|
||||
display_write(dev,x,y,&desc,my_font_[idx]);
|
||||
k_mutex_unlock(&mut);
|
||||
|
||||
}
|
||||
|
||||
void Display::print_str(int x, int y, const char* str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* display.hpp
|
||||
*
|
||||
* Created on: Aug 21, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
|
||||
#ifndef DISPLAY_HPP_
|
||||
#define DISPLAY_HPP_
|
||||
|
||||
#include <zephyr/zephyr.h>
|
||||
|
||||
class Display {
|
||||
const struct device *dev;
|
||||
k_mutex mut;
|
||||
public:
|
||||
int Init();
|
||||
void blank_off();
|
||||
void print_chr(int x, int y, char c);
|
||||
void print_str(int x, int y, const char* str);
|
||||
};
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* DISPLAY_HPP_ */
|
||||
@@ -0,0 +1,69 @@
|
||||
#ifndef FIFO_DEF_H_
|
||||
#define FIFO_DEF_H_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include <zephyr/sys/atomic.h>
|
||||
#include <zephyr/irq.h>
|
||||
|
||||
|
||||
template<size_t LEN,typename CNT=unsigned char>
|
||||
class FIFO{
|
||||
CNT data[LEN];
|
||||
CNT* const data_end;
|
||||
atomic_ptr_t wrptr;
|
||||
atomic_ptr_t rdptr;
|
||||
public:
|
||||
FIFO() : data(), data_end(&data[LEN]), wrptr(data), rdptr(data){};
|
||||
void clear()
|
||||
{
|
||||
auto key = irq_lock();
|
||||
atomic_ptr_set(&wrptr, data);
|
||||
atomic_ptr_set(&rdptr, data);
|
||||
irq_unlock(key);
|
||||
}
|
||||
inline intptr_t put(CNT val)
|
||||
{
|
||||
auto key = irq_lock();
|
||||
volatile CNT *tmwr = (volatile CNT *)atomic_ptr_get(&wrptr);
|
||||
volatile CNT *tmrd = (volatile CNT *)atomic_ptr_get(&rdptr);
|
||||
irq_unlock(key);
|
||||
|
||||
tmwr += 1;
|
||||
if(tmwr == data_end)
|
||||
tmwr = data;
|
||||
if (tmwr == tmrd)
|
||||
return 0;
|
||||
*tmwr = val;
|
||||
atomic_ptr_set(&wrptr,(void*)tmwr);
|
||||
return 1;
|
||||
|
||||
}
|
||||
inline intptr_t get(CNT* val)
|
||||
{
|
||||
auto key = irq_lock();
|
||||
volatile CNT *tmwr = (volatile CNT *)atomic_ptr_get(&wrptr);
|
||||
volatile CNT *tmrd = (volatile CNT *)atomic_ptr_get(&rdptr);
|
||||
irq_unlock(key);
|
||||
if (tmwr == tmrd)
|
||||
return 0;
|
||||
tmrd += 1;
|
||||
if(tmrd == data_end)
|
||||
tmrd = data;
|
||||
*val = *tmrd;
|
||||
atomic_ptr_set(&rdptr,(void*)tmrd);
|
||||
return 1;
|
||||
}
|
||||
inline intptr_t check()
|
||||
{
|
||||
auto key = irq_lock();
|
||||
volatile CNT *tmwr = (volatile CNT *)atomic_ptr_get(&wrptr);
|
||||
volatile CNT *tmrd = (volatile CNT *)atomic_ptr_get(&rdptr);
|
||||
irq_unlock(key);
|
||||
int ret = (tmwr - tmrd);
|
||||
if (ret < 0) ret +=LEN;
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* FIFO_H_ */
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*autogenerated file*/
|
||||
unsigned char my_font_[][16] =
|
||||
{
|
||||
{
|
||||
0xe7,0xc7,
|
||||
0xdf,0xdc,
|
||||
0xd8,0xc3,
|
||||
0xe7,0xff,
|
||||
0xff,0xff,
|
||||
0xff,0x4f,
|
||||
0x4f,0xff,
|
||||
0xff,0xff,
|
||||
},
|
||||
{
|
||||
0xdf,0xc0,
|
||||
0xc0,0xfb,
|
||||
0xf9,0xfc,
|
||||
0xfe,0xff,
|
||||
0xff,0x0f,
|
||||
0x0f,0xef,
|
||||
0xef,0x0f,
|
||||
0x1f,0xff,
|
||||
},
|
||||
{
|
||||
0xff,0xfa,
|
||||
0xfa,0xfa,
|
||||
0xf8,0xfc,
|
||||
0xff,0xff,
|
||||
0x1f,0x0f,
|
||||
0xef,0xef,
|
||||
0x1f,0x0f,
|
||||
0xef,0xff,
|
||||
},
|
||||
{
|
||||
0xfc,0xf8,
|
||||
0xfb,0xfb,
|
||||
0xfb,0xf9,
|
||||
0xfd,0xff,
|
||||
0x1f,0x0f,
|
||||
0xef,0xef,
|
||||
0xef,0xcf,
|
||||
0xdf,0xff,
|
||||
},
|
||||
};
|
||||
char my_font_map_[]=
|
||||
{
|
||||
'?',
|
||||
'b',
|
||||
'a',
|
||||
'c',
|
||||
'\0',
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
/*autogenerated file*/
|
||||
#ifndef FONT_H
|
||||
#define FONT_H
|
||||
extern unsigned char my_font_[][16] ;
|
||||
extern char my_font_map_[];
|
||||
#endif
|
||||
+122
@@ -0,0 +1,122 @@
|
||||
#include <zephyr/zephyr.h>
|
||||
#include <zephyr/device.h>
|
||||
#include <zephyr/bluetooth/bluetooth.h>
|
||||
#include <zephyr/modbus/modbus.h>
|
||||
|
||||
#include "main_modules.hpp"
|
||||
#include "printt.h"
|
||||
extern "C" void barrot_init();
|
||||
|
||||
struct Reg_data reg_data;
|
||||
|
||||
Display display;
|
||||
|
||||
|
||||
int printt( const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
|
||||
int rc;
|
||||
|
||||
va_start(ap, format);
|
||||
rc = tlay2.printvt(format,ap);
|
||||
va_end(ap);
|
||||
return rc;
|
||||
}
|
||||
|
||||
const static struct modbus_iface_param client_param = {
|
||||
.mode = MODBUS_MODE_RTU,
|
||||
.rx_timeout = 750000,
|
||||
.serial = {
|
||||
.baud = 9600/25,
|
||||
.parity = UART_CFG_PARITY_NONE,
|
||||
.stop_bits_client = UART_CFG_STOP_BITS_2,
|
||||
},
|
||||
};
|
||||
|
||||
#define MODBUS_NODE DT_COMPAT_GET_ANY_STATUS_OKAY(zephyr_modbus_serial)
|
||||
|
||||
int client_iface;
|
||||
|
||||
static int init_modbus_client(void)
|
||||
{
|
||||
const char iface_name[] = {DEVICE_DT_NAME(MODBUS_NODE)};
|
||||
|
||||
client_iface = modbus_iface_get_by_name(iface_name);
|
||||
|
||||
return modbus_init_client(client_iface, client_param);
|
||||
}
|
||||
|
||||
int d_print(int c)
|
||||
{
|
||||
printt("%c",c);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
{
|
||||
if(!tlay2.Init())
|
||||
return 1;
|
||||
|
||||
tlay2.printt("Hello World! %s", CONFIG_BOARD);
|
||||
|
||||
int err;
|
||||
|
||||
err = display.Init();
|
||||
if(err)
|
||||
return err;
|
||||
|
||||
err = bt_enable(NULL);
|
||||
if (err) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
barrot_init();
|
||||
|
||||
|
||||
k_mutex_init(®_data.mut);
|
||||
|
||||
if (init_modbus_client()) {
|
||||
tlay2.printt("Modbus RTU client initialization failed");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
display.blank_off();
|
||||
|
||||
display.print_chr(32,0,'a');
|
||||
|
||||
display.print_chr(32,32,'a');
|
||||
|
||||
display.print_chr(48,48,'a');
|
||||
|
||||
display.print_chr(48,128,'a');
|
||||
|
||||
display.print_chr(32,120,'a');
|
||||
|
||||
while(1)
|
||||
{
|
||||
uint16_t holding_reg[11];
|
||||
if(modbus_read_input_regs(client_iface, 1, 0x3045, holding_reg,
|
||||
ARRAY_SIZE(holding_reg))!=0)
|
||||
{
|
||||
printt("Read fail");
|
||||
continue;
|
||||
}
|
||||
k_mutex_lock(®_data.mut, K_FOREVER);
|
||||
reg_data.b_soc = holding_reg[0];
|
||||
reg_data.b_v = holding_reg[1];
|
||||
reg_data.b_a = holding_reg[2];
|
||||
reg_data.l_v = holding_reg[5];
|
||||
reg_data.l_a = holding_reg[6];
|
||||
reg_data.s_v = holding_reg[9];
|
||||
reg_data.s_a = holding_reg[10];
|
||||
k_mutex_unlock(®_data.mut);
|
||||
printt("Read ok");
|
||||
|
||||
//k_msleep(1000);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* main_modules.hpp
|
||||
*
|
||||
* Created on: Aug 16, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
|
||||
#ifndef MAIN_MODULES_HPP_
|
||||
#define MAIN_MODULES_HPP_
|
||||
|
||||
#include "tlay2.hpp"
|
||||
#include "display.hpp"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <zephyr/kernel.h>
|
||||
|
||||
struct Reg_data {
|
||||
uint16_t b_soc;
|
||||
uint16_t b_v;
|
||||
int16_t b_a;
|
||||
uint16_t l_v;
|
||||
uint16_t l_a;
|
||||
uint16_t s_v;
|
||||
uint16_t s_a;
|
||||
k_mutex mut;
|
||||
};
|
||||
|
||||
extern struct Reg_data reg_data;
|
||||
|
||||
extern int client_iface;
|
||||
|
||||
extern Tlay2<128> tlay2;
|
||||
|
||||
extern Display display;
|
||||
|
||||
|
||||
|
||||
|
||||
#endif /* MAIN_MODULES_HPP_ */
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* printt.h
|
||||
*
|
||||
* Created on: Aug 18, 2022
|
||||
* Author: kosa
|
||||
*/
|
||||
|
||||
#ifndef PRINTT_H_
|
||||
#define PRINTT_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int printt( const char *format, ...);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif /* PRINTT_H_ */
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
#ifndef TLAY2_TLAY2_H
|
||||
#define TLAY2_TLAY2_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <zephyr/zephyr.h>
|
||||
#include <zephyr/sys/crc.h>
|
||||
#include <zephyr/sys/cbprintf.h>
|
||||
|
||||
#include "uart.hpp"
|
||||
|
||||
|
||||
template<int MAX_PKT_SIZE>
|
||||
class Tlay2
|
||||
{
|
||||
private:
|
||||
struct k_mutex tx_mutex;
|
||||
struct k_thread rx_thread;
|
||||
struct k_sem rx_sem_wait;
|
||||
struct k_sem tx_sem_wait;
|
||||
k_thread_stack_t *rx_stack;
|
||||
size_t rx_stack_size;
|
||||
typedef void (*process_packet_t)(Tlay2<MAX_PKT_SIZE>* obj, uint8_t*data,size_t len);
|
||||
UART<MAX_PKT_SIZE+10,MAX_PKT_SIZE+10> uart;
|
||||
process_packet_t process_packet;
|
||||
|
||||
uint8_t tlay2_rx_buf[MAX_PKT_SIZE];
|
||||
uint8_t tlay2_rx_len;
|
||||
uint8_t tlay2_tx_crc;
|
||||
|
||||
static bool rx_isr_c(void* user_data, uint8_t *byte)
|
||||
{
|
||||
Tlay2<MAX_PKT_SIZE> *obj=static_cast<Tlay2<MAX_PKT_SIZE>*>(user_data);
|
||||
return obj->rx_isr(byte);
|
||||
}
|
||||
bool rx_isr(uint8_t* byte)
|
||||
{
|
||||
if(*byte == '\n')
|
||||
k_sem_give(&rx_sem_wait);
|
||||
return true;
|
||||
}
|
||||
static void rx_thread_c(void* user_data, void* arg2, void* arg3)
|
||||
{
|
||||
Tlay2<MAX_PKT_SIZE> *obj=static_cast<Tlay2<MAX_PKT_SIZE>*>(user_data);
|
||||
obj->rx_thread_fn();
|
||||
}
|
||||
void rx_thread_fn()
|
||||
{
|
||||
while(true)
|
||||
{
|
||||
k_sem_take(&rx_sem_wait,K_FOREVER);
|
||||
retry:
|
||||
tlay2_rx_len=0;
|
||||
uint8_t c;
|
||||
do {
|
||||
uart.get(&c);
|
||||
if (c == '\n')
|
||||
break;
|
||||
if (c == 0xdc)
|
||||
{
|
||||
uart.get(&c);
|
||||
c ^= 0x80;
|
||||
}
|
||||
tlay2_rx_buf[tlay2_rx_len++]=c;
|
||||
}while(tlay2_rx_len < MAX_PKT_SIZE);
|
||||
tlay2_rx_len-=1;
|
||||
if(c != '\n')
|
||||
goto retry;
|
||||
if (tlay2_rx_len < 2)
|
||||
continue;
|
||||
if (crc8_ccitt(0x00,tlay2_rx_buf,tlay2_rx_len+1) != 0)
|
||||
continue;
|
||||
if(process_packet)
|
||||
process_packet(this,tlay2_rx_buf,tlay2_rx_len);
|
||||
}
|
||||
}
|
||||
public:
|
||||
Tlay2(
|
||||
const struct device *_dev,
|
||||
k_thread_stack_t *_rx_stack,
|
||||
size_t _rx_stack_size,
|
||||
process_packet_t _process_packet=NULL)
|
||||
|
||||
:rx_stack(_rx_stack),
|
||||
rx_stack_size(_rx_stack_size),
|
||||
uart(_dev,rx_isr_c,this),
|
||||
process_packet(_process_packet)
|
||||
{
|
||||
k_mutex_init(&tx_mutex);
|
||||
k_sem_init(&rx_sem_wait, 0, MAX_PKT_SIZE);
|
||||
k_sem_init(&tx_sem_wait, 1, 1);
|
||||
}
|
||||
bool Init()
|
||||
{
|
||||
bool ret;
|
||||
|
||||
ret = uart.Init();
|
||||
if(!ret)
|
||||
return ret;
|
||||
k_thread_create(&rx_thread,rx_stack, rx_stack_size,rx_thread_c,this,NULL,NULL,5,0,K_NO_WAIT);
|
||||
return true;
|
||||
}
|
||||
|
||||
void tx_init_reply()
|
||||
{
|
||||
k_sem_take(&tx_sem_wait,K_FOREVER);
|
||||
tlay2_tx_crc=0x00;
|
||||
tx_byte(tlay2_rx_buf[0]); //remote channel
|
||||
tx_byte(tlay2_rx_buf[1]); //local function
|
||||
}
|
||||
void tx_init(uint8_t channel, uint8_t function)
|
||||
{
|
||||
k_sem_take(&tx_sem_wait,K_FOREVER);
|
||||
tlay2_tx_crc=0x00;
|
||||
tx_byte(channel); // remote channel
|
||||
tx_byte(function); // local function
|
||||
}
|
||||
void tx_end()
|
||||
{
|
||||
tx_byte(tlay2_tx_crc);
|
||||
uart.send('\n');
|
||||
k_sem_give(&tx_sem_wait);
|
||||
}
|
||||
void tx_byte(uint8_t byte)
|
||||
{
|
||||
tlay2_tx_crc=crc8_ccitt(tlay2_tx_crc,&byte,1);
|
||||
if (byte == '\n' || byte == 0xdc)
|
||||
{
|
||||
uart.send(0xdc);
|
||||
byte ^=0x80;
|
||||
}
|
||||
uart.send(byte);
|
||||
}
|
||||
void tx_u16(uint16_t byte)
|
||||
{
|
||||
tx_byte(byte&0xff);
|
||||
tx_byte(byte >> 8);
|
||||
}
|
||||
|
||||
void tx_u32(uint32_t byte)
|
||||
{
|
||||
tx_byte(byte&0xff);
|
||||
tx_byte((byte >> 8)&0xff);
|
||||
tx_byte((byte >> 16)&0xff);
|
||||
tx_byte((byte >> 24)&0xff);
|
||||
}
|
||||
uint16_t rx_u16(uint8_t * buff)
|
||||
{
|
||||
return ((uint16_t)buff[1] << 8) | buff[0];
|
||||
}
|
||||
|
||||
uint32_t rx_u32(uint8_t * buff)
|
||||
{
|
||||
return ((uint32_t)buff[3] << 24) | ((uint32_t)buff[2] << 16) | ((uint32_t)buff[1] << 8) | buff[0];
|
||||
|
||||
}
|
||||
static int cwrap_tx_byte(int c, void *ctx)
|
||||
{
|
||||
if(ctx == NULL)
|
||||
return -1;
|
||||
uint8_t cr=c;
|
||||
static_cast<Tlay2<MAX_PKT_SIZE>*>(ctx)->tx_byte(cr);
|
||||
return cr;
|
||||
}
|
||||
|
||||
int printvt(const char *format, va_list ap)
|
||||
{
|
||||
int rc;
|
||||
|
||||
tx_init(0,0);
|
||||
rc = cbvprintf((cbprintf_cb)cwrap_tx_byte, this, format, ap);
|
||||
tx_end();
|
||||
while(uart.fifo_tx.check());
|
||||
return rc;
|
||||
}
|
||||
|
||||
int printt( const char *format, ...)
|
||||
{
|
||||
va_list ap;
|
||||
int rc;
|
||||
|
||||
va_start(ap, format);
|
||||
rc = printvt(format,ap);
|
||||
va_end(ap);
|
||||
|
||||
return rc;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "main_modules.hpp"
|
||||
#include <zephyr/device.h>
|
||||
|
||||
K_KERNEL_STACK_DEFINE(tlay2_stack,300);
|
||||
|
||||
|
||||
void process_packet(Tlay2<128>* obj, uint8_t*data,size_t len);
|
||||
|
||||
Tlay2<128> tlay2 = {DEVICE_DT_GET(DT_NODELABEL(uart0)),tlay2_stack,K_THREAD_STACK_SIZEOF(tlay2_stack),process_packet};
|
||||
|
||||
void process_packet(Tlay2<128>* obj, uint8_t*data,size_t len)
|
||||
{
|
||||
switch(data[1])
|
||||
{
|
||||
case 0: //PING
|
||||
obj->tx_init_reply();
|
||||
for(size_t i=2;i<len;i++)
|
||||
obj->tx_byte(data[i]);
|
||||
obj->tx_end();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
+104
@@ -0,0 +1,104 @@
|
||||
#ifndef TLAY2_UART_H
|
||||
#define TLAY2_UART_H
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "fifo.hpp"
|
||||
#include <zephyr/drivers/uart.h>
|
||||
#include <zephyr/zephyr.h>
|
||||
|
||||
template<int RX_SIZE,int TX_SIZE>
|
||||
class UART
|
||||
{
|
||||
private:
|
||||
const struct device *dev;
|
||||
typedef bool (*rx_callback_t)(void* obj, uint8_t *byte);
|
||||
|
||||
rx_callback_t rx_callback;
|
||||
void* rx_callback_obj;
|
||||
FIFO<RX_SIZE> fifo_rx;
|
||||
public:
|
||||
FIFO<TX_SIZE> fifo_tx;
|
||||
private:
|
||||
struct k_sem tx_sem_wait;
|
||||
static void isr_c(const struct device *dev,
|
||||
void *user_data)
|
||||
{
|
||||
UART<RX_SIZE,TX_SIZE> *obj=static_cast<UART<RX_SIZE,TX_SIZE>*>(user_data);
|
||||
obj->isr();
|
||||
}
|
||||
void isr()
|
||||
{
|
||||
if (!uart_irq_update(dev) || !uart_irq_is_pending(dev))
|
||||
return;
|
||||
|
||||
if(uart_irq_rx_ready(dev))
|
||||
{
|
||||
uint8_t recvData;
|
||||
uart_fifo_read(dev, &recvData, 1);
|
||||
if(rx_callback)
|
||||
{
|
||||
if(rx_callback(rx_callback_obj,&recvData))
|
||||
fifo_rx.put(recvData);
|
||||
}
|
||||
else
|
||||
{
|
||||
fifo_rx.put(recvData);
|
||||
}
|
||||
}
|
||||
if(uart_irq_tx_ready(dev))
|
||||
{
|
||||
uint8_t val;
|
||||
intptr_t cnt = fifo_tx.get(&val);
|
||||
if(cnt)
|
||||
{
|
||||
uart_fifo_fill(dev, &val, 1);
|
||||
k_sem_give(&tx_sem_wait);
|
||||
}
|
||||
else
|
||||
{
|
||||
uart_irq_tx_disable(dev);
|
||||
}
|
||||
}
|
||||
}
|
||||
public:
|
||||
UART(
|
||||
const struct device *_dev,
|
||||
rx_callback_t _rx_callback=NULL,
|
||||
void* _rx_callback_obj=NULL)
|
||||
:dev(_dev),
|
||||
rx_callback(_rx_callback),
|
||||
rx_callback_obj(_rx_callback_obj)
|
||||
{
|
||||
k_sem_init(&tx_sem_wait, 0, 1);
|
||||
};
|
||||
bool Init()
|
||||
{
|
||||
if (!device_is_ready(dev)) {
|
||||
printk("Device %s not ready\n", dev->name);
|
||||
return false;
|
||||
}
|
||||
uart_irq_callback_user_data_set(dev,isr_c,this);
|
||||
uart_irq_rx_enable(dev);
|
||||
return true;
|
||||
}
|
||||
intptr_t get(uint8_t *byte)
|
||||
{
|
||||
return fifo_rx.get(byte);
|
||||
}
|
||||
intptr_t send(uint8_t byte)
|
||||
{
|
||||
intptr_t ret;
|
||||
do {
|
||||
ret = fifo_tx.put(byte);
|
||||
uart_irq_tx_enable(dev);
|
||||
if(!ret)
|
||||
{
|
||||
k_sem_take(&tx_sem_wait,K_FOREVER);
|
||||
}
|
||||
} while(!ret);
|
||||
return ret;
|
||||
}
|
||||
};
|
||||
|
||||
#endif
|
||||
Reference in New Issue
Block a user