Skip to content
Snippets Groups Projects
Commit 2e9d36ca authored by Grzegorz Gwóźdź's avatar Grzegorz Gwóźdź
Browse files

Rewriting doorlock to C++, keeping old files in src/archive/


Signed-off-by: default avatarGrzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
parent 76036311
No related branches found
No related tags found
No related merge requests found
......@@ -2,9 +2,16 @@
# SPDX-FileCopyrightText: Huawei Inc.
# SPDX-License-Identifier: Apache-2.0
# Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
# Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
set(CMAKE_CXX_STANDARD 11)
set(CMAKE_CXX_STANDARD_REQUIRED True)
cmake_minimum_required(VERSION 3.16.5)
find_package(Zephyr REQUIRED HINTS $ENV{ZEPHYR_BASE})
project(doorlock)
project(doorlock LANGUAGES CXX)
target_sources(app PRIVATE src/main.cpp src/led_light.cpp src/solenoid_doorlock.cpp
src/rotating_doorlock.cpp src/led_doorlock.cpp src/led_rot_doorlock.cpp src/doorlock.cpp)
target_sources(app PRIVATE src/main.c src/led.c src/kbd.c src/lock_solenoid.c src/lock_rotating.c src/debugconsole.c src/storage.c)
Kconfig 0 → 100644
# Copyright (c) 2022 Huawei Inc.
# SPDX-License-Identifier: Apache-2.0
mainmenu "Input devices and doorlock classes"
menu "Input devices settings"
config KBD_INPUT
bool "Enable keypad input"
help
Enable the keypad input
config SHELL_INPUT
bool "Enable shell input"
help
Enable the shell input
select SHELL
config COAP_INPUT
bool "Enable CoAP input"
help
Enable the CoAP input
config LED_DOORLOCK
bool "Enable led doorlock"
help
Enable the led doorlock
config LED_ROT_DOORLOCK
bool "Enable led rotating doorlock"
help
Enable the led rotating doorlock
config SOLENOID_DOORLOCK
bool "Enable solenoid doorlock"
help
Enable the solenoid doorlock
config ROTATING_DOORLOCK
bool "Enable rotating doorlock"
help
Enable the rotating doorlock
endmenu
source "Kconfig.zephyr"
Code for the doorlock is available in src/
In src/archive there is deprecated version in C,
the new version is implemented in C++,
using object-oriented programming
and zephyr
......@@ -100,17 +100,8 @@
kbd6 = &kbd6;
};
chosen {
zephyr,console = &cdc_acm_uart0;
};
};
/* This is for compatibility with Zephyr 2.6.
Remove the next section once we require 2.7. */
zephyr_udc0: &usbd {
compatible = "nordic,nrf-usbd";
status = "okay";
};
&zephyr_udc0 {
cdc_acm_uart0: cdc_acm_uart0 {
......
# SPDX-FileCopyrightText: Huawei Inc.
#
# SPDX-License-Identifier: Apache-2.0
CONFIG_GPIO=y
CONFIG_FLASH=y
......@@ -5,14 +9,119 @@ CONFIG_FLASH_PAGE_LAYOUT=y
CONFIG_NVS=y
CONFIG_MPU_ALLOW_FLASH_WRITE=y
CONFIG_PRINTK=y
CONFIG_HEAP_MEM_POOL_SIZE=256
CONFIG_HEAP_MEM_POOL_SIZE=4096
CONFIG_ASSERT=y
CONFIG_EXCEPTIONS=y
# For debugging
CONFIG_USB_DEVICE_STACK=y
CONFIG_USB_DEVICE_PRODUCT="Doorlock debugging console"
CONFIG_SERIAL=y
CONFIG_USB_CDC_ACM=y
CONFIG_UART_LINE_CTRL=y
CONFIG_UART_CONSOLE=y
CONFIG_USB_CDC_ACM=y
CONFIG_CONSOLE_SUBSYS=y
CONFIG_CONSOLE_GETLINE=y
CONFIG_CPLUSPLUS=y
CONFIG_LIB_CPLUSPLUS=y
CONFIG_STD_CPP17=y
CONFIG_NEWLIB_LIBC_NANO=n
CONFIG_NETWORKING=y
CONFIG_NET_SOCKETS=y
CONFIG_POSIX_API=y
CONFIG_NET_SOCKETS_POSIX_NAMES=y
CONFIG_NET_SOCKETPAIR=y
# Disable default configs
CONFIG_BT=n
CONFIG_NET_L2_ETHERNET=n
CONFIG_NET_L2_IEEE802154=n
CONFIG_NET_TCP=n
CONFIG_NET_IPV4=n
CONFIG_NET_DHCPV4=n
CONFIG_NET_IPV6_NBR_CACHE=n
CONFIG_NET_IPV6_MLD=y
# Kernel options
CONFIG_MAIN_STACK_SIZE=8192
CONFIG_SYSTEM_WORKQUEUE_STACK_SIZE=2048
CONFIG_ENTROPY_GENERATOR=y
CONFIG_INIT_STACKS=y
CONFIG_NEWLIB_LIBC=y
# Logging
CONFIG_NET_LOG=y
CONFIG_LOG=y
CONFIG_NET_STATISTICS=y
CONFIG_PRINTK=y
# Network buffers
CONFIG_NET_PKT_RX_COUNT=16
CONFIG_NET_PKT_TX_COUNT=16
CONFIG_NET_BUF_RX_COUNT=100
CONFIG_NET_BUF_TX_COUNT=100
CONFIG_NET_CONTEXT_NET_PKT_POOL=y
# IP address options
CONFIG_NET_IF_UNICAST_IPV6_ADDR_COUNT=5
CONFIG_NET_IF_MCAST_IPV6_ADDR_COUNT=10
CONFIG_NET_MAX_CONTEXTS=10
CONFIG_NET_CONFIG_SETTINGS=y
CONFIG_NET_CONFIG_NEED_IPV6=y
CONFIG_NET_CONFIG_MY_IPV6_ADDR="2001:db8:0:1::1"
CONFIG_NET_CONFIG_PEER_IPV6_ADDR="2001:db8:0:1::2"
CONFIG_NET_CONFIG_NEED_IPV4=n
CONFIG_NET_CONFIG_MY_IPV4_ADDR=""
CONFIG_NET_CONFIG_PEER_IPV4_ADDR=""
# TLS configuration
CONFIG_MBEDTLS=y
CONFIG_MBEDTLS_BUILTIN=y
CONFIG_MBEDTLS_ENABLE_HEAP=y
CONFIG_MBEDTLS_HEAP_SIZE=60000
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=2048
CONFIG_NET_SOCKETS_SOCKOPT_TLS=y
CONFIG_NET_SOCKETS_TLS_MAX_CONTEXTS=4
CONFIG_NET_SOCKETS_ENABLE_DTLS=y
CONFIG_POSIX_MAX_FDS=8
CONFIG_MBEDTLS_SSL_MAX_CONTENT_LEN=768
# Enable shell (including net and OpenThread)
CONFIG_SHELL=y
CONFIG_NET_SHELL=y
CONFIG_OPENTHREAD_SHELL=y
CONFIG_SHELL_STACK_SIZE=3072
# OpenThread support
CONFIG_NET_L2_OPENTHREAD=y
CONFIG_OPENTHREAD_DEBUG=y
CONFIG_OPENTHREAD_L2_DEBUG=y
CONFIG_OPENTHREAD_L2_LOG_LEVEL_INF=y
# Default values used on OTBR
# PAN ID 0x1357 to decimal 4951
CONFIG_OPENTHREAD_PANID=4951
CONFIG_OPENTHREAD_CHANNEL=26
CONFIG_OPENTHREAD_NETWORK_NAME="OniroThread"
CONFIG_OPENTHREAD_XPANID="0x11112222deadbeef"
CONFIG_OPENTHREAD_JOINER=y
CONFIG_OPENTHREAD_JOINER_AUTOSTART=y
CONFIG_OPENTHREAD_JOINER_PSKD="J01NU5"
CONFIG_OPENTHREAD_SLAAC=y
CONFIG_OPENTHREAD_THREAD_VERSION_1_2=y
CONFIG_NET_MGMT_EVENT_INFO=y
CONFIG_COAP=y
CONFIG_COAP_WELL_KNOWN_BLOCK_WISE=n
CONFIG_NET_UDP=y
CONFIG_KBD_INPUT=y
CONFIG_SHELL_INPUT=y
CONFIG_COAP_INPUT=y
CONFIG_LED_DOORLOCK=y
CONFIG_LED_ROT_DOORLOCK=y
CONFIG_SOLENOID_DOORLOCK=y
CONFIG_ROTATING_DOORLOCK=y
......@@ -13,11 +13,12 @@
#include <drivers/gpio.h>
static inline int gpio_pin_get_dt(const struct gpio_dt_spec *spec)
{
return gpio_pin_get(spec->port, spec->pin);
return gpio_pin_get(spec->port, spec->pin);
}
static inline int gpio_pin_set_dt(const struct gpio_dt_spec *spec, int value)
{
return gpio_pin_set(spec->port, spec->pin, value);
return gpio_pin_set(spec->port, spec->pin, value);
}
#endif
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
*/
#include "debugconsole.h"
int debugconsole_init() {
const struct device *dev = device_get_binding(DT_LABEL(DT_CHOSEN(zephyr_console))); // Once we drop support for < 2.7: DEVICE_DT_GET(DT_CHOSEN(zephyr_console));
uint32_t dtr = 0;
uint32_t retries = 0;
if (usb_enable(NULL)) {
return 1;
}
/* Poll if the DTR flag was set
* Time out after 2 seconds -- we might be
* connected to a power supply only
*/
while (!dtr && (retries++ < 20)) {
uart_line_ctrl_get(dev, UART_LINE_CTRL_DTR, &dtr);
/* Give CPU resources to low priority threads. */
k_sleep(K_MSEC(100));
}
return !dtr;
}
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
*/
#pragma once
#ifndef NDEBUG
#include <usb/usb_device.h>
#include <drivers/uart.h>
BUILD_ASSERT(DT_NODE_HAS_COMPAT(DT_CHOSEN(zephyr_console), zephyr_cdc_acm_uart),
"Console device is not ACM CDC UART device");
int debugconsole_init();
#else
static int debugconsole_init() { }
#endif
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
* Luca Seritan <luca.seritan@huawei.com>
*/
#include <drivers/gpio.h>
#include <sys/printk.h>
#include "doorlock.hpp"
doorlock::doorlock() : _m_state(locking_state::UNLOCKED) { }
void doorlock::lock()
{
if (this->is_locked())
return;
this->_m_state = locking_state::LOCKED;
}
void doorlock::unlock()
{
if (!this->is_locked())
return;
this->_m_state = locking_state::UNLOCKED;
}
bool doorlock::is_locked()
{
return this->_m_state == locking_state::LOCKED;
}
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
* Luca Seritan <luca.seritan@huawei.com>
*/
#ifndef DOORLOCK_HPP
#define DOORLOCK_HPP
#include <drivers/gpio.h>
#include <sys/printk.h>
/**
* @brief Enum for state of lock
* It tracks what is the current
* state of the doorlock, it is useful
* to tell whether there is a need
* to start locking/unlocking
* or it is irrelevant
*/
enum class locking_state
{
UNLOCKED = 1,
LOCKED = 2
};
class doorlock
{
public:
/**
* @brief Construct a new doorlock object
*
*/
doorlock();
/**
* @brief Unlock the doorlock
*/
virtual void unlock();
/**
* @brief Locking the doorlocklock
*/
virtual void lock();
/**
* @brief State of lock
* @return true if it is locked
* false otherwise
*/
bool is_locked();
protected:
locking_state _m_state;
};
#endif
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
*/
#include "kbd.h"
#include "led.h"
#include "compat.h"
#include <drivers/gpio.h>
#include <sys/printk.h>
#include <string.h>
static const struct gpio_dt_spec kbd[7] = {
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd0), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd1), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd2), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd3), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd4), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd5), gpios, {0}),
GPIO_DT_SPEC_GET_OR(DT_ALIAS(kbd6), gpios, {0})
};
static const int col_pins[3] = { 6, 2, 1 };
static const int row_pins[4] = { 5, 0, 4, 3 };
static const char keys[4][3] = {
{ '1', '2', '3' },
{ '4', '5', '6' },
{ '7', '8', '9' },
{ '*', '0', '#' }
};
static char pressedKeys[13];
int kbd_init() {
for(int i=0; i<7; i++)
gpio_pin_configure_dt(&kbd[i], GPIO_INPUT | GPIO_PULL_UP);
return 0;
}
char *kbd_scanKeys() {
memset(pressedKeys, 0, 13);
for(int i=0; i<7; i++)
gpio_pin_configure_dt(&kbd[i], GPIO_INPUT | GPIO_PULL_UP);
for(int row=0; row<4; row++) {
gpio_pin_configure_dt(&kbd[row_pins[row]], GPIO_OUTPUT);
gpio_pin_set_dt(&kbd[row_pins[row]], 0);
for(int col=0; col<3; col++) {
if(!gpio_pin_get_dt(&kbd[col_pins[col]]))
pressedKeys[strlen(pressedKeys)] = keys[row][col];
}
gpio_pin_configure_dt(&kbd[row_pins[row]], GPIO_INPUT | GPIO_PULL_UP);
}
return pressedKeys;
}
void kbd_wait_for_release() {
while(kbd_scanKeys()[0] != 0)
k_msleep(100);
}
void kbd_wait_for_key_release(char key) {
while(strchr(kbd_scanKeys(), key))
k_msleep(100);
}
char *kbd_get(int timeout) {
char *ret = k_malloc(13);
memset(ret, 0, 13);
char previous[13];
*previous=0;
while(1) {
char *keys = kbd_scanKeys();
if(keys && *keys) {
if(!*ret) {
strcpy(ret, keys);
} else {
for(int i=0; i<strlen(keys); i++) {
if(!strchr(ret, keys[i]))
ret[strlen(ret)]=keys[i];
}
}
strcpy(previous, keys);
} else if(ret[0]) {
return ret;
}
k_msleep(100);
if(timeout) {
timeout -= 100;
if(timeout <= 0) {
k_free(ret);
return NULL;
}
}
}
}
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
*/
#pragma once
/**
* Initialize the keyboard
*/
int kbd_init();
/**
* scan pressed keys
* @return all currently pressed keys
*/
char *kbd_scanKeys();
/**
* wait until all keys are released
*/
void kbd_wait_for_release();
/**
* wait until a specific key is released
* @param key key to wait for
*/
void kbd_wait_for_key_release(char key);
/**
* Get a key sequence from the keyboard.
* A key sequence is considered complete when at least
* one key has been pressed and all keys have been
* released.
* e.g. just pressing 1 will result in "1".
* Pressing and holding 1, then pressing 2 and 3
* and releasing everything will result in "123".
* Every possible key is counted only once, so
* pressing and holding 1 while pressing 2324
* will result in 1234, not 12324.
* @param timeout timeout in milliseconds (0: no timeout)
* @return key sequence or NULL on timeout. Has to be freed with k_free.
*/
char *kbd_get(int timeout);
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
*/
#include "led.h"
#include "compat.h"
#include <zephyr.h>
#include <drivers/gpio.h>
#include <sys/printk.h>
#include <string.h>
#define LED0_NODE DT_ALIAS(led0)
#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
static struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET_OR(LED0_NODE, gpios, {0});
#else
#warning led0 not defined in devicetree, LED commands will be ignored
static struct gpio_dt_spec led0 = { NULL, 0, 0 };
#endif
enum led_status __led_status;
K_FIFO_DEFINE(led_blink_thread_control);
struct led_blink_thread_msg_t {
void *fifo_reserved;
int frequency;
};
static void led_blink_thread_handler(void *p1, void *p2, void *p3) {
while(1) {
struct led_blink_thread_msg_t *data = (struct led_blink_thread_msg_t*)k_fifo_get(&led_blink_thread_control, K_FOREVER);
int frequency = data->frequency;
k_free(data);
while(frequency) {
led_toggle();
data = k_fifo_get(&led_blink_thread_control, K_MSEC(frequency));
if(data) {
frequency = data->frequency;
k_free(data);
}
}
led_off();
}
}
K_THREAD_DEFINE(led_blink_thread, 512, led_blink_thread_handler, NULL, NULL, NULL, 7, 0, 0);
int led_init() {
if(led0.port && !device_is_ready(led0.port)) {
printk("LED led0 not ready, LED commands will be ignored\n");
led0.port = NULL;
}
if(led0.port) {
gpio_pin_configure_dt(&led0, GPIO_OUTPUT);
gpio_pin_set_dt(&led0, 1);
return 0;
} else {
return ENODEV;
}
}
void led_on() {
gpio_pin_set_dt(&led0, 0);
__led_status |= 1;
}
void led_off() {
gpio_pin_set_dt(&led0, 1);
__led_status &= ~1;
}
void led_toggle() {
gpio_pin_set_dt(&led0, __led_status&1);
__led_status ^= 1;
}
void led_blink() {
led_toggle();
k_msleep(500);
led_toggle();
k_msleep(500);
}
void led_start_blinking(int frequency) {
if(!frequency && !(__led_status&BLINKING))
return;
struct led_blink_thread_msg_t msg = { .frequency = frequency };
const size_t size = sizeof(struct led_blink_thread_msg_t);
char *mem = k_malloc(size);
memcpy(mem, &msg, size);
k_fifo_put(&led_blink_thread_control, mem);
if(frequency)
__led_status |= BLINKING;
else
__led_status &= ~BLINKING;
}
void led_stop_blinking() {
led_start_blinking(0);
}
enum led_status led_status() {
return __led_status;
}
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#include "led.hpp"
#include "compat.h"
#include <drivers/gpio.h>
#include <string.h>
#include <sys/printk.h>
#include <zephyr.h>
#define LED0_NODE DT_ALIAS(led0)
#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
static struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET_OR(LED0_NODE, gpios, {0});
#else
#warning led0 not defined in devicetree, LED commands will be ignored
static gpio_dt_spec led0 = {NULL, 0, 0};
#endif
int __led_status = 0x00;
K_FIFO_DEFINE(led_blink_thread_control);
struct led_blink_thread_msg_t
{
void *fifo_reserved;
int frequency;
};
namespace {
void led_blink_thread_handler(void *p1, void *p2, void *p3)
{
while (1) {
struct led_blink_thread_msg_t *data =
(struct led_blink_thread_msg_t *)k_fifo_get(&led_blink_thread_control,
K_FOREVER);
int frequency = data->frequency;
k_free(data);
while (frequency) {
led_toggle();
data = (led_blink_thread_msg_t *)k_fifo_get(&led_blink_thread_control,
K_MSEC(frequency));
if (data)
{
frequency = data->frequency;
k_free(data);
}
}
led_off();
}
}
} /* namespace */
K_THREAD_DEFINE(led_blink_thread, 512, led_blink_thread_handler, NULL, NULL,
NULL, 7, 0, 0);
void led_init()
{
if (led0.port && !device_is_ready(led0.port)) {
printk("LED led0 not ready, LED commands will be ignored\n");
led0.port = NULL;
}
if (led0.port) {
gpio_pin_configure_dt(&led0, GPIO_OUTPUT);
gpio_pin_set_dt(&led0, 1);
}
else {
throw(ENODEV);
}
}
void led_on()
{
gpio_pin_set_dt(&led0, 0);
__led_status |= 1;
}
void led_off()
{
gpio_pin_set_dt(&led0, 1);
__led_status &= ~1;
}
void led_toggle()
{
gpio_pin_set_dt(&led0, __led_status & 1);
__led_status ^= 1;
}
void led_blink()
{
printk("%d ", __led_status);
led_toggle();
k_msleep(500);
led_toggle();
k_msleep(500);
}
void led_start_blinking(int frequency)
{
if (!frequency && !(__led_status & int(led_status::BLINKING)))
return;
struct led_blink_thread_msg_t msg = {.frequency = frequency};
const size_t size = sizeof(struct led_blink_thread_msg_t);
char *mem = (char *)k_malloc(size);
memcpy(mem, &msg, size);
k_fifo_put(&led_blink_thread_control, mem);
if (frequency)
__led_status |= int(led_status::BLINKING);
else
__led_status &= ~int(led_status::BLINKING);
}
void led_stop_blinking()
{
led_start_blinking(0);
}
int led_status()
{
return __led_status;
}
......@@ -6,42 +6,51 @@
#pragma once
enum led_status {
enum class led_status
{
OFF = 0x00,
ON = 0x01,
BLINKING = 0x02
};
/**
* Initialize the LED
* @brief Initialize the LED
*/
int led_init();
void led_init();
/**
* Turn the LED on
* @brief Turn the LED on
*/
void led_on();
/**
* Turn the LED off
* @brief Turn the LED off
*/
void led_off();
/**
* Toggle the LED
* @brief Toggle the LED
*/
void led_toggle();
/**
* Blink the LED once (toggle for 1 second, then toggle back)
* @brief Blink the LED once (toggle for 1 second, then toggle back)
*/
void led_blink();
/**
* Start blinking the LED
* @brief Start blinking the LED
* @param frequency frequency in milliseconds
*/
void led_start_blinking(int frequency);
/**
* Stop blinking the LED
* @brief Stop blinking the LED
*/
void led_stop_blinking();
/**
* Get the status of the LED
* @brief Get the status of the LED
* @return Status of the LED
*/
enum led_status led_status();
int led_status();
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#ifdef CONFIG_LED_DOORLOCK
#include "led_doorlock.hpp"
/**
* @brief Lock Led implementation
* It's not even a real doorlock, its sole purpose
* is to test the class implementation introduced in the new version
*/
led_doorlock::led_doorlock() : doorlock(),
_led_light()
{
}
void led_doorlock::unlock()
{
this->doorlock::unlock();
this->_led_light.led_off();
}
void led_doorlock::lock()
{
this->doorlock::lock();
this->_led_light.led_on();
}
#endif
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#ifdef CONFIG_LED_DOORLOCK
#ifndef LED_DOORLOCK_HPP
#define LED_DOORLOCK_HPP
#include "doorlock.hpp"
#include "led_light.hpp"
class led_doorlock : public doorlock
{
public:
led_doorlock();
virtual void unlock();
virtual void lock();
private:
/**
* @brief Light object
* Object used for led light
*/
led_light _led_light;
const device *Pin0, *Pin1;
};
#endif //LED_DOORLOCK_HPP
#endif //CONFIG_LED_DOORLOCK
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#include "led_light.hpp"
#include "compat.h"
#include <zephyr.h>
#include <drivers/gpio.h>
#include <string.h>
#include <sys/printk.h>
#define LED0_NODE DT_ALIAS(led0)
#if DT_NODE_HAS_STATUS(LED0_NODE, okay)
static struct gpio_dt_spec led0 = GPIO_DT_SPEC_GET_OR(LED0_NODE, gpios, {0});
#else
#warning led0 not defined in devicetree, LED commands will be ignored
static struct gpio_dt_spec led0 = {NULL, 0, 0};
#endif
K_FIFO_DEFINE(led_blink_thread_control);
struct led_blink_thread_msg_t
{
void *fifo_reserved;
int frequency;
};
namespace {
void led_blink_thread_handler(void *__led_pointer, void *p2, void *p3)
{
led_light * led_pointer = reinterpret_cast <led_light *> (__led_pointer);
while (1) {
led_blink_thread_msg_t *data = reinterpret_cast <led_blink_thread_msg_t *>
(k_fifo_get(&led_blink_thread_control, K_FOREVER));
int frequency = data->frequency;
k_free(data);
while (frequency) {
led_pointer->led_toggle();
data = reinterpret_cast <led_blink_thread_msg_t *>
(k_fifo_get(&led_blink_thread_control, K_MSEC(frequency)));
if (data) {
frequency = data->frequency;
k_free(data);
}
}
led_pointer->led_off();
}
}
K_THREAD_STACK_DEFINE(led_stack_area, 512);
} /* namespace */
led_light::led_light()
{
this->__led_status = 0x00;
void * __this = reinterpret_cast <void *> (this);
led_tid = k_thread_create(&led_thread_data, led_stack_area,
K_THREAD_STACK_SIZEOF(led_stack_area),
led_blink_thread_handler,
__this, NULL, NULL,
7, 0, K_NO_WAIT);
if (led0.port && !device_is_ready(led0.port)) {
printk("LED led0 not ready, LED commands will be ignored\n");
led0.port = NULL;
}
if (led0.port) {
gpio_pin_configure_dt(&led0, GPIO_OUTPUT);
gpio_pin_set_dt(&led0, 1);
}
else {
throw(ENODEV);
}
}
void led_light::led_on()
{
gpio_pin_set_dt(&led0, 0);
this->__led_status |= 1;
}
void led_light::led_off()
{
gpio_pin_set_dt(&led0, 1);
this->__led_status &= ~1;
}
void led_light::led_toggle()
{
gpio_pin_set_dt(&led0, this->__led_status & 1);
this->__led_status ^= 1;
}
void led_light::led_blink()
{
printk("%d ", this->__led_status);
this->led_toggle();
k_msleep(500);
this->led_toggle();
k_msleep(500);
}
void led_light::led_start_blinking(int frequency)
{
if (!frequency && !(this->__led_status & int(led_status::BLINKING)))
return;
struct led_blink_thread_msg_t msg = {.frequency = frequency};
const size_t size = sizeof(struct led_blink_thread_msg_t);
char *mem = reinterpret_cast <char *> (k_malloc(size));
memcpy(mem, &msg, size);
k_fifo_put(&led_blink_thread_control, mem);
if (frequency)
this->__led_status |= int(led_status::BLINKING);
else
this->__led_status &= ~int(led_status::BLINKING);
}
void led_light::led_stop_blinking()
{
this->led_start_blinking(0);
}
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#ifndef LED_LIGHT_HPP
#define LED_LIGHT_HPP
#include <zephyr.h>
#include <drivers/gpio.h>
enum class led_status
{
OFF = 0x00,
ON = 0x01,
BLINKING = 0x02
};
class led_light
{
private:
k_thread led_thread_data;
k_tid_t led_tid;
/**
* @brief Status of the LED
*/
int __led_status;
public:
/**
* @brief Initialize the LED
*/
led_light();
/**
* @brief Turn the LED on
*/
void led_on();
/**
* @brief Turn the LED off
*/
void led_off();
/**
* @brief Toggle the LED
*/
void led_toggle();
/**
* @brief Blink the LED once (toggle for 1 second, then toggle back)
*/
void led_blink();
/**
* @brief Start blinking the LED
* @param frequency frequency in milliseconds
*/
void led_start_blinking(int frequency);
/**
* @brief Stop blinking the LED
*/
void led_stop_blinking();
};
#endif
/* Copyright (C) 2021 Huawei Inc.
* SPDX-FileCopyrightText: Huawei Inc.
* SPDX-License-Identifier: Apache-2.0
* Bernhard Rosenkraenzer <bernhard.rosenkraenzer.ext@huawei.com>
* Grzegorz Gwozdz <grzegorz.gwozdz@huawei.com>
*/
#ifdef CONFIG_LED_ROT_DOORLOCK
#include "led_rot_doorlock.hpp"
#include "doorlock.hpp"
#include "led_light.hpp"
#include <zephyr/logging/log.h>
#define DOORLOCK0_NODE DT_ALIAS(doorlock0)
#if DT_NODE_HAS_STATUS(DOORLOCK0_NODE, okay)
#define DOORLOCK0 DT_GPIO_LABEL(DOORLOCK0_NODE, gpios)
#define PIN0 DT_GPIO_PIN(DOORLOCK0_NODE, gpios)
#define FLAGS0 DT_GPIO_FLAGS(DOORLOCK0_NODE, gpios)
#else
#error "Unsupported board: doorlock0 devicetree alias is not defined"
#endif
#define DOORLOCK1_NODE DT_ALIAS(doorlock1)
#if DT_NODE_HAS_STATUS(DOORLOCK1_NODE, okay)
#define DOORLOCK1 DT_GPIO_LABEL(DOORLOCK1_NODE, gpios)
#define PIN1 DT_GPIO_PIN(DOORLOCK1_NODE, gpios)
#define FLAGS1 DT_GPIO_FLAGS(DOORLOCK1_NODE, gpios)
#else
#error "Unsupported board: doorlock1 devicetree alias is not defined"
#endif
#define CONFIG_LED_LOG_LEVEL 4
LOG_MODULE_DECLARE(led_rotating_doorlock, CONFIG_LED_LOG_LEVEL);
/**
* @brief Lock Rotating Led implementation
* It's not even a real doorlock, its sole purpose
* is to test the class implementation introduced in the new version
* This also tests CONTAINER_OF functionalities implemented
* in RotatingDoorlock class
*
* Right now, it prints in the console besides led lighting
*
*/
void lock_stop_led_rotating_timer_handler(k_timer *timer_id)
{
LOG_DBG("Got to this timer_handler...\n");
led_rotating_doorlock::timer_wrapper *wrapper =
CONTAINER_OF(timer_id, led_rotating_doorlock::timer_wrapper, timer);
wrapper->lock->lock_rotating_stop();
}
led_rotating_doorlock::led_rotating_doorlock() : doorlock(),
_led_light(),
wrapper(this)
{
LOG_INF("Initialized\n");
k_timer_init(&wrapper.timer, lock_stop_led_rotating_timer_handler, NULL);
}
void led_rotating_doorlock::lock_rotating_rotate_clockwise()
{
this->_led_light.led_on();
LOG_INF("Locking...\n");
}
void led_rotating_doorlock::lock_rotating_rotate_counterclockwise()
{
this->_led_light.led_off();
LOG_INF("Unlocking...\n");
}
void led_rotating_doorlock::lock_rotating_stop()
{
LOG_DBG("Got to lock_rotating_stop!\n");
// No point in leaving an auto-stop running if we've already stopped it
k_timer_stop(&wrapper.timer);
}
void led_rotating_doorlock::unlock()
{
this->doorlock::unlock();
this->lock_rotating_rotate_counterclockwise();
k_timer_start(&wrapper.timer, K_SECONDS(1), K_NO_WAIT);
}
void led_rotating_doorlock::lock()
{
this->doorlock::lock();
this->lock_rotating_rotate_clockwise();
// It takes roughly 13 seconds to go from fully open to fully closed
// but for the testing purpose we are waiting only 1 second
k_timer_start(&wrapper.timer, K_SECONDS(1), K_NO_WAIT);
}
void led_rotating_doorlock::unlock_lock(int time)
{
this->lock();
//we have to wait for at least a second
if (time < 1)
time = 1;
k_timer_start(&wrapper.timer, K_SECONDS(time), K_NO_WAIT);
this->unlock();
}
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment