lmic fork for Senet NAMote
Fork of lmic_MOTE_L152RC_2 by
Diff: TARGET_MOTE_L152RC/hal.cpp
- Revision:
- 0:f2716e543d97
- Child:
- 1:04fd63382b03
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/TARGET_MOTE_L152RC/hal.cpp Tue Jun 02 19:04:29 2015 +0000 @@ -0,0 +1,326 @@ +/* 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 RFSwitch_CNTR_2(PC_13); +//static DigitalOut rxtx(PC_4); // RFSwitch_CNTR_1 +DigitalOut rfsw1(RFSW1); +DigitalOut rfsw2(RFSW2); + +static DigitalOut hdr_fem_ctx(PC_7); + +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_ctx = 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); + + t &= 0xffff; + // 14: SSR is driven at 16384Hz + return (t << 14) | 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 */ + + 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 */ + hdr_fem_ctx = 1; + + 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 + + hdr_fem_ctx = 0; +#ifdef SLEEP_DEBUG + end_tick = hal_ticks(); + time_asleep = end_tick - start_tick; + printf("%d\r\n", time_asleep); +#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 + // assuming always using PA_BOOST + if (pa_boost) { + rfsw2 = 0; + rfsw1 = 1; + } else { + rfsw2 = 1; + rfsw1 = 0; + } + } else if (mode == OPMODE_RX || mode == OPMODE_RX_SINGLE || mode == OPMODE_CAD) { // start of reception + rfsw2 = 1; + rfsw1 = 1; + } else { // RF switch shutdown + rfsw2 = 0; + rfsw1 = 0; + } +} + +void hal_pin_rst (u1_t val) +{ + if (val == 0 || val == 1) { // drive pin + rst.output(); + rst = val; + } else { // keep pin floating + rst.input(); + } +} +