mirror of
https://github.com/korneliuszo/lumiax-controller.git
synced 2026-03-28 19:22:33 +01:00
Initial commit
This commit is contained in:
18
CMakeLists.txt
Normal file
18
CMakeLists.txt
Normal file
@@ -0,0 +1,18 @@
|
||||
|
||||
set(BOARD_ROOT ${CMAKE_CURRENT_SOURCE_DIR})
|
||||
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
|
||||
|
||||
# ===== DO NOT REMOVE =====
|
||||
cmake_minimum_required(VERSION 3.13.1)
|
||||
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
|
||||
# ===== DO NOT REMOVE =====
|
||||
|
||||
project(controller-fw)
|
||||
|
||||
target_sources(app PRIVATE
|
||||
src/main.cpp
|
||||
src/uart.cpp
|
||||
src/bt.c
|
||||
src/display.cpp
|
||||
src/font.c
|
||||
)
|
||||
8
boards/arm/controller/Kconfig.board
Normal file
8
boards/arm/controller/Kconfig.board
Normal file
@@ -0,0 +1,8 @@
|
||||
# nRF51 BLE400 board configuration
|
||||
|
||||
# Copyright (c) 2018 Roman Tataurov <diytronic@yandex.ru>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
config BOARD_CONTROLLER
|
||||
bool "Controller"
|
||||
depends on SOC_NRF51822_QFAC
|
||||
14
boards/arm/controller/Kconfig.defconfig
Normal file
14
boards/arm/controller/Kconfig.defconfig
Normal file
@@ -0,0 +1,14 @@
|
||||
# nRF51 BLE400 board configuration
|
||||
|
||||
# Copyright (c) 2018 Roman Tataurov <diytronic@yandex.ru>
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
if BOARD_CONTROLLER
|
||||
|
||||
config BOARD
|
||||
default "controller"
|
||||
|
||||
config BT_CTLR
|
||||
default BT
|
||||
|
||||
endif # BOARD_CONTORLLER
|
||||
4
boards/arm/controller/board.cmake
Normal file
4
boards/arm/controller/board.cmake
Normal file
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
board_runner_args(pyocd "--target=nrf51822" "--frequency=4000000")
|
||||
include(${ZEPHYR_BASE}/boards/common/pyocd.board.cmake)
|
||||
52
boards/arm/controller/controller-pinctrl.dtsi
Normal file
52
boards/arm/controller/controller-pinctrl.dtsi
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Copyright (c) 2022 Nordic Semiconductor
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
&pinctrl {
|
||||
i2c0_default: i2c0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 0)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 1)>;
|
||||
};
|
||||
};
|
||||
|
||||
i2c0_sleep: i2c0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(TWIM_SDA, 0, 0)>,
|
||||
<NRF_PSEL(TWIM_SCL, 0, 1)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
spi1_default: spi1_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 14)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 16)>;
|
||||
};
|
||||
};
|
||||
|
||||
spi1_sleep: spi1_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(SPIM_SCK, 0, 14)>,
|
||||
<NRF_PSEL(SPIM_MOSI, 0, 16)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_default: uart0_default {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 9)>,
|
||||
<NRF_PSEL(UART_RX, 0, 11)>;
|
||||
};
|
||||
};
|
||||
|
||||
uart0_sleep: uart0_sleep {
|
||||
group1 {
|
||||
psels = <NRF_PSEL(UART_TX, 0, 9)>,
|
||||
<NRF_PSEL(UART_RX, 0, 11)>;
|
||||
low-power-enable;
|
||||
};
|
||||
};
|
||||
|
||||
};
|
||||
176
boards/arm/controller/controller.dts
Normal file
176
boards/arm/controller/controller.dts
Normal file
@@ -0,0 +1,176 @@
|
||||
/*
|
||||
* Copyright (c) 2018 Roman Tataurov <diytronic@yandex.ru>
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/dts-v1/;
|
||||
#include <nordic/nrf51822_qfac.dtsi>
|
||||
#include "controller-pinctrl.dtsi"
|
||||
|
||||
/ {
|
||||
model = "Waveshare BLE400";
|
||||
compatible = "waveshare,BLE400";
|
||||
|
||||
chosen {
|
||||
zephyr,sram = &sram0;
|
||||
zephyr,flash = &flash0;
|
||||
zephyr,display = &ssd16xx;
|
||||
};
|
||||
|
||||
/* These aliases are provided for compatibility with samples */
|
||||
aliases {
|
||||
led0 = &led0;
|
||||
led1 = &led1;
|
||||
led2 = &led2;
|
||||
led3 = &led3;
|
||||
led4 = &led4;
|
||||
sw0 = &button0;
|
||||
sw1 = &button1;
|
||||
watchdog0 = &wdt0;
|
||||
};
|
||||
|
||||
leds {
|
||||
compatible = "gpio-leds";
|
||||
led0: led_0 {
|
||||
gpios = <&gpio0 18 0>;
|
||||
label = "Red LED 0";
|
||||
};
|
||||
led1: led_1 {
|
||||
gpios = <&gpio0 19 0>;
|
||||
label = "Red LED 1";
|
||||
};
|
||||
led2: led_2 {
|
||||
gpios = <&gpio0 20 0>;
|
||||
label = "Red LED 2";
|
||||
};
|
||||
led3: led_3 {
|
||||
gpios = <&gpio0 21 0>;
|
||||
label = "Red LED 3";
|
||||
};
|
||||
led4: led_4 {
|
||||
gpios = <&gpio0 22 0>;
|
||||
label = "Red LED 4";
|
||||
};
|
||||
};
|
||||
|
||||
buttons {
|
||||
/* Push button switch 0 KEY1 */
|
||||
compatible = "gpio-keys";
|
||||
button0: button_0 {
|
||||
gpios = <&gpio0 16 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Push button switch 0";
|
||||
};
|
||||
/* Push button switch 1 KEY2 */
|
||||
button1: button_1 {
|
||||
gpios = <&gpio0 17 (GPIO_PULL_UP | GPIO_ACTIVE_LOW)>;
|
||||
label = "Push button switch 1";
|
||||
};
|
||||
};
|
||||
barrot {
|
||||
compatible = "barrot_serial";
|
||||
btaddr = [82 72 95 83 15 00];
|
||||
|
||||
modbus0 {
|
||||
compatible = "zephyr,modbus-serial";
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
&gpiote {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&gpio0 {
|
||||
status = "okay";
|
||||
};
|
||||
|
||||
&i2c0 {
|
||||
status = "okay";
|
||||
/* smba-pin = <2>; */
|
||||
pinctrl-0 = <&i2c0_default>;
|
||||
pinctrl-1 = <&i2c0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
|
||||
&spi1 {
|
||||
compatible = "nordic,nrf-spi";
|
||||
status = "okay";
|
||||
cs-gpios = <&gpio0 12 GPIO_ACTIVE_LOW>;
|
||||
pinctrl-0 = <&spi1_default>;
|
||||
pinctrl-1 = <&spi1_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
|
||||
ssd16xx: ssd16xxfb@0 {
|
||||
compatible = "gooddisplay,GDEM029T94", "solomon,ssd1680", "solomon,ssd16xxfb";
|
||||
spi-max-frequency = <4000000>;
|
||||
reg = <0>;
|
||||
width = <296>;
|
||||
height = <136>; // it's 128 but needs 136
|
||||
pp-width-bits = <8>;
|
||||
pp-height-bits = <16>;
|
||||
dc-gpios = <&gpio0 10 GPIO_ACTIVE_LOW>;
|
||||
reset-gpios = <&gpio0 8 GPIO_ACTIVE_LOW>;
|
||||
busy-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
|
||||
gdv = [17];
|
||||
sdv = [41 00 32];
|
||||
vcom = <0x36>;
|
||||
//orientation-flipped;
|
||||
border-waveform = <0xC0>;
|
||||
//softstart = [d7 d6 9d];
|
||||
lut-initial = [
|
||||
80 66 00 00 00 00 00 00
|
||||
40 00 00 00 10 66 00 00
|
||||
00 00 00 00 20 00 00 00
|
||||
80 66 00 00 00 00 00 00
|
||||
40 00 00 00 10 66 00 00
|
||||
00 00 00 00 20 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 14 08 00 00
|
||||
00 00 01 0a 0a 00 0a 0a
|
||||
00 01 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 14 08 00 01
|
||||
00 00 01 00 00 00 00 00
|
||||
00 01 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
44 44 44 44 44 44 00 00
|
||||
00
|
||||
];
|
||||
lut-default = [
|
||||
00 40 00 00 00 00 00 00
|
||||
00 00 00 00 80 80 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
40 40 00 00 00 00 00 00
|
||||
00 00 00 00 00 80 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 0a 00 00 00
|
||||
00 00 02 01 00 00 00 00
|
||||
00 00 01 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
00 00 00 00 00 00 00 00
|
||||
22 22 22 22 22 22 00 00
|
||||
00
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
&uart0 {
|
||||
current-speed = <115200>;
|
||||
status = "okay";
|
||||
pinctrl-0 = <&uart0_default>;
|
||||
pinctrl-1 = <&uart0_sleep>;
|
||||
pinctrl-names = "default", "sleep";
|
||||
};
|
||||
17
boards/arm/controller/controller.yaml
Normal file
17
boards/arm/controller/controller.yaml
Normal file
@@ -0,0 +1,17 @@
|
||||
identifier: controller
|
||||
name: controller
|
||||
type: mcu
|
||||
arch: arm
|
||||
toolchain:
|
||||
- zephyr
|
||||
- gnuarmemb
|
||||
- xtools
|
||||
ram: 32
|
||||
supported:
|
||||
- ble
|
||||
- gpio
|
||||
- i2c
|
||||
testing:
|
||||
ignore_tags:
|
||||
- net
|
||||
|
||||
13
boards/arm/controller/controller_defconfig
Normal file
13
boards/arm/controller/controller_defconfig
Normal file
@@ -0,0 +1,13 @@
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
CONFIG_SOC_SERIES_NRF51X=y
|
||||
CONFIG_SOC_NRF51822_QFAC=y
|
||||
CONFIG_BOARD_CONTROLLER=y
|
||||
|
||||
# enable GPIO
|
||||
CONFIG_GPIO=y
|
||||
|
||||
# enable uart driver
|
||||
CONFIG_SERIAL=y
|
||||
|
||||
CONFIG_PINCTRL=y
|
||||
7
boards/arm/controller/dts/bindings/barrot_serial.yaml
Normal file
7
boards/arm/controller/dts/bindings/barrot_serial.yaml
Normal file
@@ -0,0 +1,7 @@
|
||||
compatible: "barrot_serial"
|
||||
description: Barrot
|
||||
|
||||
properties:
|
||||
btaddr:
|
||||
type: uint8-array
|
||||
required: true
|
||||
6
boards/arm/controller/pre_dt_board.cmake
Normal file
6
boards/arm/controller/pre_dt_board.cmake
Normal file
@@ -0,0 +1,6 @@
|
||||
# Copyright (c) 2022 Nordic Semiconductor
|
||||
# SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
# Suppress "unique_unit_address_if_enabled" to handle the following overlaps:
|
||||
# - power@40000000 & clock@40000000 & nrf-mpu@40000000
|
||||
list(APPEND EXTRA_DTC_FLAGS "-Wno-unique_unit_address_if_enabled")
|
||||
78
generate_font.py
Executable file
78
generate_font.py
Executable file
@@ -0,0 +1,78 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
from PIL import Image, ImageOps
|
||||
from pathlib import Path
|
||||
import bdflib.reader
|
||||
|
||||
used_chars = "?bac"
|
||||
|
||||
bdf_file = Path(sys.argv[1])
|
||||
bdf=bdflib.reader.read_bdf(open(bdf_file,'rb'))
|
||||
|
||||
|
||||
source = open("src/font.c","w")
|
||||
header = open("src/font.h","w")
|
||||
|
||||
def gen_hdr(tgt):
|
||||
tgt.write('unsigned char my_font_[][16] ')
|
||||
|
||||
|
||||
def gen_char(tgt,ch):
|
||||
glyph=bdf.glyphs_by_codepoint[ord(ch)]
|
||||
|
||||
if glyph.bbH != 16 or glyph.bbW != 8:
|
||||
raise Exception("glyph size not supported")
|
||||
|
||||
data_raw = bytes(glyph.data)
|
||||
|
||||
data = bytearray([255])*16
|
||||
for x in range(8):
|
||||
for y in range(16):
|
||||
if(data_raw[y]&(1<<(7-x))):
|
||||
data[x+(1-(y//8))*8] &= ~(1<<(y%8))
|
||||
|
||||
tgt.write(" {\n")
|
||||
|
||||
line_buffer = []
|
||||
for p in data:
|
||||
line_buffer.append("0x%02x,"%p)
|
||||
if len(line_buffer) >= 2:
|
||||
tgt.write(' %s\n'%(''.join(line_buffer)))
|
||||
line_buffer = []
|
||||
if len(line_buffer):
|
||||
tgt.write(' %s\n'%(''.join(line_buffer)))
|
||||
tgt.write(" },\n")
|
||||
|
||||
def gen_map_hdr(tgt):
|
||||
tgt.write('char my_font_map_[]')
|
||||
def gen_map_char(tgt,char):
|
||||
tgt.write(" '%s',\n"%char)
|
||||
|
||||
|
||||
source.write("/*autogenerated file*/\n")
|
||||
gen_hdr(source)
|
||||
source.write("=\n{\n")
|
||||
for char in used_chars:
|
||||
gen_char(source,char)
|
||||
source.write("};\n")
|
||||
|
||||
gen_map_hdr(source)
|
||||
source.write("=\n{\n")
|
||||
for char in used_chars:
|
||||
gen_map_char(source,char)
|
||||
gen_map_char(source,"\\0")
|
||||
source.write("};\n")
|
||||
|
||||
|
||||
header.write("/*autogenerated file*/\n")
|
||||
header.write("#ifndef FONT_H\n")
|
||||
header.write("#define FONT_H\n")
|
||||
header.write("extern ")
|
||||
gen_hdr(header)
|
||||
header.write(";\n")
|
||||
header.write("extern ")
|
||||
gen_map_hdr(header)
|
||||
header.write(";\n")
|
||||
header.write("#endif\n")
|
||||
|
||||
24
prj.conf
Normal file
24
prj.conf
Normal file
@@ -0,0 +1,24 @@
|
||||
|
||||
CONFIG_DISPLAY=y
|
||||
|
||||
CONFIG_MULTITHREADING=y
|
||||
CONFIG_UART_INTERRUPT_DRIVEN=y
|
||||
CONFIG_UART_0_INTERRUPT_DRIVEN=y
|
||||
CONFIG_CPLUSPLUS=y
|
||||
|
||||
CONFIG_BT=y
|
||||
CONFIG_BT_CENTRAL=y
|
||||
CONFIG_BT_GATT_CLIENT=y
|
||||
|
||||
CONFIG_BT_BUF_ACL_RX_SIZE=255
|
||||
CONFIG_BT_BUF_ACL_TX_SIZE=251
|
||||
CONFIG_BT_BUF_CMD_TX_SIZE=255
|
||||
CONFIG_BT_BUF_EVT_DISCARDABLE_SIZE=255
|
||||
|
||||
CONFIG_BT_L2CAP_TX_MTU=247
|
||||
|
||||
CONFIG_MODBUS=y
|
||||
CONFIG_MODBUS_ROLE_CLIENT=y
|
||||
|
||||
CONFIG_DEBUG_THREAD_INFO=y
|
||||
CONFIG_EXTRA_EXCEPTION_INFO=y
|
||||
15
scripts/aaa.py
Executable file
15
scripts/aaa.py
Executable file
@@ -0,0 +1,15 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import tlay2_client
|
||||
import socket
|
||||
|
||||
conn = tlay2_client.Tlay2_out(0)
|
||||
|
||||
while True:
|
||||
packet = conn.recv()
|
||||
if packet == b'[SUBSCRIBED]\n':
|
||||
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
|
||||
s.connect(("127.0.0.1",4444))
|
||||
s.send(b"reset\n")
|
||||
s.close()
|
||||
27
scripts/tlay2_client.py
Normal file
27
scripts/tlay2_client.py
Normal file
@@ -0,0 +1,27 @@
|
||||
|
||||
import socket
|
||||
|
||||
class Tlay2_out():
|
||||
def __init__(self,fnaddr):
|
||||
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
self.s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
|
||||
self.s.bind(("127.255.255.255",12349))
|
||||
self.fnaddr = fnaddr
|
||||
def recv(self):
|
||||
while True:
|
||||
buff=self.s.recv(1024)
|
||||
if buff[0] == self.fnaddr:
|
||||
return buff[1:]
|
||||
|
||||
class Tlay2_msg():
|
||||
def __init__(self,fnaddr):
|
||||
self.s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
self.s.connect(("127.0.0.1",12348))
|
||||
self.s.settimeout(2)
|
||||
self.fnaddr = bytes([fnaddr])
|
||||
def msgout(self,payload):
|
||||
self.s.send(self.fnaddr+payload)
|
||||
def msg(self,payload):
|
||||
self.msgout(payload)
|
||||
return self.s.recv(1024)[1:]
|
||||
10
scripts/tlay2_dbgout.py
Executable file
10
scripts/tlay2_dbgout.py
Executable file
@@ -0,0 +1,10 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
|
||||
import tlay2_client
|
||||
|
||||
conn = tlay2_client.Tlay2_out(0)
|
||||
|
||||
while True:
|
||||
packet = conn.recv()
|
||||
print(packet)
|
||||
74
scripts/tlay2_server.py
Executable file
74
scripts/tlay2_server.py
Executable file
@@ -0,0 +1,74 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import sys
|
||||
import serial
|
||||
import crcmod
|
||||
import threading
|
||||
import socket
|
||||
import os
|
||||
|
||||
ser = serial.Serial(sys.argv[1], 115200)
|
||||
|
||||
crc8 = crcmod.predefined.mkCrcFun('crc-8')
|
||||
|
||||
connections = {}
|
||||
|
||||
my_mutex = threading.Event()
|
||||
my_mutex.set()
|
||||
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s.bind(("127.0.0.1",12348))
|
||||
|
||||
s2 = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
s2.setsockopt(socket.SOL_SOCKET, socket.SO_BROADCAST, 1)
|
||||
s2.connect(("127.255.255.255",12349))
|
||||
|
||||
def udprecv():
|
||||
global connections
|
||||
global my_mutex
|
||||
curid = 1
|
||||
while True:
|
||||
data, addr = s.recvfrom(1024)
|
||||
#print("Sending:",data)
|
||||
buff=b''
|
||||
data = bytes([curid]) + data
|
||||
data += bytes([crc8(data)])
|
||||
connections[curid]= addr
|
||||
curid+=1
|
||||
if curid == 256:
|
||||
curid = 1
|
||||
for byte in data:
|
||||
if byte == 0x0a or byte == 0xdc:
|
||||
buff+=bytes([0xdc])
|
||||
byte ^= 0x80
|
||||
buff+=bytes([byte])
|
||||
buff+=b'\n'
|
||||
my_mutex.wait(1.5)
|
||||
my_mutex.clear()
|
||||
ser.write(buff)
|
||||
|
||||
|
||||
t1 = threading.Thread(target = udprecv)
|
||||
|
||||
t1.start()
|
||||
|
||||
buff=b""
|
||||
while True:
|
||||
c= ser.read()
|
||||
if c == b'\n':
|
||||
if len(buff) < 3:
|
||||
print("Too short packet",buff)
|
||||
elif crc8(buff) != 0:
|
||||
print("CRC ERROR")
|
||||
else:
|
||||
#print("Recv:",buff[1:-1])
|
||||
if buff[0] == 0:
|
||||
s2.send(buff[1:-1])
|
||||
else:
|
||||
my_mutex.set()
|
||||
s.sendto(buff[1:-1],connections[buff[0]])
|
||||
buff = b""
|
||||
continue
|
||||
if c == b"\xdc":
|
||||
c = bytes([(ser.read()[0] ^ 0x80)])
|
||||
buff+=c
|
||||
549
src/bt.c
Normal file
549
src/bt.c
Normal file
@@ -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);
|
||||
23
src/bt.h
Normal file
23
src/bt.h
Normal file
@@ -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_ */
|
||||
67
src/display.cpp
Normal file
67
src/display.cpp
Normal file
@@ -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)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
28
src/display.hpp
Normal file
28
src/display.hpp
Normal file
@@ -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_ */
|
||||
69
src/fifo.hpp
Normal file
69
src/fifo.hpp
Normal file
@@ -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
src/font.c
Normal file
52
src/font.c
Normal file
@@ -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',
|
||||
};
|
||||
6
src/font.h
Normal file
6
src/font.h
Normal file
@@ -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
src/main.cpp
Normal file
122
src/main.cpp
Normal file
@@ -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;
|
||||
}
|
||||
|
||||
39
src/main_modules.hpp
Normal file
39
src/main_modules.hpp
Normal file
@@ -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_ */
|
||||
22
src/printt.h
Normal file
22
src/printt.h
Normal file
@@ -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
src/tlay2.hpp
Normal file
189
src/tlay2.hpp
Normal file
@@ -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
|
||||
24
src/uart.cpp
Normal file
24
src/uart.cpp
Normal file
@@ -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
src/uart.hpp
Normal file
104
src/uart.hpp
Normal file
@@ -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