nes-proj/cpu/mc1322x/init.c

207 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();
}