void resetSystem(void) { // set watchdog timer to reset device; 0x780A (Watchdog Reset Control Register) // see GPL Programmer's Manual (V1.0 Dec 20,2006), Section 3.5, page 18 checkVoltage(); // USB may have been supplying sole power -- need to check if voltage dropping fast stop(); if (PLEASE_WAIT_IDX && context.package) { // prevents trying to insert this sound before config & control files are loaded. insertSound(&pkgSystem.files[PLEASE_WAIT_IDX],NULL,TRUE); } checkVoltage(); // USB may have been supplying sole power -- need to check if voltage dropping fast saveVolumeProfile(); logString((char *)"* RESET *",ASAP,LOG_ALWAYS); saveLogFile(0); fs_safexit(); // should close all open files disk_safe_exit(0); // try to get the sd card in a safe state - reverse what we do on startup _deviceunmount(0); fs_uninit(); SD_Uninitial(); turnSDoff(); playBip(); setLED(LED_ALL,FALSE); *P_WatchDog_Ctrl &= ~0x4001; // clear bits 14 and 0 for resetting system and time=0.125 sec *P_WatchDog_Ctrl |= 0x8004; // set bits 2 and 15 for 0.125 sec, system reset, and enable watchdog while(1); }
/**************************************************************************//** * @brief Update clock and wait in EM2 for RTC tick. *****************************************************************************/ void clockLoop(void) { LCD_FrameCountInit_TypeDef frameInit; LCD_AnimInit_TypeDef animInit; /* Write Gecko and display, and light up the colon between hours and minutes. */ SegmentLCD_Symbol(LCD_SYMBOL_COL10, 1); SegmentLCD_Write("Wonder"); /* Setup frame counter */ frameInit.enable = true; /* Enable framecounter */ frameInit.top = 15; /* Generate event every 15 frames. */ frameInit.prescale = lcdFCPrescDiv1; /* No prescaling */ LCD_FrameCountInit(&frameInit); /* Animate half ring - by special board design it is possible to achieve */ /* "slide in/slide out" effect */ animInit.enable = true; /* Enable animation after initialization. */ animInit.AReg = 0x00; /* Initial A register value */ animInit.BReg = 0x0F; /* Initial B register value */ animInit.AShift = lcdAnimShiftLeft; /* Shift A register left */ animInit.BShift = lcdAnimShiftLeft; /* Shift B register left */ animInit.animLogic = lcdAnimLogicOr; /* Enable segment if A or B */ animInit.startSeg = 8; /* Initial animation segment */ LCD_AnimInit(&animInit); while (1) { checkVoltage(); SegmentLCD_Number(hours * 100 + minutes); EMU_EnterEM2(true); } }
extern int rotate(void) { int rotation = getRotation() + 1; if (rotation >= MAX_ROTATIONS) // TODO: Should we use this to indicate the last rotation is now complete? Maybe if agents are clearing feedback msgs anyway rotation = -1; else { checkVoltage(); // updates vCur_1 used in next line setRotation(rotation,getPeriod(),(getCumulativeDays()*24) + *P_Hour + (*P_Minute / 30),vCur_1); } return rotation; }
extern void setPowerups(unsigned int powerupNumber) { struct NORpowerups powerups; int currentPowerups = getPowerups(); if (powerupNumber > currentPowerups) { powerups.structType = NOR_STRUCT_ID_POWERUPS; powerups.powerups = powerupNumber; checkVoltage(); // updates vCur_1 used in next line powerups.initVoltage = vCur_1; ptrsCounts.powerups = (struct NORpowerups *)AppendStructToFlash(&powerups); } }
void wait(int t) { //t=time in msec unsigned int i; unsigned long j, k; unsigned long int cyclesPerMilliSecond = (long)(*P_PLLN & 0x3f) * 1000L; // 96000 at 96MHz const unsigned int cyclesPerNOP = 70; // cycles for each no-operation instruction const unsigned int cyclesPerVoltCheck = cyclesPerNOP * 300; // cycles for each no-operation instruction // const unsigned int NOPsPerMilliSecond = cyclesPerMilliSecond / cyclesPerNOP; // loop count per millisecond const unsigned int VChecksPerMilliSecond = cyclesPerMilliSecond / cyclesPerVoltCheck; // loop count per millisecond for (i = 0; i < t; i++) for (j = 0; j < VChecksPerMilliSecond; j++) { // asm("nop\n"); // a CPU no-op instruction to pass the time if (!shuttingDown) { checkVoltage(); } else { // shutting down - don't check voltage - instead use NOPs for (k=0; k< (cyclesPerVoltCheck/cyclesPerNOP);k++) { asm("nop\n"); } } } }
/**************************************************************************//** * @brief LCD Test Routine, shows various text and patterns *****************************************************************************/ void Test(void) { int i, numberOfIterations = 0; /* Initialize GPIO */ GPIO_IRQInit(); /* Initialize RTC */ RTCDRV_Setup(cmuSelect_LFRCO, cmuClkDiv_32); /* Loop through funny pattern */ while (1) { SegmentLCD_AllOff(); #if VBOOST_SUPPORT checkVoltage(); #endif if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } else { for (i = 100; i > 0; i--) { SegmentLCD_Number(i); EM2Sleep(10); } SegmentLCD_NumberOff(); SegmentLCD_Symbol(LCD_SYMBOL_GECKO, 1); SegmentLCD_Symbol(LCD_SYMBOL_EFM32, 1); SegmentLCD_Write(" TINY "); EM2Sleep(500); SegmentLCD_Write(" Gecko "); EM2Sleep(1000); SegmentLCD_AllOn(); EM2Sleep(1000); SegmentLCD_AllOff(); } if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } else { SegmentLCD_Write("OOOOOOO"); EM2Sleep(62); SegmentLCD_Write("XXXXXXX"); EM2Sleep(62); SegmentLCD_Write("+++++++"); EM2Sleep(62); SegmentLCD_Write("@@@@@@@"); EM2Sleep(62); SegmentLCD_Write("ENERGY "); EM2Sleep(250); SegmentLCD_Write("@@ERGY "); EM2Sleep(62); SegmentLCD_Write(" @@RGY "); EM2Sleep(62); SegmentLCD_Write(" M@@GY "); EM2Sleep(62); SegmentLCD_Write(" MI@@Y "); EM2Sleep(62); SegmentLCD_Write(" MIC@@ "); EM2Sleep(62); SegmentLCD_Write(" MICR@@"); EM2Sleep(62); SegmentLCD_Write(" MICRO@"); EM2Sleep(62); SegmentLCD_Write(" MICRO "); EM2Sleep(250); SegmentLCD_Write("-EFM32-"); EM2Sleep(250); /* Various eye candy */ SegmentLCD_AllOff(); if (emMode != DEMO_MODE_NONE) { SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 1); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 1); } for (i = 0; i < 8; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_ARing(i, 1); EM2Sleep(20); } for (i = 0; i < 8; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_ARing(i, 0); EM2Sleep(100); } for (i = 0; i < 5; i++) { SegmentLCD_Number(numberOfIterations + i); SegmentLCD_Battery(i); SegmentLCD_EnergyMode(i, 1); EM2Sleep(100); SegmentLCD_EnergyMode(i, 0); EM2Sleep(100); } SegmentLCD_Symbol(LCD_SYMBOL_ANT, 1); for (i = 0; i < 4; i++) { SegmentLCD_EnergyMode(i, 1); EM2Sleep(100); } SegmentLCD_Symbol(LCD_SYMBOL_ANT, 0); SegmentLCD_Battery(0); } /* Energy Modes */ SegmentLCD_NumberOff(); SegmentLCD_Symbol(LCD_SYMBOL_GECKO, 1); SegmentLCD_Symbol(LCD_SYMBOL_EFM32, 1); if ((emMode != DEMO_MODE_EM3) && (emMode != DEMO_MODE_EM4)) { ScrollText("Energy Mode demo, Press PB0 for EM3 or PB1 for EM4 "); } SegmentLCD_Write(" EM0 "); SegmentLCD_Number(0); SegmentLCD_EnergyMode(0, 1); SegmentLCD_EnergyMode(1, 1); SegmentLCD_EnergyMode(2, 1); SegmentLCD_EnergyMode(3, 1); SegmentLCD_EnergyMode(4, 1); RTCDRV_Delay(4000, false); SegmentLCD_Write(" EM1 "); SegmentLCD_Number(1111); SegmentLCD_EnergyMode(0, 0); EM1Sleep(4000); SegmentLCD_Write(" EM2 "); SegmentLCD_Number(2222); SegmentLCD_EnergyMode(1, 0); EM2Sleep(4000); /* Check if somebody has pressed one of the buttons */ if (emMode == DEMO_MODE_EM3) { ScrollText("Going down to EM3, press PB0 to wake up "); SegmentLCD_Write(" EM3 "); SegmentLCD_Number(3333); RTCDRV_Delay(1000, false); /* Wake up on GPIO interrupt */ EM3Sleep(); SegmentLCD_Number(0000); SegmentLCD_Write("--EM0--"); RTCDRV_Delay(500, false); SegmentLCD_Symbol(LCD_SYMBOL_PAD0, 0); SegmentLCD_Symbol(LCD_SYMBOL_PAD1, 0); emMode = DEMO_MODE_NONE; } /* Check if somebody's joystick down */ if (emMode == DEMO_MODE_EM4) { ScrollText("Going down to EM4, press reset to restart "); SegmentLCD_Write(" EM4 "); SegmentLCD_Number(4444); RTCDRV_Delay(1000, false); /* Wake up on reset */ EM4Sleep(); } SegmentLCD_EnergyMode(0, 0); SegmentLCD_EnergyMode(1, 0); SegmentLCD_EnergyMode(2, 0); SegmentLCD_EnergyMode(3, 0); SegmentLCD_EnergyMode(4, 0); /* Scrolltext */ ScrollText(stext); /* Blink and animation featurs */ BlinkTest(); numberOfIterations++; } }
extern void setSystemData(struct SystemData *sd) { struct SystemCounts2 sc; int size, totalSize, i, reflashes; dumpSystemDataToLog(sd); sd->structType = NOR_STRUCT_ID_SYSTEM; reflashes = getReflashCount(); if (!sd->countReflashes) sd->countReflashes = reflashes + 1; if (!sd->serialNumber[0]) { strcpy(sd->serialNumber,getSerialNumber()); if (!sd->serialNumber[0]) { strcpy(sd->serialNumber,(char *)"UNKNOWN"); } } if (!sd->location[0]) { strcpy(sd->location,getLocation()); if (!sd->location[0]) { strcpy(sd->location,(char *)"UNKNOWN"); } } if (!sd->imageName[0]) { strcpy(sd->imageName,getImageName()); if (!sd->imageName[0]) { strcpy(sd->imageName,(char *)"UNKNOWN"); } } if (!sd->updateNumber[0]) strcpy(sd->updateNumber,getUpdateNumber()); if (!sd->monthLastUpdated) sd->monthLastUpdated = getUpdateMonth(); if (!sd->dateLastUpdated) sd->dateLastUpdated = getUpdateDate(); if (!sd->yearLastUpdated) sd->yearLastUpdated = getUpdateYear(); dumpSystemDataToLog(sd); systemCounts.monthday = sd->dateLastUpdated; systemCounts.month = sd->monthLastUpdated; systemCounts.year = sd->yearLastUpdated; sc.structType = NOR_STRUCT_ID_COUNTS; sc.period = 0; sc.cumulativeDays = 0; sc.corruptionDay = 0; sc.powerups = 0; sc.lastInitVoltage = 0; sc.rotations[0].structType = NOR_STRUCT_ID_ROTATION; sc.rotations[0].rotationNumber = 0; sc.rotations[0].periodNumber = 0; sc.rotations[0].hoursAfterLastUpdate = 0; checkVoltage(); sc.rotations[0].initVoltage = vCur_1; for (i=1; i< MAX_ROTATIONS; i++) { sc.rotations[i].structType = -2; // -1 is bad since FF is unwritten memory } // startup() assumes that struct SystemData is written first at TB_SERIAL_NUMBER_ADDR totalSize = 0; size = sizeof(struct SystemData); // round up # of words write_app_flash((int *)sd, size, totalSize); totalSize += size; ptrsCounts.systemData = (struct SystemData *)(TB_SERIAL_NUMBER_ADDR); size = sizeof(struct SystemCounts2); // round up # of words write_app_flash((int *)&sc, size, totalSize); ptrsCounts.systemCounts = (struct SystemCounts2 *)(TB_SERIAL_NUMBER_ADDR + totalSize); ptrsCounts.period = NULL; ptrsCounts.cumulativeDays = NULL; ptrsCounts.powerups = NULL; ptrsCounts.corruptionDay = NULL; ptrsCounts.latestRotation = NULL; }
int main() { cli(); disableWatchdog(); slowClock(); initBuzzer(); initSwitch(); initADC(); #ifdef DEBUG uint16_t v = getVoltage(); uint16_t i; for (i = 0x8000; i != 0; i >>= 1) { if (v & i) { dit(); } else { dah(); } _delay_ms(1000); } #endif // Retrieve the current warning timeout from eeprom uint8_t warn_min = eeprom_read_byte(&cfg_warn_min); if (switchPressed()) { number(warn_min); // pause between increments _delay_ms(3000); } // If switch is depressed (at power up), begin increasing // warning time, in 5-minute increments, max 30 minutes // SOS time is 2 x warning time. // while (switchPressed()) { if (switchPressed()) { // Increment warning time by 5 minutes warn_min += 5; // Maximum warning time is 30 minutes if (warn_min > 30) warn_min = 5; // Save the new warning time eeprom_update_byte(&cfg_warn_min, warn_min); } number(warn_min); // pause between increments _delay_ms(3000); } // Compute the number of seconds for warning and SOS warn_sec = warn_min * 60; sos_sec = warn_sec * 2; if (checkVoltage()) { ok(); } else { sos(); } enableWatchdog(); sei(); while (1) { set_sleep_mode(SLEEP_MODE_PWR_DOWN); sleep_mode(); } }