206 lines
5.6 KiB
C
206 lines
5.6 KiB
C
#include <stdio.h>
|
|
|
|
/* debug */
|
|
#define DEBUG DEBUG_FULL
|
|
#include "net/ip/uip-debug.h"
|
|
|
|
/* contiki */
|
|
#include "sys/process.h"
|
|
|
|
/* mc1322x */
|
|
#include "mc1322x.h"
|
|
#include "contiki-maca.h"
|
|
#include "config.h"
|
|
|
|
/* Threshold for buck converter; buck will be disabled if vbatt is below this */
|
|
#define MC1322X_BUCK_THRES 2425
|
|
/* Hysterisis window around buck threshold */
|
|
#define MC1322X_BUCK_WINDOW 150
|
|
#define MC1322X_BUCK_THRES_H (MC1322X_BUCK_THRES + MC1322X_BUCK_WINDOW/2)
|
|
#define MC1322X_BUCK_THRES_L (MC1322X_BUCK_THRES - MC1322X_BUCK_WINDOW/2)
|
|
/* Time between vbatt checks for the buck */
|
|
#define MC1322X_BUCK_MONITOR_PERIOD 600 * CLOCK_SECOND
|
|
|
|
/* periodically poll adc_vbatt and manages the buck appropriately */
|
|
static struct etimer et_buck;
|
|
PROCESS(buck_monitor, "buck monitor");
|
|
PROCESS_THREAD(buck_monitor, ev, data)
|
|
{
|
|
|
|
PROCESS_BEGIN();
|
|
PRINTF("starting vbatt monitor\n");
|
|
|
|
etimer_set(&et_buck, MC1322X_BUCK_MONITOR_PERIOD);
|
|
|
|
while (1) {
|
|
PROCESS_WAIT_EVENT();
|
|
if(etimer_expired(&et_buck))
|
|
{
|
|
adc_service();
|
|
PRINTF("buck monitor: vbatt: %d mV\n\r", adc_vbatt);
|
|
if( CRM->VREG_CNTLbits.BUCK_EN == 1 && adc_vbatt < MC1322X_BUCK_THRES_L ) {
|
|
PRINTF("vbatt low, disabling buck\n\r", adc_vbatt);
|
|
CRM->SYS_CNTLbits.PWR_SOURCE = 0;
|
|
CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 0;
|
|
CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 1;
|
|
CRM->VREG_CNTLbits.BUCK_EN = 0;
|
|
} else if ( CRM->VREG_CNTLbits.BUCK_EN == 0 && adc_vbatt > MC1322X_BUCK_THRES_H ) {
|
|
PRINTF("vbatt high, enabling buck\n\r", adc_vbatt);
|
|
CRM->SYS_CNTLbits.PWR_SOURCE = 1;
|
|
CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 1;
|
|
CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 0;
|
|
CRM->VREG_CNTLbits.BUCK_EN = 1;
|
|
}
|
|
etimer_set(&et_buck, MC1322X_BUCK_MONITOR_PERIOD);
|
|
}
|
|
}
|
|
|
|
PROCESS_END();
|
|
|
|
}
|
|
|
|
void buck_setup(void) {
|
|
nvmType_t type;
|
|
nvmErr_t err;
|
|
volatile int i;
|
|
|
|
default_vreg_init();
|
|
|
|
while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; }
|
|
while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; }
|
|
|
|
/* takes time for the flash supply to fail (if there is no buck) */
|
|
/* spin while this happens doing nvm_detects */
|
|
/* XXX todo: don't probe buck if Vbatt < 2.5V */
|
|
|
|
adc_service();
|
|
PRINTF("vbatt: %04u mV\n\r", adc_vbatt);
|
|
|
|
type = 1;
|
|
for(i = 0; i < 128 && type != 0; i++) {
|
|
err = nvm_detect(gNvmInternalInterface_c, &type);
|
|
}
|
|
if (type == gNvmType_NoNvm_c)
|
|
{
|
|
PRINTF("NVM failed without buck, trying with buck\n\r");
|
|
|
|
if (adc_vbatt < MC1322X_BUCK_THRES_L)
|
|
{
|
|
PRINTF("Vbatt is low, bypassing buck\n\r");
|
|
CRM->SYS_CNTLbits.PWR_SOURCE = 0;
|
|
CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 0;
|
|
CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 1;
|
|
CRM->VREG_CNTLbits.BUCK_EN = 0;
|
|
} else {
|
|
CRM->SYS_CNTLbits.PWR_SOURCE = 1;
|
|
CRM->VREG_CNTLbits.BUCK_SYNC_REC_EN = 1;
|
|
CRM->VREG_CNTLbits.BUCK_BYPASS_EN = 0;
|
|
CRM->VREG_CNTLbits.BUCK_EN = 1;
|
|
}
|
|
|
|
while(CRM->STATUSbits.VREG_BUCK_RDY == 0) { continue; }
|
|
CRM->VREG_CNTLbits.VREG_1P5V_SEL = 3;
|
|
CRM->VREG_CNTLbits.VREG_1P5V_EN = 3;
|
|
CRM->VREG_CNTLbits.VREG_1P8V_EN = 1;
|
|
|
|
while(CRM->STATUSbits.VREG_1P5V_RDY == 0) { continue; }
|
|
while(CRM->STATUSbits.VREG_1P8V_RDY == 0) { continue; }
|
|
|
|
type = 1;
|
|
for(i = 0; i < 128 && type != 0; i++) {
|
|
err = nvm_detect(gNvmInternalInterface_c, &type);
|
|
}
|
|
if (type != gNvmType_NoNvm_c) {
|
|
PRINTF("buck ok\n\r");
|
|
/* start a process to monitor vbatt and enable/disable the buck as necessary */
|
|
process_start(&buck_monitor, NULL);
|
|
} else {
|
|
printf("fatal: couldn't detect NVM\n\r");
|
|
}
|
|
} else {
|
|
PRINTF("NVM ok without buck\n\r");
|
|
}
|
|
}
|
|
|
|
/* setup the RTC */
|
|
/* try to start the 32kHz xtal */
|
|
void rtc_setup(void) {
|
|
volatile uint32_t rtc_count;
|
|
volatile uint32_t i;
|
|
|
|
ring_osc_off();
|
|
xtal32_on();
|
|
xtal32_exists();
|
|
rtc_count = CRM->RTC_COUNT;
|
|
PRINTF("trying to start 32kHz xtal\n\r");
|
|
|
|
for(i = 0; i < 150000 && CRM->RTC_COUNT == rtc_count; i++) { continue; }
|
|
if(CRM->RTC_COUNT == rtc_count) {
|
|
PRINTF("32xtal failed, using ring osc\n\r");
|
|
CRM->SYS_CNTLbits.XTAL32_EXISTS = 0;
|
|
CRM->XTAL32_CNTLbits.XTAL32_EN = 0;
|
|
ring_osc_on();
|
|
|
|
/* Set default tune values from datasheet */
|
|
CRM->RINGOSC_CNTLbits.ROSC_CTUNE = 0x6;
|
|
CRM->RINGOSC_CNTLbits.ROSC_FTUNE = 0x17;
|
|
|
|
/* Trigger calibration */
|
|
rtc_calibrate();
|
|
PRINTF("RTC calibrated to %d Hz\r\n", rtc_freq);
|
|
} else {
|
|
PRINTF("32kHz xtal started\n\r");
|
|
rtc_freq = 32768;
|
|
}
|
|
}
|
|
|
|
/* call mc1322x_init once to initalize everything with the current config */
|
|
void mc1322x_init(void) {
|
|
|
|
/* XXX TODO load config from flash */
|
|
/* config should say what uart to use for debug console */
|
|
/* config should also set the baud rate */
|
|
/* for now, just clean up contiki-conf.h */
|
|
/* maybe factor into conf.h -> contiki-conf.h and mc1322x-conf.h platform-conf.h */
|
|
|
|
/* print out config in debug */
|
|
/* initialize the uarts */
|
|
uart_init(CONSOLE_UART, CONSOLE_BAUD);
|
|
PRINTF("mc1322x init\n\r");
|
|
|
|
adc_init();
|
|
ctimer_init();
|
|
process_init();
|
|
process_start(&etimer_process, NULL);
|
|
process_start(&contiki_maca_process, NULL);
|
|
buck_setup();
|
|
|
|
/* start with a default config */
|
|
|
|
mc1322x_config_restore(&mc1322x_config);
|
|
if ( mc1322x_config_valid(&mc1322x_config) != 1 ) {
|
|
PRINTF("flash invalid\n\r");
|
|
/* save the default config to flash */
|
|
mc1322x_config_set_default(&mc1322x_config);
|
|
mc1322x_config_save(&mc1322x_config);
|
|
}
|
|
|
|
#if DEBUG_FULL
|
|
mc1322x_config_print();
|
|
#endif
|
|
|
|
/* setup the radio */
|
|
maca_init();
|
|
set_power(mc1322x_config.power);
|
|
set_channel(mc1322x_config.channel);
|
|
set_demodulator_type(mc1322x_config.flags.demod);
|
|
set_prm_mode(mc1322x_config.flags.autoack);
|
|
|
|
/* must be done AFTER maca_init */
|
|
/* the radio calibration appears to clobber the RTC trim caps */
|
|
rtc_setup();
|
|
rtimer_init();
|
|
clock_init();
|
|
|
|
}
|
|
|