Esempio n. 1
0
int main(void)
{
	uint32_t data_counter=0;			//used as data timestamp
	uint8_t deadly_flashes=0,system_state=0,repetition_counter=0;
	int16_t sensor_data, sensor_raw_data[3]={};	//used for handling data passed back from sensors
	int16_t sfe_sensor_ref_buff[2][3],sfe_sensor_ref_buff_old[2][3];//used to detect and fix I2C bus lockup
	RTC_t RTC_time;
	wave_stuffer Gyro_wav_stuffer={0,0},Accel_wav_stuffer={0,0};//Used to controlling wav file bit packing
	SystemInit();					//Sets up the clk
	setup_gpio();					//Initialised pins, and detects boot source
	DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);	//Watchdog stopped during JTAG halt
	if(RCC->CSR&RCC_CSR_IWDGRSTF) {			//Watchdog reset, turn off
		RCC->CSR|=RCC_CSR_RMVF;			//Reset the reset flags
		shutdown();
	}
	SysTick_Configuration();			//Start up system timer at 100Hz for uSD card functionality
	Watchdog_Config(WATCHDOG_TIMEOUT);		//Set the watchdog
	Watchdog_Reset();				//Reset watchdog as soon as possible incase it is still running at power on
	rtc_init();					//Real time clock initialise - (keeps time unchanged if set)
	Usarts_Init();
	ISR_Config();
	rprintfInit(__usart_send_char);			//Printf over the bluetooth
	if(USB_SOURCE==bootsource) {
		Set_System();				//This actually just inits the storage layer
		Set_USBClock();
		USB_Interrupts_Config();
		USB_Init();
		uint32_t nojack=0x000FFFFF;		//Countdown timer - a few hundered ms of 0v on jack detect forces a shutdown
		while (bDeviceState != CONFIGURED) {	//Wait for USB config - timeout causes shutdown
			if(Millis>10000 || !nojack)	//No USB cable - shutdown (Charger pin will be set to open drain, cant be disabled without usb)
				shutdown();
			if(GET_CHRG_STATE)		//Jack detect resets the countdown
				nojack=0x0FFFFF;
			nojack--;
			Watchdog_Reset();		//Reset watchdog here, if we are stalled here the Millis timeout should catch us
		}
		USB_Configured_LED();
		EXTI_ONOFF_EN();			//Enable the off interrupt - allow some time for debouncing
		while(1) {				//If running off USB (mounted as mass storage), stay in this loop - dont turn on anything
			if(Millis%1000>500)		//1Hz on/off flashing
				switch_leds_on();	//Flash the LED(s)
			else
				switch_leds_off();
			Watchdog_Reset();
			__WFI();			//Sleep until something arrives
		}
	}
	else {
		if(!GET_PWR_STATE)			//Check here to make sure the power button is still pressed, if not, sleep
			shutdown();			//This means a glitch on the supply line, or a power glitch results in sleep
		EXTI_ONOFF_EN();			//Enable the off interrupt - allow some time for debouncing
		ADC_Configuration();			//At present this is purely here to detect low battery
		do {
			battery_voltage=Battery_Voltage;//Have to flush adc for some reason
			Delay(25000);
		} while(fabs(Battery_Voltage-battery_voltage)>0.01 || !battery_voltage);
		I2C_Config();				//Setup the I2C bus
		Sensors=detect_sensors(0);		//Search for connected sensors
		if(battery_voltage<BATTERY_STARTUP_LIMIT)
			deadly_flashes=1;
		if(!(Sensors&(1<<FOREHEAD_ACCEL)))	//Check for any missing sensors
			deadly_flashes=2;
		if(!(Sensors&(1<<(FOREHEAD_GYRO-1))))
			deadly_flashes=3;
		if(!(Sensors&(1<<(SFE_1_ACCEL-1))))
			deadly_flashes=4;
		if(!(Sensors&(1<<(SFE_1_MAGNO-1))))
			deadly_flashes=5;
		if(!(Sensors&(1<<(SFE_1_GYRO-1))))
			deadly_flashes=6;
		if(!(Sensors&(1<<(SFE_2_ACCEL-3))))
			deadly_flashes=7;
		if(!(Sensors&(1<<(SFE_2_MAGNO-3))))
			deadly_flashes=8;
		if(!(Sensors&(1<<(SFE_2_GYRO-3))))
			deadly_flashes=9;
		if((f_err_code = f_mount(0, &FATFS_Obj)))Usart_Send_Str((char*)"FatFs mount error\r\n");//This should only error if internal error
		else if(!deadly_flashes){		//FATFS and the I2C initialised ok, try init the card, this also sets up the SPI1
			if(!f_open(&FATFS_logfile,"time.txt",FA_OPEN_EXISTING | FA_READ | FA_WRITE)) {//Try and open a time file to get the system time
				if(!f_stat((const TCHAR *)"time.txt",&FATFS_info)) {//Get file info
					if(!FATFS_info.fsize) {//Empty file
						RTC_time.year=(FATFS_info.fdate>>9)+1980;//populate the time struct (FAT start==1980, RTC.year==0)
						RTC_time.month=(FATFS_info.fdate>>5)&0x000F;
						RTC_time.mday=FATFS_info.fdate&0x001F;
						RTC_time.hour=(FATFS_info.ftime>>11)&0x001F;
						RTC_time.min=(FATFS_info.ftime>>5)&0x003F;
						RTC_time.sec=(FATFS_info.ftime<<1)&0x003E;
						rtc_settime(&RTC_time);
						rprintfInit(__fat_print_char);//printf to the open file
						printf("RTC set to %d/%d/%d %d:%d:%d\n",RTC_time.mday,RTC_time.month,RTC_time.year,\
						RTC_time.hour,RTC_time.min,RTC_time.sec);
					}				
				}
				f_close(&FATFS_logfile);//Close the time.txt file
			}
			rtc_gettime(&RTC_time);		//Get the RTC time and put a timestamp on the start of the file
			rprintfInit(__str_print_char);	//Print to the string
			//timestamp name
			printf("%d-%02d-%02dT%02d-%02d-%02d",RTC_time.year,RTC_time.month,RTC_time.mday,RTC_time.hour,RTC_time.min,RTC_time.sec);
			rprintfInit(__usart_send_char);	//Printf over the bluetooth
			f_err_code = f_mkdir(print_string); //Try to make a directory where the logfiles will live
			if(f_err_code) {
				printf("FatFs drive error %d\r\n",f_err_code);
				if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY)
					Usart_Send_Str((char*)"No uSD card inserted?\r\n");
				repetition_counter=1;
			}
			else
				f_err_code=f_chdir(print_string);//enter our new directory
			if(f_err_code) {
				if(!repetition_counter)
					printf("FatFs drive error entering direcotry %d\r\n",f_err_code);
				repetition_counter=1;
			}
			else {
				strcat(print_string,".csv");
				f_err_code=f_open(&FATFS_logfile,print_string,FA_CREATE_ALWAYS | FA_WRITE);//Try to open the main 100sps csv logfile
			}
			if(f_err_code) {
				if(!repetition_counter)
					printf("FatFs drive error creating logfile %d\r\n",f_err_code);
				repetition_counter=1;
			}
			else {	
				print_string[strlen(print_string)-4]=0x00;	//Wipe the .csv off the string
				strcat(print_string,"_accel.wav");
				f_err_code=f_open(&FATFS_wavfile_accel,print_string,FA_CREATE_ALWAYS | FA_WRITE);//Try to open the accel wav logfile
			}
			if(f_err_code) {
				if(!repetition_counter)
					printf("FatFs drive error creating accel wav file %d\r\n",f_err_code);
				repetition_counter=1;
			}
			else {	
				print_string[strlen(print_string)-9]=0x00;	//Wipe the accel.wav off the string
				strcat(print_string,"gyro.wav");
				f_err_code=f_open(&FATFS_wavfile_gyro,print_string,FA_CREATE_ALWAYS | FA_WRITE);//Try to open the gyro wav logfile
			}
			if(f_err_code) {
				if(!repetition_counter)
					printf("FatFs drive error creating gyro wav file %d\r\n",f_err_code);
			}
			else {				//We have a mounted card
				print_string[0]=0x00;	//Wipe the string
				f_err_code=f_lseek(&FATFS_logfile, PRE_SIZE);// Pre-allocate clusters
				if (f_err_code || f_tell(&FATFS_logfile) != PRE_SIZE)// Check if the file size has been increased correctly
					Usart_Send_Str((char*)"Pre-Allocation error\r\n");
				else {
					if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing
						Usart_Send_Str((char*)"Seek error\r\n");
					else
						rprintfInit(__str_print_char);//Printf to the logfile
				}
				if(f_err_code)
					f_close(&FATFS_logfile);//Close the already opened file on error
				else
					file_opened=0x01;//So we know to close the file properly on shutdown - bit mask for the files
				if(!f_err_code) {
					f_err_code=f_lseek(&FATFS_wavfile_accel, PRE_SIZE);// Pre-allocate clusters
					if (f_err_code || f_tell(&FATFS_wavfile_accel) != PRE_SIZE)// Check if the file size has been increased correctly
						Usart_Send_Str((char*)"Pre-Allocation error\r\n");
					else {
						if((f_err_code=f_lseek(&FATFS_wavfile_accel, 0)))//Seek back to start of file to start writing
							Usart_Send_Str((char*)"Seek error\r\n");
					}
					if(f_err_code)
						f_close(&FATFS_wavfile_accel);//Close the already opened file on error
					else
						file_opened|=0x02;//So we know to close the file properly on shutdown - bit mask for the files
				}
				if(!f_err_code) {
					f_err_code=f_lseek(&FATFS_wavfile_gyro, PRE_SIZE);// Pre-allocate clusters
					if (f_err_code || f_tell(&FATFS_wavfile_gyro) != PRE_SIZE)// Check if the file size has been increased correctly
						Usart_Send_Str((char*)"Pre-Allocation error\r\n");
					else {
						if((f_err_code=f_lseek(&FATFS_wavfile_gyro, 0)))//Seek back to start of file to start writing
							Usart_Send_Str((char*)"Seek error\r\n");
					}
					if(f_err_code)
						f_close(&FATFS_wavfile_gyro);//Close the already opened file on error
					else
						file_opened|=0x04;//So we know to close the file properly on shutdown - bit mask for the files
				}
			}
		}
		repetition_counter=0;			//Reset this here	
		//We die, but flash out a number of flashes first
		if(f_err_code || deadly_flashes) {	//There was an init error
			for(;deadly_flashes;deadly_flashes--) {
				RED_LED_ON;
				Delay(200000);
				RED_LED_OFF;
				Delay(200000);
				Watchdog_Reset();
			}
			RED_LED_ON;
			Delay(400000);
			shutdown();			//Abort after a (further )single red flash
		}
	}
