// ************************************************************************************************* // @fn update_light // @brief Update light status // @param none // @return none // ************************************************************************************************* void update_light(void) { if(!sys.flag.low_battery && light.value >= LIGHT_LEVEL) { // Config front light duty cicle and blink rate light.front_blink = 6; light.front_duty = 10; // Enable front light Timer light.front_enable = TRUE; Timer0_A1_Start(); // Enable back light Timer light.back_enable = TRUE; Timer0_A2_Start(); // Turn on lights set_light(LIGHT_ALL, LIGHT_ON); } else { // Disable front light Timer light.front_enable = FALSE; Timer0_A1_Stop(); // Disable back light Timer light.back_enable = FALSE; Timer0_A2_Stop(); // Turn off lights set_light(LIGHT_ALL, LIGHT_OFF); } }
// ************************************************************************************************* // @fn doorlock_random_timer // @brief this timer callback changes the index in the array where the random bits are // collected to, until the array is filled. // @param none // @return none // ************************************************************************************************* void doorlock_random_timer(void) { if (doorlock_random_index < 32) { ++ doorlock_random_index; } else { Timer0_A1_Stop(); } }
// ************************************************************************************************* // @fn doorlock_random // @brief garther random bits using accelerometer // @param random bits (output) // @return none // ************************************************************************************************* void doorlock_random(u8 random[16]) { u8 longrandom[32] = {0}; // initialize doorlock_random_index = 0; // start accelerometer as_start(AS_MODE_2G_100HZ); // start timer fptr_Timer0_A1_function = doorlock_random_timer; Timer0_A1_Start(CONV_MS_TO_TICKS(DOORLOCK_RANDOM_INTERVAL)); for(;;) { idle(); if (doorlock_random_index >= 32) { as_stop(); break; } // look for accelerometer data ready event if (!request.flag.acceleration_measurement) { continue; } request.flag.acceleration_measurement = 0; // "randomly" flipping bits longrandom[(doorlock_random_index + 0) % 32] ^= as_get_x(); longrandom[(doorlock_random_index + 10) % 32] ^= as_get_y(); longrandom[(doorlock_random_index + 20) % 32] ^= as_get_z(); } // just to make sure Timer0_A1_Stop(); // now encrypt aes_encrypt(longrandom, longrandom + 16); // done memcpy(random, longrandom, sizeof(u8) * 16); }
// ************************************************************************************************* // @fn sync_sidereal // @brief calculates local sidereal time from solar time and sets sidereal clock // @param none // @return none // ************************************************************************************************* void sync_sidereal(void) { unsigned long sidtime=sidereal_seconds(secs_since_fix(sTime.second, sTime.minute, sTime.hour, sDate.day, sDate.month, sDate.year)-360*sTime.UTCoffset); //calculate difference of local time from greenwich time long localcorr= (long)(sSidereal_time.lon[sSidereal_time.lon_selection].deg*60 + sSidereal_time.lon[sSidereal_time.lon_selection].min)*4 + (sSidereal_time.lon[sSidereal_time.lon_selection].sec+7)/15; //round correctly //prevent sidtime from becoming negative if(localcorr<0 && -localcorr>sidtime) { sidtime+=86400; } sidtime+=localcorr; //make sure the time is between 00:00:00 and 23:59:59 if(sidtime>=86400) { sidtime -=86400; } // Disable interrupts to prevent race conditions Timer0_A1_Stop(); // Set sidereal 24H time to calculated value sSidereal_time.hour = sidtime/3600; sidtime %=3600; sSidereal_time.minute = sidtime/60; sidtime %=60; sSidereal_time.second = sidtime; // Set clock timer for one sidereal second in the future Timer0_A1_Start(); //sync=1: automatically sync only one time if (sSidereal_time.sync==1) { sSidereal_time.sync=0; } }
// ************************************************************************************************* // @fn mx_sidereal // @brief Sidereal Clock set routine. // has three layers of different configuration sets // @param u8 line LINE1, LINE2 // @return none // ************************************************************************************************* void mx_sidereal(u8 line) { u8 select; s32 hours; s32 minutes; s32 seconds; s32 lon_degrees[SIDEREAL_NUM_LON]; s32 lon_minutes[SIDEREAL_NUM_LON]; s32 lon_seconds[SIDEREAL_NUM_LON]; s32 sync; s32 heart; u8 level; s32 direction[SIDEREAL_NUM_LON]; s32 UTCoffset; u8 * str; int i; // Clear display clear_display_all(); // Convert global time to local variables hours = sSidereal_time.hour; minutes = sSidereal_time.minute; seconds = sSidereal_time.second; sync = sSidereal_time.sync; for(i=0; i<SIDEREAL_NUM_LON; i++) { if(sSidereal_time.lon[i].deg<0 || sSidereal_time.lon[i].min<0 || sSidereal_time.lon[i].sec<0) { direction[i]=0; lon_degrees[i] = -sSidereal_time.lon[i].deg; lon_minutes[i] = -sSidereal_time.lon[i].min; lon_seconds[i] = -sSidereal_time.lon[i].sec; } else { direction[i]=1; lon_degrees[i] = sSidereal_time.lon[i].deg; lon_minutes[i] = sSidereal_time.lon[i].min; lon_seconds[i] = sSidereal_time.lon[i].sec; } } UTCoffset = sTime.UTCoffset; // Init value index (start with Auto Sync selection) select = 0; heart =0; level=sSidereal_time.lon_selection; // Loop values until all are set or user breaks set while(1) { // Idle timeout: exit without saving if (sys.flag.idle_timeout) { display_symbol(LCD_SYMB_AM, SEG_OFF); display_symbol(LCD_UNIT_L1_DEGREE, SEG_OFF); display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); break; } if( heart!=0 ) { if(select<=4) { //go to longitude settings if(heart>0) { select=5; level=0; } //go to time zone settings else { select=10; } clear_display_all(); display_symbol(LCD_SYMB_AM, SEG_OFF); } else if(select<=9) { if(heart<0) { //go to previous level if(level>0) { level-=1; select=5; } //go to time/sync settings else { select=0; } } else { //go to next level if(level<SIDEREAL_NUM_LON-1) { level+=1; select=5; } //go to time zone settings else { select=10; } } clear_display_all(); display_symbol(LCD_UNIT_L1_DEGREE, SEG_OFF); display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); } else { //go to time/sync settings if(heart>0) { select=0; } //go to longitude settings else { select=5; level=SIDEREAL_NUM_LON-1; } clear_display_all(); display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); } heart=0; } // Button STAR (short): save, then exit if (button.flag.star) { //store sync settings sSidereal_time.sync=sync; sTime.UTCoffset = UTCoffset; for(i=0; i<SIDEREAL_NUM_LON; i++) { //store direction as sign of longitude if(direction[i] & 0x1) { sSidereal_time.lon[i].deg = lon_degrees[i]; sSidereal_time.lon[i].min = lon_minutes[i]; sSidereal_time.lon[i].sec = lon_seconds[i]; } else { sSidereal_time.lon[i].deg = -lon_degrees[i]; sSidereal_time.lon[i].min = -lon_minutes[i]; sSidereal_time.lon[i].sec = -lon_seconds[i]; } } //only save new lon_selection when it is clear which level is selected if(select<=9 && select>4) { sSidereal_time.lon_selection=level; } #ifdef CONFIG_INFOMEM //store new longitude and time zone in information memory u16 buf[SIDEREAL_NUM_LON*sizeof(struct longitude)/2+1]; ((u8*)buf)[0]=sTime.UTCoffset; ((u8*)buf)[1]=sSidereal_time.lon_selection; memcpy(buf+1, &(sSidereal_time.lon),SIDEREAL_NUM_LON*sizeof(struct longitude)); infomem_app_replace(SIDEREAL_INFOMEM_ID,buf,SIDEREAL_NUM_LON*sizeof(struct longitude)/2+1); #endif //sync time if desired if(sync >=1) { sync_sidereal(); } else { // Disable interrupts to prevent race conditions Timer0_A1_Stop(); // Store local variables in global sidereal clock time sSidereal_time.hour = hours; sSidereal_time.minute = minutes; sSidereal_time.second = seconds; // Set clock timer for one sidereal second in the future Timer0_A1_Start(); } // Full display update is done when returning from function display_symbol(LCD_SYMB_AM, SEG_OFF); display_symbol(LCD_SYMB_ARROW_UP, SEG_OFF); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_OFF); display_symbol(LCD_UNIT_L1_DEGREE, SEG_OFF); break; } switch (select) { case 0: // Heart Symbol to switch to longitude settings // Display HH:MM (LINE1) and As .SS (LINE2) str = _itoa(hours, 2, 0); display_chars(LCD_SEG_L1_3_2, str, SEG_ON); display_symbol(LCD_SEG_L1_COL, SEG_ON); str = _itoa(minutes, 2, 0); display_chars(LCD_SEG_L1_1_0, str, SEG_ON); str = _itoa(seconds, 2, 0); display_chars(LCD_SEG_L2_1_0, str, SEG_ON); display_symbol(LCD_SEG_L2_DP, SEG_ON); str = _itoa(sync,1,0); display_char(LCD_SEG_L2_3, *str, SEG_ON); display_char(LCD_SEG_L2_4, 'A', SEG_ON); set_value(&heart, 0, 0, -1, 1, SETVALUE_DISPLAY_SYMBOL + SETVALUE_NEXT_VALUE, LCD_ICON_HEART, display_value1); select =1; break; case 1: // Set Automatic Sync setings set_value(&sync, 1, 0, 0, 2, SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_3, display_value1); select =2; break; case 2: // Set hours set_value(&hours, 2, 0, 0, 23, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_3_2, display_hours_12_or_24); select = 3; break; case 3: // Set minutes set_value(&minutes, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_1_0, display_value1); select = 4; break; case 4: // Set seconds set_value(&seconds, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1); select = 0; break; /*=============================================*/ case 5: // Heart Symbol to switch to time settings or UTC offset //display current level at free digit next to the degrees str = _itoa(level+1, 1, 0); display_chars(LCD_SEG_L1_0, str, SEG_ON); str = _itoa(lon_degrees[level], 3, 0); display_chars(LCD_SEG_L1_3_1, str, SEG_ON); display_symbol(LCD_UNIT_L1_DEGREE, SEG_ON); str = _itoa(lon_minutes[level], 2, 0); display_chars(LCD_SEG_L2_4_3, str, SEG_ON); str = _itoa(lon_seconds[level], 2, 0); display_chars(LCD_SEG_L2_1_0, str, SEG_ON); display_symbol(LCD_SEG_L2_COL0, SEG_ON); if(direction[level] & 0x1) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); } else { display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); } set_value(&heart, 0, 0, -1, 1, SETVALUE_DISPLAY_SYMBOL + SETVALUE_NEXT_VALUE, LCD_ICON_HEART, display_value1); select =6; break; case 6: // Set orientation set_value(direction+level, 0, 0, 0, 1, SETVALUE_ROLLOVER_VALUE + SETVALUE_NEXT_VALUE + SETVALUE_SWITCH_ARROWS, 0, display_value1); select = 7; break; case 7: // Set degrees set_value(lon_degrees+level, 3, 0, 0, 180, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L1_3_1, display_value1); select = 8; break; case 8: // Set minutes set_value(lon_minutes+level, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_4_3, display_value1); select = 9; break; case 9: // Set seconds set_value(lon_seconds+level, 2, 0, 0, 59, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE, LCD_SEG_L2_1_0, display_value1); select = 5; break; /*=============================================*/ case 10: // Heart Symbol to switch to longitude settings if(UTCoffset >= 0) { str = _itoa(UTCoffset, 3, 0); if(UTCoffset>0) { display_symbol(LCD_SYMB_ARROW_UP, SEG_ON); } } else { str = _itoa( - UTCoffset, 3, 0); display_symbol(LCD_SYMB_ARROW_DOWN, SEG_ON); } display_chars(LCD_SEG_L1_3_1, str, SEG_ON); display_symbol(LCD_SEG_L1_DP1,SEG_ON); memcpy(str,"UTC",3); display_chars(LCD_SEG_L2_4_2, str, SEG_ON); set_value(&heart, 0, 0, -1, 1, SETVALUE_DISPLAY_SYMBOL + SETVALUE_NEXT_VALUE, LCD_ICON_HEART, display_value1); select =11; break; case 11: // Set UTC OFFSET set_value(&UTCoffset, 3, 0, -120, 120, SETVALUE_ROLLOVER_VALUE + SETVALUE_DISPLAY_VALUE + SETVALUE_NEXT_VALUE + SETVALUE_DISPLAY_ARROWS + SETVALUE_STEP_FIFE, LCD_SEG_L1_3_1, display_value1); select = 10; break; } } // Clear button flags button.all_flags = 0; }