Senet-ized LMIC for MOTE_L152RC
Fork of lmic_MOTE_L152RC by
TARGET_MOTE_L152RC/hal.cpp
- Committer:
- dkjendal
- Date:
- 2016-08-11
- Revision:
- 13:097c74da6ffe
- Parent:
- 9:83ae7f34e88c
File content as of revision 13:097c74da6ffe:
/* HAL for MOTE_L152RC */
#include "mbed.h"
#include "oslmic.h"
#include "debug.h"
#define RADIO_MOSI PB_15
#define RADIO_MISO PB_14
#define RADIO_SCLK PB_13
#define RADIO_NSS PB_12
#define RESET_PIN PC_2
#define RFSW1 PC_4 //NorAm_Mote RFSwitch_CNTR_1
#define RFSW2 PC_13 //NorAm_Mote RFSwitch_CNTR_2
static DigitalOut nss(RADIO_NSS);
static SPI spi(RADIO_MOSI, RADIO_MISO, RADIO_SCLK); // (mosi, miso, sclk)
static DigitalInOut rst(RESET_PIN);
DigitalOut rfsw1(RFSW1);
DigitalOut rfsw2(RFSW2);
DigitalOut hdr_fem_csd(PC_0);
static InterruptIn dio0(PC_6);
static InterruptIn dio1(PC_10);
static InterruptIn dio2(PC_11);
extern RTC_HandleTypeDef RtcHandle;
// HAL state
static struct {
int irqlevel;
} HAL;
void radio_irq_handler (u1_t dio);
static void dio0Irq( void ){
radio_irq_handler( 0 );
}
static void dio1Irq( void ){
radio_irq_handler( 1 );
}
static void dio2Irq( void ){
radio_irq_handler( 2 );
}
void hal_disableIRQs()
{
__disable_irq();
HAL.irqlevel++;
}
void hal_enableIRQs()
{
if (--HAL.irqlevel == 0) {
__enable_irq();
}
}
void hal_failed ()
{
while (1)
asm("nop");
}
static void rtc_wkup_irq(void)
{
HAL_RTCEx_WakeUpTimerIRQHandler(&RtcHandle);
}
void HAL_RTCEx_WakeUpTimerEventCallback(RTC_HandleTypeDef *hrtc)
{
/* Clear Wake Up Flag */
__HAL_PWR_CLEAR_FLAG(PWR_FLAG_WU);
}
/*void HAL_RCC_CCSCallback()
{
for (;;) asm("nop");
}*/
volatile uint32_t /*rcc_cr_a, rcc_cr_b,*/ rcc_cr_c;
void hal_init (void)
{
memset(&HAL, 0x00, sizeof(HAL));
hal_disableIRQs();
#if USE_SMTC_RADIO_DRIVER
#else
// configure input lines
dio0.mode(PullDown);
dio0.rise(dio0Irq);
dio0.enable_irq();
dio1.mode(PullDown);
dio1.rise(dio1Irq);
dio1.enable_irq();
dio2.mode(PullDown);
dio2.rise(dio2Irq);
dio2.enable_irq();
// configure reset line
rst.input();
// configure spi
spi.frequency(8000000);
spi.format(8, 0);
nss = 1;
//RFSwitch_CNTR_2 = 1;
#endif
set_time(0); // initialize RTC
/* Enable Ultra low power mode */
HAL_PWREx_EnableUltraLowPower();
/* Enable the fast wake up from Ultra low power mode */
HAL_PWREx_EnableFastWakeUp();
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
NVIC_SetVector(RTC_WKUP_IRQn, (uint32_t)rtc_wkup_irq);
NVIC_EnableIRQ(RTC_WKUP_IRQn);
hdr_fem_csd = 0;
hal_enableIRQs();
GPIOA->MODER |= 0x01415500; // unused pins as outputs: PA4, PA5, PA6, PA7, PA8, (PA11,PA12 USB)
GPIOB->MODER |= 0x00000401; // unused pins as outputs: PB0(HDR_DIO1), PB5 (PB10 pulled hi by LED), PB3-T_SWO
GPIOC->MODER |= 0x00000041; // unused pins as outputs: PC0(HDR_FEM_CSD), PC3(SPI3_enable)
}
u4_t hal_ticks ()
{
RTC_DateTypeDef dateStruct;
RTC_TimeTypeDef timeStruct;
struct tm timeinfo;
uint16_t sub_seconds;
RtcHandle.Instance = RTC;
// Read actual date and time
// Warning: the time must be read first!
HAL_RTC_GetTime(&RtcHandle, &timeStruct, FORMAT_BIN);
HAL_RTC_GetDate(&RtcHandle, &dateStruct, FORMAT_BIN);
sub_seconds = 16384 - timeStruct.SubSeconds; // RTC_SSR counts down
// Setup a tm structure based on the RTC
timeinfo.tm_wday = dateStruct.WeekDay;
timeinfo.tm_mon = dateStruct.Month - 1;
timeinfo.tm_mday = dateStruct.Date;
timeinfo.tm_year = dateStruct.Year + 100;
timeinfo.tm_hour = timeStruct.Hours;
timeinfo.tm_min = timeStruct.Minutes;
timeinfo.tm_sec = timeStruct.Seconds;
// Convert to timestamp
time_t t = mktime(&timeinfo);
// 14: SSR is driven at 16384Hz
t <<= 14;
return t | sub_seconds;
}
void hal_waitUntil (u4_t time)
{
while (hal_ticks() < time)
asm("nop");
}
volatile char deep_sleep;
/* return 1 if target time is soon, return 0 if timer was programmed */
u1_t hal_checkTimer (u4_t time)
{
int d = time - hal_ticks();
HAL_RTCEx_DeactivateWakeUpTimer(&RtcHandle);
__HAL_RTC_WAKEUPTIMER_CLEAR_FLAG(&RtcHandle, RTC_FLAG_WUTF);
if (d < 0x10000) { // less than 4s
deep_sleep = 0;
if (d < 4)
return 1; // very soon
if (d > ms2osticks(100)) {
d -= 13; // HSE_PLL startup time
deep_sleep = 1;
}
// 61.035us steps
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d, RTC_WAKEUPCLOCK_RTCCLK_DIV2);
} else if (d < 0x20000) { // less than 8s
d -= 6; // HSE_PLL startup time
deep_sleep = 1;
// 122us steps
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 1, RTC_WAKEUPCLOCK_RTCCLK_DIV4);
} else if (d < 0x40000) { // less than 16s
deep_sleep = 1;
// 244us steps
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 2, RTC_WAKEUPCLOCK_RTCCLK_DIV8);
} else if (d < 0x80000) { // less than 32s
deep_sleep = 1;
// 488us steps
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 3, RTC_WAKEUPCLOCK_RTCCLK_DIV16);
} else {
deep_sleep = 1;
// 1s steps to 18hours
HAL_RTCEx_SetWakeUpTimer_IT(&RtcHandle, d >> 14, RTC_WAKEUPCLOCK_CK_SPRE_16BITS);
/* RTC_WAKEUPCLOCK_CK_SPRE_17BITS: 18h to 36h */
/*for (;;)
asm("nop");*/
}
return 0;
}
//#define SLEEP_DEBUG 1
void hal_sleep ()
{
#ifdef SLEEP_DEBUG
u4_t start_tick, end_tick;
volatile uint32_t time_asleep;
#endif /* SLEEP_DEBUG */
#ifdef USE_DEBUGGER
HAL_EnableDBGStopMode();
if (!DBGMCU->CR & DBGMCU_CR_DBG_STOP)
for (;;) asm("nop");
#endif /* USE_DEBUGGER */
//printf("%x cr:%06x isr:%04x %d\r\n", RtcHandle.Instance->WUTR, RtcHandle.Instance->CR, RtcHandle.Instance->ISR, deep_sleep);
//debug_done();
if (deep_sleep) {
debug_done(); // wait here if debug still printing
}
if (__HAL_RTC_WAKEUPTIMER_GET_FLAG(&RtcHandle, RTC_FLAG_WUTF) == 0) {
// set gpio for sleep
#ifdef SLEEP_DEBUG
start_tick = hal_ticks();
#endif /* SLEEP_DEBUG */
if (deep_sleep) {
#ifndef USE_DEBUGGER
/* PA13 to undriven JTMS/SWDIO pin (from AF0 to GPIO), and PA2 */
GPIOA->MODER &= 0xf7ffffdf;
GPIOB->MODER &= 0xffffdfff; // PB6 UART_TX to input
#endif
deepsleep(); // blocks until waking
#ifndef USE_DEBUGGER
/* PA13 back to JTMS/SWDIO pin (from GPIO to AF0), and PA2 */
GPIOA->MODER |= 0x08000020;
GPIOB->MODER |= 0x00002000; // PB6 input to UART_TX
#endif
} else
sleep(); // blocks until waking
#ifdef SLEEP_DEBUG
end_tick = hal_ticks();
time_asleep = end_tick - start_tick;
printf("%u = %u - %u\r\n", time_asleep, end_tick, start_tick);
#endif /* SLEEP_DEBUG */
// restore gpio from sleep
}
}
void hal_pin_nss (u1_t val)
{
nss = val;
}
u1_t hal_spi (u1_t out)
{
return spi.write(out);
}
// 0=RX 1=TX
/*void hal_pin_rxtx (u1_t val)
{
rxtx = !val;
}*/
#define OPMODE_LORA 0x80
#define OPMODE_MASK 0x07
#define OPMODE_SLEEP 0x00
#define OPMODE_STANDBY 0x01
#define OPMODE_FSTX 0x02
#define OPMODE_TX 0x03
#define OPMODE_FSRX 0x04
#define OPMODE_RX 0x05
#define OPMODE_RX_SINGLE 0x06
#define OPMODE_CAD 0x07
void hal_opmode(u1_t mode, u1_t pa_boost)
{
if (mode == OPMODE_TX) { // start of transmission
if (pa_boost) {
rfsw2 = 0;
rfsw1 = 1;
} else {
rfsw2 = 1;
rfsw1 = 0;
}
hdr_fem_csd = 0; // debug
} else if (mode == OPMODE_RX || mode == OPMODE_RX_SINGLE || mode == OPMODE_CAD) { // start of reception
rfsw2 = 1;
rfsw1 = 1;
hdr_fem_csd = 1; // debug
} else { // RF switch shutdown
rfsw2 = 0;
rfsw1 = 0;
hdr_fem_csd = 0; // debug
}
}
void hal_pin_rst (u1_t val)
{
if (val == 0 || val == 1) { // drive pin
rst.output();
rst = val;
} else { // keep pin floating
rst.input();
}
}