Esempio n. 2
0
int main(void)
{
	uint8_t system_state=0, i2c_resets=0, si446x_resets=0;//used to track button press functionality and any errors
	uint8_t sensors=0;
	uint32_t repetition_counter=0;			//Used to detect any I2C lockup
	uint8_t L3GD20_Data_Buffer_old[8];		//Used to test for noise in the gyro data (indicating that it is working)
	uint8_t UplinkFlags=0,CutFlags=0;
	uint16_t UplinkBytes=0;				//Counters and flags for telemetry
	uint32_t last_telemetry=0,cutofftime=0,indtest=0,badgyro=0,permission_time=0,countdown_time=0,last_cuttest=0;
	uint16_t sentence_counter=0;
	uint8_t silab;
	//Cutdown config stuff here, atm uses hardcoded polygon defined in polygon.h
	static const int32_t Geofence[UK_GEOFENCE_POINTS*2]=UK_GEOFENCE;
	RTC_t RTC_time;
        _REENT_INIT_PTR(&my_reent);
        _impure_ptr = &my_reent;
	SystemInit();					//Sets up the clk
	setup_gpio();					//Initialised pins, and detects boot source
	DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);	//Watchdog stopped during JTAG halt
	RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);/* Enable PWR and BKP clocks */
	PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */
	uint16_t shutdown_lock=BKP_ReadBackupRegister(BKP_DR3);	//Holds the shutdown lock setting
	uint16_t reset_counter=BKP_ReadBackupRegister(BKP_DR2); //The number of consecutive failed reboot cycles
	PWR_BackupAccessCmd(DISABLE);
	if(RCC->CSR&RCC_CSR_IWDGRSTF && shutdown_lock!=SHUTDOWNLOCK_MAGIC) {//Watchdog reset, turn off
		RCC->CSR|=RCC_CSR_RMVF;			//Reset the reset flags
		shutdown();
	}
	if(USB_SOURCE==bootsource) {
		RCC->CFGR &= ~(uint32_t)RCC_CFGR_PPRE1_DIV16;
		RCC->CFGR |= (uint32_t)RCC_CFGR_PPRE1_DIV4;//Swap the ABP1 bus to run at 12mhz rather than 4 if we booted from USB, makes USB fast enough
	}
	SysTick_Configuration();			//Start up system timer at 100Hz for uSD card functionality
	Watchdog_Config(WATCHDOG_TIMEOUT);		//Set the watchdog
	Watchdog_Reset();				//Reset watchdog as soon as possible incase it is still running at power on
	rtc_init();					//Real time clock initialise - (keeps time unchanged if set)
	Usarts_Init();
	ISR_Config();
	rprintfInit(__usart_send_char);			//Printf over the bluetooth
	if(USB_SOURCE==bootsource) {
		Set_System();				//This actually just inits the storage layer
		Set_USBClock();
		USB_Interrupts_Config();
		USB_Init();
		uint32_t nojack=0x000FFFFF;		//Countdown timer - a few hundered ms of 0v on jack detect forces a shutdown
		while (bDeviceState != CONFIGURED) {	//Wait for USB config - timeout causes shutdown
			if((Millis>10000 && bDeviceState == UNCONNECTED)|| !nojack)	//No USB cable - shutdown (Charger pin will be set to open drain, cant be disabled without usb)
				shutdown();
			if(GET_VBUS_STATE)		//Jack detect resets the countdown
				nojack=0x0FFFFF;
			nojack--;
			Watchdog_Reset();		//Reset watchdog here, if we are stalled here the Millis timeout should catch us
		}
		PWR_BackupAccessCmd(ENABLE);		/* Allow access to BKP Domain */
		BKP_WriteBackupRegister(BKP_DR3,0x0000);//Wipe the shutdown lock setting
		PWR_BackupAccessCmd(DISABLE);
		while(1) {
			if(!(Millis%1000) && bDeviceState == SUSPENDED) {
				Delay(100);
				if(!GET_VBUS_STATE)
					shutdown();
			}
			Watchdog_Reset();
			__WFI();			//Sleep mode
		}
	}
        if(!GET_PWR_STATE && !(CoreDebug->DHCSR&0x00000001) && shutdown_lock!=SHUTDOWNLOCK_MAGIC) {//Check here to make sure the power button is still pressed, if not, sleep if no debug and not in always on flight mode
                shutdown();                             //This means a glitch on the supply line, or a power glitch results in sleep
        }
	// check to see if battery has enough charge to start
	ADC_Configuration();				//We leave this a bit later to allow stabilisation
	{
	uint32_t t=Millis;
	while(Millis<(t+100)){__WFI();}			//Sensor+inst amplifier takes about 100ms to stabilise after power on
	}
	if(Battery_Voltage<BATTERY_STARTUP_LIMIT) {	//We will have to turn off
		if(reset_counter<10)
			shutdown();
	}
	Watchdog_Reset();				//Card Init can take a second or two
	// system has passed battery level check and so file can be opened
	{//Context
	uint8_t silabs_header[5]={};
	uint8_t* silabs_header_=NULL;			//Pointer to the array (if all goes ok)
	if((f_err_code = f_mount(0, &FATFS_Obj)))Usart_Send_Str((char*)"FatFs mount error\r\n");//This should only error if internal error
	else {						//FATFS initialised ok, try init the card, this also sets up the SPI1
		if(!(f_err_code=f_open(&FATFS_logfile,(const TCHAR*)"time.txt",FA_OPEN_EXISTING|FA_READ|FA_WRITE))){//Try to open time file get system time
			if(!f_stat((const TCHAR *)"time.txt",&FATFS_info)) {//Get file info
				if(FATFS_info.fsize<5) {	//Empty file
					RTC_time.year=(FATFS_info.fdate>>9)+1980;//populate the time struct (FAT start==1980, RTC.year==0)
					RTC_time.month=(FATFS_info.fdate>>5)&0x000F;
					RTC_time.mday=FATFS_info.fdate&0x001F;
					RTC_time.hour=(FATFS_info.ftime>>11)&0x001F;
					RTC_time.min=(FATFS_info.ftime>>5)&0x003F;
					RTC_time.sec=(FATFS_info.ftime<<1)&0x003E;
					rtc_settime(&RTC_time);
					rprintfInit(__fat_print_char);//printf to the open file
					printf("RTC set to %d/%d/%d %d:%d:%d\n",RTC_time.mday,RTC_time.month,RTC_time.year,\
					RTC_time.hour,RTC_time.min,RTC_time.sec);
				}				
			}
			f_close(&FATFS_logfile);	//Close the time.txt file
		}
		// load settings if file exists
		Watchdog_Reset();			//Card Init can take a second or two
		if(!f_open(&FATFS_logfile,(const TCHAR *)"settings.dat",FA_OPEN_EXISTING | FA_READ)) {
			UINT br;
			int8_t rtc_correction;
			f_read(&FATFS_logfile, (void*)(&rtc_correction),sizeof(rtc_correction),&br);
			//Use the setting to apply correction to the RTC
                        if(br && (rtc_correction<30) && (rtc_correction>-92) && rtc_correction ) {
                                PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */
                                uint16_t tweaked_prescale = (0x0001<<15)-2;/* Try to run the RTC slightly too fast so it can be corrected either way */
                                RTC_WaitForSynchro();   /* Wait for RTC registers synchronization */
                                if( RTC->PRLL != tweaked_prescale ) {/*Note that there is a 0.5ppm offset here (correction 0==0.5ppm slow)*/
                                        RTC_SetPrescaler(tweaked_prescale); /* RTC period = RTCCLK/RTC_PR = (32.768 KHz)/(32767-2+1) */
                                        RTC_WaitForLastTask();
                                }
                                BKP_SetRTCCalibrationValue((uint8_t) ((int16_t)31-(21*(int16_t)rtc_correction)/(int16_t)20) );
                                BKP_RTCOutputConfig(BKP_RTCOutputSource_None);/* Ensure any output is disabled here */
                                /* Lock access to BKP Domain */
                                PWR_BackupAccessCmd(DISABLE);
                        }
                        else if(br && ((uint8_t)rtc_correction==0x91) ) {/* 0x91 magic flag sets the RTC clock output on */
                                PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */
                                BKP_RTCOutputConfig(BKP_RTCOutputSource_CalibClock);/* Output a 512Hz reference clock on the TAMPER pin*/
                                PWR_BackupAccessCmd(DISABLE);
                        }
			if(br) {
				f_read(&FATFS_logfile, (void*)(&shutdown_lock),sizeof(shutdown_lock),&br);/*This needs to be set with the same magic flag value*/
				if(br==2) {
                                	PWR_BackupAccessCmd(ENABLE);/* Allow access to BKP Domain */
					BKP_WriteBackupRegister(BKP_DR3,shutdown_lock);//Wipe the shutdown lock setting
                               		PWR_BackupAccessCmd(DISABLE);
				}
			}
			if(br==2) {			//Read was successful, next try to read 5 bytes of packet header
				f_read(&FATFS_logfile, (void*)(silabs_header),5,&br);
				if(br!=5)
					silabs_header_=silabs_header;
			}
			f_close(&FATFS_logfile);	//Close the settings.dat file
		}
#ifndef SINGLE_LOGFILE
		rtc_gettime(&RTC_time);			//Get the RTC time and put a timestamp on the start of the file
		rprintfInit(__str_print_char);		//Print to the string
		printf("%02d-%02d-%02dT%02d-%02d-%02d-%s.csv",RTC_time.year,RTC_time.month,RTC_time.mday,RTC_time.hour,RTC_time.min,RTC_time.sec,"Log");//Timestamp name
		rprintfInit(__usart_send_char);		//Printf over the bluetooth
#endif
		Watchdog_Reset();			//Card Init can take a second or two
		if((f_err_code=f_open(&FATFS_logfile,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Present
			Delay(10000);
			if((f_err_code=f_open(&FATFS_logfile,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Try again
				printf("FatFs drive error %d\r\n",f_err_code);
				if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY)
					Usart_Send_Str((char*)"No uSD card inserted?\r\n");
			}
		}
		else {
			Watchdog_Reset();		//Card Init can take a second or two
			print_string[strlen(print_string)-4]=0x00;//Wipe the .csv off the string
			strcat(print_string,"_gyro.wav");
			if((f_err_code=f_open(&FATFS_wavfile_gyro,(TCHAR*)LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Present
				printf("FatFs drive error %d\r\n",f_err_code);
				if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY)
					Usart_Send_Str((char*)"No uSD card inserted?\r\n");
			}
			else {					//We have a mounted card
				f_err_code=f_lseek(&FATFS_logfile, PRE_SIZE);// Pre-allocate clusters
				if (f_err_code || f_tell(&FATFS_logfile) != PRE_SIZE)// Check if the file size has been increased correctly
					Usart_Send_Str((char*)"Pre-Allocation error\r\n");
				else {
					if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing
						Usart_Send_Str((char*)"Seek error\r\n");
					else
						rprintfInit(__str_print_char);//Printf to the logfile
				}
				if(f_err_code)
					f_close(&FATFS_logfile);//Close the already opened file on error
				else
					file_opened=1;		//So we know to close the file properly on shutdown
				if(file_opened==1) {
					Watchdog_Reset();	//Card Init can take a second or two
					if (f_err_code || f_tell(&FATFS_wavfile_gyro) != PRE_SIZE)// Check if the file size has been increased correctly
						Usart_Send_Str((char*)"Pre-Allocation error\r\n");
					else {
						if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing
							Usart_Send_Str((char*)"Seek error\r\n");
						else
							rprintfInit(__str_print_char);//Printf to the logfile
					}
					if(f_err_code)
						f_close(&FATFS_wavfile_gyro);//Close the already opened file on error
					else
						file_opened|=2;	//So we know to close the file properly on shutdown
				}
			}
		}
	}
	f_err_code|=write_wave_header(&FATFS_wavfile_gyro, 4, 100, 16);//4 channels, last channel is for the current rpm
	Watchdog_Reset();				//Card Init can take a second or two
	//Setup and test the silabs radio
	silab=si446x_setup(silabs_header_);
	if(silab!=0x44) {				//Should return the device code
		print_string[0]=0x00;
		printf("Silabs: %02x\n",silab);
		f_puts("Silabs detect error, got:",&FATFS_logfile);
		f_puts(print_string,&FATFS_logfile);
		shutdown_filesystem(ERR, file_opened);//So we log that something went wrong in the logfile
		shutdown();
	}
	}//Context
Esempio n. 3
0
int main(void)
{
	uint32_t ppg;					//PPG channel
	uint32_t data_counter=0;			//used as data timestamp
	uint8_t system_state=0;				//used to track button press functionality
	float sensor_data;				//used for handling data passed back from sensors
	RTC_t RTC_time;
        _REENT_INIT_PTR(&my_reent);
        _impure_ptr = &my_reent;
	SystemInit();					//Sets up the clk
	setup_gpio();					//Initialised pins, and detects boot source
	DBGMCU_Config(DBGMCU_IWDG_STOP, ENABLE);	//Watchdog stopped during JTAG halt
	if(RCC->CSR&RCC_CSR_IWDGRSTF) {			//Watchdog reset, turn off
		RCC->CSR|=RCC_CSR_RMVF;			//Reset the reset flags
		shutdown();
	}
	SysTick_Configuration();			//Start up system timer at 100Hz for uSD card functionality
	Watchdog_Config(WATCHDOG_TIMEOUT);		//Set the watchdog
	Watchdog_Reset();				//Reset watchdog as soon as possible incase it is still running at power on
	rtc_init();					//Real time clock initialise - (keeps time unchanged if set)
	Usarts_Init();
	ISR_Config();
	rprintfInit(__usart_send_char);			//Printf over the bluetooth
	if(USB_SOURCE==bootsource) {
		Set_System();				//This actually just inits the storage layer
		Set_USBClock();
		USB_Interrupts_Config();
		USB_Init();
		uint32_t nojack=0x000FFFFF;		//Countdown timer - a few hundered ms of 0v on jack detect forces a shutdown
		while (bDeviceState != CONFIGURED) {	//Wait for USB config - timeout causes shutdown
			if(Millis>10000 || !nojack)	//No USB cable - shutdown (Charger pin will be set to open drain, cant be disabled without usb)
				shutdown();
			if(GET_VBUS_STATE)		//Jack detect resets the countdown
				nojack=0x0FFFFF;
			nojack--;
			Watchdog_Reset();		//Reset watchdog here, if we are stalled here the Millis timeout should catch us
		}
		USB_Configured_LED();
		EXTI_ONOFF_EN();			//Enable the off interrupt - allow some time for debouncing
		while(1) {				//If running off USB (mounted as mass storage), stay in this loop - dont turn on anything
			if(Millis%1000>500)		//1Hz on/off flashing
				switch_leds_on();	//Flash the LED(s)
			else
				switch_leds_off();
			Watchdog_Reset();
		}
	}
	if(!GET_PWR_STATE)				//Check here to make sure the power button is still pressed, if not, sleep
		shutdown();				//This means a glitch on the supply line, or a power glitch results in sleep
	for(uint8_t n=0;n<PPG_CHANNELS;n++)
		init_buffer(&(Buff[n]),PPG_BUFFER_SIZE);//Enough for ~0.25S of data
	setup_pwm();					//Enable the PWM outputs on all three channels
	Delay(100000);					//Sensor+inst amplifier takes about 100ms to stabilise after power on
	ADC_Configuration();				//We leave this a bit later to allow stabilisation
	calibrate_sensor();				//Calibrate the offset on the diff pressure sensor
	EXTI_ONOFF_EN();				//Enable the off interrupt - allow some time for debouncing
	I2C_Config();					//Setup the I2C bus
	uint8_t sensors_=detect_sensors();		//Search for connected sensors
	sensor_data=GET_BATTERY_VOLTAGE;		//Have to flush adc for some reason
	Delay(10000);
	if(!(sensors_&~(1<<PRESSURE_HOSE))||GET_BATTERY_VOLTAGE<BATTERY_STARTUP_LIMIT) {//We will have to turn off
		Watchdog_Reset();			//LED flashing takes a while
		if(abs(Reported_Pressure)>PRESSURE_MARGIN)
			Set_Motor(-1);			//If the is air backpressure, dump to rapidly drop to zero pressure before turnoff
		if(file_opened)
			f_close(&FATFS_logfile);	//be sure to terminate file neatly
		red_flash();
		Delay(400000);
		red_flash();				//Two flashes means battery abort -----------------ABORT 2
		if(sensors_&~(1<<PRESSURE_HOSE))
			shutdown();
		Delay(400000);
		red_flash();				//Three flashes means no sensors abort ------------ABORT 3
		shutdown();
	}
	if((f_err_code = f_mount(0, &FATFS_Obj)))Usart_Send_Str((char*)"FatFs mount error\r\n");//This should only error if internal error
	else {						//FATFS initialised ok, try init the card, this also sets up the SPI1
		if(!f_open(&FATFS_logfile,"time.txt",FA_OPEN_EXISTING | FA_READ | FA_WRITE)) {//Try and open a time file to get the system time
			if(!f_stat((const TCHAR *)"time.txt",&FATFS_info)) {//Get file info
				if(!FATFS_info.fsize) {	//Empty file
					RTC_time.year=(FATFS_info.fdate>>9)+1980;//populate the time struct (FAT start==1980, RTC.year==0)
					RTC_time.month=(FATFS_info.fdate>>5)&0x000F;
					RTC_time.mday=FATFS_info.fdate&0x001F;
					RTC_time.hour=(FATFS_info.ftime>>11)&0x001F;
					RTC_time.min=(FATFS_info.ftime>>5)&0x003F;
					RTC_time.sec=(FATFS_info.ftime<<1)&0x003E;
					rtc_settime(&RTC_time);
					rprintfInit(__fat_print_char);//printf to the open file
					printf("RTC set to %d/%d/%d %d:%d:%d\n",RTC_time.mday,RTC_time.month,RTC_time.year,\
					RTC_time.hour,RTC_time.min,RTC_time.sec);
				}				
			}
			f_close(&FATFS_logfile);	//Close the time.txt file
		}
#ifndef SINGLE_LOGFILE
		rtc_gettime(&RTC_time);			//Get the RTC time and put a timestamp on the start of the file
		rprintfInit(__str_print_char);		//Print to the string
		printf("%d-%d-%dT%d-%d-%d.txt",RTC_time.year,RTC_time.month,RTC_time.mday,RTC_time.hour,RTC_time.min,RTC_time.sec);//Timestamp name
		rprintfInit(__usart_send_char);		//Printf over the bluetooth
#endif
		if((f_err_code=f_open(&FATFS_logfile,LOGFILE_NAME,FA_CREATE_ALWAYS | FA_WRITE))) {//Present
			printf("FatFs drive error %d\r\n",f_err_code);
			if(f_err_code==FR_DISK_ERR || f_err_code==FR_NOT_READY)
				Usart_Send_Str((char*)"No uSD card inserted?\r\n");
		}
		else {					//We have a mounted card
			f_err_code=f_lseek(&FATFS_logfile, PRE_SIZE);// Pre-allocate clusters
			if (f_err_code || f_tell(&FATFS_logfile) != PRE_SIZE)// Check if the file size has been increased correctly
				Usart_Send_Str((char*)"Pre-Allocation error\r\n");
			else {
				if((f_err_code=f_lseek(&FATFS_logfile, 0)))//Seek back to start of file to start writing
					Usart_Send_Str((char*)"Seek error\r\n");
				else
					rprintfInit(__str_print_char);//Printf to the logfile
			}
			if(f_err_code)
				f_close(&FATFS_logfile);//Close the already opened file on error
			else
				file_opened=1;		//So we know to close the file properly on shutdown
		}
	}