Senet-ized LMIC for MOTE_L152RC
Fork of lmic_MOTE_L152RC by
TARGET_MOTE_L152RC/hal.cpp
- Committer:
- dudmuck
- Date:
- 2015-06-04
- Revision:
- 2:edb5d1f3deeb
- Parent:
- 1:04fd63382b03
- Child:
- 4:1a9a62cf220f
File content as of revision 2:edb5d1f3deeb:
/* 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); // 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 */ 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("%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; } } 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(); } }