lmic fork for Senet NAMote

Dependents:   Senet NAMote

Fork of lmic_MOTE_L152RC_2 by Dave Kjendal

Revision:
0:f2716e543d97
Child:
1:04fd63382b03
diff -r 000000000000 -r f2716e543d97 TARGET_MOTE_L152RC/hal.cpp
--- /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();
+    }
+}
+