mirror of https://github.com/ARMmbed/mbed-os.git
251 lines
7.5 KiB
C++
251 lines
7.5 KiB
C++
/* mbed Microcontroller Library
|
|
* Copyright (c) 2017-2017 ARM Limited
|
|
* SPDX-License-Identifier: Apache-2.0
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#if DEVICE_SERIAL && DEVICE_SERIAL_FC
|
|
|
|
#include "CyH4TransportDriver.h"
|
|
#include "mbed_power_mgmt.h"
|
|
#include "drivers/InterruptIn.h"
|
|
#include "cybsp_types.h"
|
|
#include "Callback.h"
|
|
#include "rtos/ThisThread.h"
|
|
#include <chrono>
|
|
|
|
namespace ble {
|
|
namespace vendor {
|
|
namespace cypress_ble {
|
|
|
|
using namespace std::chrono_literals;
|
|
|
|
CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud, PinName bt_host_wake_name, PinName bt_device_wake_name, uint8_t host_wake_irq, uint8_t dev_wake_irq) :
|
|
cts(cts), rts(rts),
|
|
bt_host_wake_name(bt_host_wake_name),
|
|
bt_device_wake_name(bt_device_wake_name),
|
|
bt_host_wake(bt_host_wake_name, PIN_INPUT, PullNone, 0),
|
|
bt_device_wake(bt_device_wake_name, PIN_OUTPUT, PullNone, 1),
|
|
host_wake_irq_event(host_wake_irq),
|
|
dev_wake_irq_event(dev_wake_irq)
|
|
{
|
|
cyhal_uart_init(&uart, tx, rx, NULL, NULL);
|
|
enabled_powersave = true;
|
|
bt_host_wake_active = false;
|
|
}
|
|
|
|
CyH4TransportDriver::CyH4TransportDriver(PinName tx, PinName rx, PinName cts, PinName rts, int baud) :
|
|
cts(cts),
|
|
rts(rts),
|
|
bt_host_wake_name(NC),
|
|
bt_device_wake_name(NC),
|
|
bt_host_wake(bt_host_wake_name),
|
|
bt_device_wake(bt_device_wake_name)
|
|
{
|
|
cyhal_uart_init(&uart, tx, rx, NULL, NULL);
|
|
enabled_powersave = false;
|
|
bt_host_wake_active = false;
|
|
sleep_manager_lock_deep_sleep();
|
|
holding_deep_sleep_lock = true;
|
|
}
|
|
|
|
CyH4TransportDriver::~CyH4TransportDriver()
|
|
{
|
|
if (holding_deep_sleep_lock)
|
|
{
|
|
sleep_manager_unlock_deep_sleep();
|
|
holding_deep_sleep_lock = false;
|
|
}
|
|
}
|
|
|
|
void CyH4TransportDriver::bt_host_wake_rise_irq_handler(void)
|
|
{
|
|
if (host_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
|
|
if(bt_host_wake_active == true)
|
|
{
|
|
/* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */
|
|
sleep_manager_unlock_deep_sleep();
|
|
bt_host_wake_active = false;
|
|
}
|
|
} else {
|
|
/* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */
|
|
sleep_manager_lock_deep_sleep();
|
|
bt_host_wake_active = true;
|
|
}
|
|
}
|
|
|
|
void CyH4TransportDriver::bt_host_wake_fall_irq_handler(void)
|
|
{
|
|
if (host_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
|
|
/* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */
|
|
sleep_manager_lock_deep_sleep();
|
|
bt_host_wake_active = true;
|
|
} else {
|
|
if(bt_host_wake_active == true)
|
|
{
|
|
/* lock PSoC 6 DeepSleep entry as long as host_wake is asserted */
|
|
sleep_manager_unlock_deep_sleep();
|
|
bt_host_wake_active = false;
|
|
}
|
|
}
|
|
}
|
|
|
|
static void on_controller_irq(void *callback_arg, cyhal_uart_event_t event)
|
|
{
|
|
(void)(event);
|
|
cyhal_uart_t *uart_obj = (cyhal_uart_t *)callback_arg;
|
|
sleep_manager_lock_deep_sleep();
|
|
|
|
while (cyhal_uart_readable(uart_obj)) {
|
|
uint8_t char_received;
|
|
cyhal_uart_getc(uart_obj, &char_received, 0);
|
|
CyH4TransportDriver::on_data_received(&char_received, 1);
|
|
}
|
|
|
|
sleep_manager_unlock_deep_sleep();
|
|
}
|
|
|
|
void CyH4TransportDriver::initialize()
|
|
{
|
|
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
|
|
mbed::InterruptIn *host_wake_pin;
|
|
#endif
|
|
|
|
sleep_manager_lock_deep_sleep();
|
|
|
|
const cyhal_uart_cfg_t uart_cfg = { .data_bits = 8, .stop_bits = 1, .parity = CYHAL_UART_PARITY_NONE, .rx_buffer = NULL, .rx_buffer_size = 0 };
|
|
cyhal_uart_configure(&uart, &uart_cfg);
|
|
cyhal_uart_set_flow_control(&uart, cts, rts);
|
|
cyhal_uart_register_callback(&uart, &on_controller_irq, &uart);
|
|
cyhal_uart_enable_event(&uart, CYHAL_UART_IRQ_RX_NOT_EMPTY, CYHAL_ISR_PRIORITY_DEFAULT, true);
|
|
|
|
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
|
|
if (bt_host_wake_name != NC) {
|
|
//Register IRQ for Host WAKE
|
|
host_wake_pin = new mbed::InterruptIn(bt_host_wake_name);
|
|
host_wake_pin->fall(mbed::callback(this, &CyH4TransportDriver::bt_host_wake_fall_irq_handler));
|
|
host_wake_pin->rise(mbed::callback(this, &CyH4TransportDriver::bt_host_wake_rise_irq_handler));
|
|
}
|
|
#endif
|
|
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
|
|
if (bt_device_wake_name != NC)
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
|
|
} else {
|
|
if (bt_device_wake_name != NC)
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
|
|
}
|
|
sleep_manager_unlock_deep_sleep();
|
|
rtos::ThisThread::sleep_for(500ms);
|
|
}
|
|
|
|
void CyH4TransportDriver::terminate() { }
|
|
|
|
uint16_t CyH4TransportDriver::write(uint8_t type, uint16_t len, uint8_t *pData)
|
|
{
|
|
uint16_t i = 0;
|
|
|
|
sleep_manager_lock_deep_sleep();
|
|
assert_bt_dev_wake();
|
|
|
|
while (i < len + 1) {
|
|
uint8_t to_write = i == 0 ? type : pData[i - 1];
|
|
while (cyhal_uart_writable(&uart) == 0);
|
|
cyhal_uart_putc(&uart, to_write);
|
|
++i;
|
|
}
|
|
while(cyhal_uart_is_tx_active(&uart));
|
|
|
|
deassert_bt_dev_wake();
|
|
sleep_manager_unlock_deep_sleep();
|
|
return len;
|
|
}
|
|
|
|
void CyH4TransportDriver::assert_bt_dev_wake()
|
|
{
|
|
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
|
|
if (enabled_powersave) {
|
|
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
|
|
} else {
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void CyH4TransportDriver::deassert_bt_dev_wake()
|
|
{
|
|
#if (defined(MBED_TICKLESS) && DEVICE_SLEEP && DEVICE_LPTICKER)
|
|
if (enabled_powersave) {
|
|
if (dev_wake_irq_event == WAKE_EVENT_ACTIVE_LOW) {
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_HIGH;
|
|
} else {
|
|
bt_device_wake = WAKE_EVENT_ACTIVE_LOW;
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
|
|
void CyH4TransportDriver::update_uart_baud_rate(int baud)
|
|
{
|
|
uint32_t ignore;
|
|
cyhal_uart_set_baud(&uart, (uint32_t)baud, &ignore);
|
|
}
|
|
|
|
bool CyH4TransportDriver::get_enabled_powersave()
|
|
{
|
|
return (enabled_powersave);
|
|
}
|
|
|
|
uint8_t CyH4TransportDriver::get_host_wake_irq_event()
|
|
{
|
|
return (host_wake_irq_event);
|
|
}
|
|
|
|
uint8_t CyH4TransportDriver::get_dev_wake_irq_event()
|
|
{
|
|
return (dev_wake_irq_event);
|
|
}
|
|
|
|
|
|
} // namespace cypress_ble
|
|
} // namespace vendor
|
|
} // namespace ble
|
|
|
|
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_default_h4_transport_driver()
|
|
{
|
|
#if (defined(CYBSP_BT_HOST_WAKE) && defined(CYBSP_BT_DEVICE_WAKE))
|
|
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
|
|
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
|
|
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, DEF_BT_BAUD_RATE,
|
|
CYBSP_BT_HOST_WAKE, CYBSP_BT_DEVICE_WAKE
|
|
);
|
|
|
|
#else
|
|
static ble::vendor::cypress_ble::CyH4TransportDriver s_transport_driver(
|
|
/* TX */ CYBSP_BT_UART_TX, /* RX */ CYBSP_BT_UART_RX,
|
|
/* cts */ CYBSP_BT_UART_CTS, /* rts */ CYBSP_BT_UART_RTS, DEF_BT_BAUD_RATE);
|
|
#endif
|
|
return s_transport_driver;
|
|
}
|
|
|
|
MBED_WEAK
|
|
ble::vendor::cypress_ble::CyH4TransportDriver& ble_cordio_get_h4_transport_driver()
|
|
{
|
|
return (ble_cordio_get_default_h4_transport_driver());
|
|
}
|
|
|
|
#endif
|