예제 #1
0
void init_watchdog(void) {
  /* Enable interface clock */
  LPC_SYSCON->SYSAHBCLKCTRL |= (1 << 15);

  LPC_SYSCON->WDTCLKSEL = 0x0; // Use IRC oscillator
  LPC_SYSCON->WDTCLKUEN = 1; // Switch Clock
  LPC_SYSCON->WDTCLKUEN = 0;
  LPC_SYSCON->WDTCLKUEN = 1; // Switch Clock
  LPC_SYSCON->WDTCLKDIV = 1;

  /* IRC = 12MHz, TC = 4 * 12*10_6, => Twdt = 4 seconds */
  LPC_WDT->TC = 12*1000*1000; // MAX: 2^24

  /* Lock on the watchdog */
  LPC_WDT->MOD |= 0x3; // WDEN = 1, WDRESET = 1

  /* And feed to enable */
  feed_watchdog();

  /* Make sure feed sequence completed */
  for (int i = 0; i < 0x80000; i++);
}
예제 #2
0
파일: thermometer.c 프로젝트: yzkqfll/ibaby
/*********************************************************************
 * @fn      Thermometer_ProcessEvent
 *
 * @brief   Thermometer Application Task event processor.  This function
 *          is called to process all events for the task.  Events
 *          include timers, messages and any other user defined events.
 *
 * @param   task_id  - The OSAL assigned task ID.
 * @param   events - events to process.  This is a bit map and can
 *                   contain more than one event.
 *
 * @return  events not processed
 */
uint16 Thermometer_ProcessEvent(uint8 task_id, uint16 events)
{
	struct ther_info *ti = &ther_info;

	/* message handle */
	if ( events & SYS_EVENT_MSG ) {
		uint8 *msg;

		if ( (msg = osal_msg_receive(ti->task_id)) != NULL ) {
			ther_dispatch_msg(ti, (osal_event_hdr_t *)msg);

			osal_msg_deallocate( msg );
		}

		return (events ^ SYS_EVENT_MSG);
	}

	if (events & TH_POWER_ON_EVT) {
		ther_system_power_on(ti);

		return (events ^ TH_POWER_ON_EVT);
	}

	if (events & TH_POWER_OFF_EVT) {
		ther_system_power_off_post(ti);

		return (events ^ TH_POWER_OFF_EVT);
	}

	if (events & TH_AUTO_POWER_OFF_EVT) {
		if (!ti->ble_connect &&
			((ti->previous_temp >= ti->temp_current && ti->previous_temp - ti->temp_current < 50) ||
			(ti->previous_temp < ti->temp_current && ti->temp_current - ti->previous_temp < 50))) {

			ti->same_temp_number++;
		} else {
			ti->same_temp_number = 0;
//			ti->previous_temp = ti->temp_current;
		}

		print(LOG_DBG, MODULE "auto power off: same_temp_number %d\n", ti->same_temp_number);

		if (ti->same_temp_number >= AUTO_POWER_OFF_NUMBER_THRESHOLD) {
			print(LOG_DBG, MODULE "auto power off\n");
			ther_system_power_off_pre(ti);
		} else {
			osal_start_timerEx( ti->task_id, TH_AUTO_POWER_OFF_EVT, AUTO_POWER_OFF_MEASURE_INTERVAL);
		}

		return (events ^ TH_AUTO_POWER_OFF_EVT);
	}

	/* batt measure */
	if (events & TH_BATT_EVT) {
		if (ti->mode == NORMAL_MODE) {
			Batt_MeasLevel();
			ti->batt_percentage = ther_batt_get_percentage(FALSE);
			oled_update_picture(OLED_CONTENT_BATT, TRUE, ti->batt_percentage);
			print(LOG_DBG, MODULE "batt %d%%\n", ti->batt_percentage);

			if (!ti->batt_warning_on && ti->batt_percentage < 10) {
				ti->batt_warning_on = TRUE;
				osal_start_timerEx( ti->task_id, TH_LOW_BATT_WARNING_EVT, LOW_BATT_WARNING_INTERVAL);
			}

			osal_start_timerEx( ti->task_id, TH_BATT_EVT, BATT_MEASURE_INTERVAL);
		}

		return (events ^ TH_BATT_EVT);
	}

	if (events & TH_LOW_BATT_BLINK_EVT) {
		if (ti->batt_in_dispaly) {
			oled_update_picture(OLED_CONTENT_BATT, FALSE, 0);
			ti->batt_in_dispaly = FALSE;
		} else {
			oled_update_picture(OLED_CONTENT_BATT, TRUE, ti->batt_percentage);
			ti->batt_in_dispaly = TRUE;
		}

		if (ti->display_picture != OLED_PICTURE_NONE)
			osal_start_timerEx(ti->task_id, TH_LOW_BATT_BLINK_EVT, LOW_BATT_BLINK_INTERVAL);

		return (events ^ TH_LOW_BATT_BLINK_EVT);
	}

	if (events & TH_LOW_BATT_WARNING_EVT) {
		ther_buzzer_start_music(BUZZER_MUSIC_LOW_BATT_WARNING);

		if (ti->batt_percentage < LOW_BATT_WARNING_THRESHOLD)
			osal_start_timerEx( ti->task_id, TH_LOW_BATT_WARNING_EVT, LOW_BATT_WARNING_INTERVAL);
		else
			ti->batt_warning_on = FALSE;

		return (events ^ TH_LOW_BATT_WARNING_EVT);
	}

	/* temp measure event */
	if (events & TH_TEMP_MEASURE_EVT) {

		if (ti->mode != NORMAL_MODE) {
			return (events ^ TH_TEMP_MEASURE_EVT);
		}

		switch (ti->temp_measure_stage) {
		case TEMP_STAGE_SETUP:
			ther_temp_power_on();

			osal_start_timerEx( ti->task_id, TH_TEMP_MEASURE_EVT, TEMP_POWER_SETUP_TIME);
			ti->temp_measure_stage = TEMP_STAGE_MEASURE;
			break;

		case TEMP_STAGE_MEASURE:

			ti->temp_last_saved = ti->temp_current;
			ti->temp_current = (int16)(ther_read_temp() * 100 + 0.5);
			ther_temp_power_off();

			/* for auto power off, save only once */
			if (ti->previous_temp == 0)
				ti->previous_temp = ti->temp_current;

			if (ti->temp_max < ti->temp_current) {
				ti->temp_max = ti->temp_current;
				print(LOG_DBG, MODULE "update max temp to %d\n", ti->temp_max);
				oled_update_picture(OLED_CONTENT_MAX_TEMP, TRUE, ti->temp_max);
			}

			/* high temp warning */
			if (ti->warning_enabled && !ti->temp_warning_on && ti->temp_current >= ti->next_warning_threshold) {
				ti->temp_warning_on = TRUE;
				osal_start_timerEx( ti->task_id, TH_HIGH_TEMP_WARNING_EVT, HIGH_TEMP_WARNING_INTERVAL);
			}
			if (ti->temp_warning_on && ti->temp_current < ti->next_warning_threshold) {
				ti->next_warning_threshold -= 50; /* 0.5 C */
				if (ti->next_warning_threshold < ti->high_temp_threshold)
					ti->next_warning_threshold = ti->high_temp_threshold;

				ti->temp_warning_on = FALSE;
				osal_stop_timerEx(ti->task_id, TH_HIGH_TEMP_WARNING_EVT);
			}

			if (ti->ble_connect) {
				if (ti->temp_notification_enable) {
//					ther_send_temp_notify(ti->temp_current);
				}
				if (ti->temp_indication_enable) {
					ther_send_temp_indicate(ti->task_id, ti->temp_current);
				}
			} else {
				ther_save_temp_to_local(ti->temp_current);
			}

			if (ti->temp_current != ti->temp_last_saved) {
				oled_update_picture(OLED_CONTENT_TEMP, TRUE, ti->temp_current);
			}

			osal_start_timerEx( ti->task_id, TH_TEMP_MEASURE_EVT, ti->temp_measure_interval);
			ti->temp_measure_stage = TEMP_STAGE_SETUP;
			break;

		default:
			break;
		}

		return (events ^ TH_TEMP_MEASURE_EVT);
	}

	if (events & TH_HIGH_TEMP_WARNING_EVT) {
		ther_buzzer_start_music(BUZZER_MUSIC_HIGH_TEMP_WARNING);
		osal_start_timerEx( ti->task_id, TH_HIGH_TEMP_WARNING_EVT, HIGH_TEMP_WARNING_INTERVAL);

		return (events ^ TH_HIGH_TEMP_WARNING_EVT);
	}

	if (events & TH_HIS_TEMP_RESTORE_EVT) {
		if (!ti->his_temp_bundle) {
			if (ti->temp_notification_enable) {
				storage_restore_temp((uint8 **)&ti->his_temp_bundle, &ti->his_temp_len);
				if (ti->his_temp_bundle) {
					ti->his_temp_offset = 0;
					osal_start_timerEx(ti->task_id, TH_HIS_TEMP_RESTORE_EVT, HIS_TEMP_UPLOADING_INTERVAL);
				} else {
					print(LOG_DBG, MODULE "his temp restore: no more his temp, exit\n");
					ti->his_temp_uploading = FALSE;
				}

			} else if (!ti->ble_connect) {
				print(LOG_DBG, MODULE "his temp restore: ble disconnect, exit\n");
				ti->his_temp_uploading = FALSE;

			} else {
//				print(LOG_DBG, MODULE "his temp restore: wait for notify enable\n");
				osal_start_timerEx(ti->task_id, TH_HIS_TEMP_RESTORE_EVT, HIS_TEMP_RESTORE_WAIT_ENABLE);
			}

		} else {
			if (ti->his_temp_offset < ti->his_temp_len) {
				uint8 *data = ti->his_temp_bundle + ti->his_temp_offset;

				ther_send_history_temp(ti->task_id, data, sizeof(struct temp_data));

				ti->his_temp_offset += sizeof(struct temp_data);
			} else {
				ti->his_temp_bundle = NULL;
				ti->his_temp_offset = 0;
				ti->his_temp_len = 0;
				print(LOG_DBG, MODULE "his temp restore: a bundle uploading completed\n");
			}
			osal_start_timerEx(ti->task_id, TH_HIS_TEMP_RESTORE_EVT, HIS_TEMP_UPLOADING_INTERVAL);
		}

		return (events ^ TH_HIS_TEMP_RESTORE_EVT);
	}

	/* Display event */
	if (events & TH_DISPLAY_EVT) {

		oled_display_state_machine();

		return (events ^ TH_DISPLAY_EVT);
	}

	/* buzzer event */
	if (events & TH_BUZZER_EVT) {
		ther_buzzer_playing_music();

		return (events ^ TH_BUZZER_EVT);
	}

	/* button event */
	if (events & TH_BUTTON_EVT) {
		ther_measure_button_time();

		return (events ^ TH_BUTTON_EVT);
	}

	if (events & TH_WATCHDOG_EVT) {
		feed_watchdog();
		osal_start_timerEx(ti->task_id, TH_WATCHDOG_EVT, WATCHDOG_FEED_INTERVAL);

		return (events ^ TH_WATCHDOG_EVT);
	}


	if (events & TH_TEST_EVT) {
		{
			struct display_param param;

			if (ti->display_picture > OLED_PICTURE_NONE) {
				print(LOG_DBG, MODULE "ignore button press when picture is %d\n", ti->display_picture);
				return (events ^ TH_TEST_EVT);
			}

			encap_picture_param(ti, &param);
			if (ti->display_picture == OLED_PICTURE_NONE) {
				oled_show_picture(OLED_PICTURE1, DISPLAY_TIME, &param);

			} else {
				oled_show_next_picture(DISPLAY_TIME, &param);
			}
		}
		osal_start_timerEx(ti->task_id, TH_TEST_EVT, SEC_TO_MS(10 * 60));

		return (events ^ TH_TEST_EVT);
	}

	return 0;
}
예제 #3
0
/**
 * Main system entry point
 */
int main (void) {
  SystemInit();

  /* Initialise Pins */
  CUTDOWN_OFF();
  HEATER_OFF();
  MBED_OFF();
  GREEN_OFF();

  /* Update the value of SystemCoreClock */
  SystemCoreClockUpdate();

  /* Initialise Interfaces */
  i2c_init();
  spi_init(process_imu_frame); // IMU
  sd_spi_init(); // SD
  uart_init(); // GPS
  pwrmon_init(); // ADC

  /* Initialise Sensors */
  init_barometer();

  /* SD Card */
  if (initialise_card()) { // Initialised to something
    if (disk_initialize() == 0) { // Disk initialisation was successful
      sd_good = 1;
    }
  }

  GREEN_ON();

  /* Configure the SysTick */
  NVIC_SetPriority(SysTick_IRQn, 0); // Highest Priority Interrupt
  SysTick_Config(SystemCoreClock / RTTY_BAUD);

  /* Watchdog - Disabled for debugging */
#ifndef WATCHDOG_DISABLED
  init_watchdog();
#endif

  struct barometer* b;
  struct imu_raw ir;
  struct gps_data gd;
  struct gps_time gt;
  double alt, ext_temp;
  int tx_length; // The length of the built tx string

  char tx_string[TX_STRING_LENGTH];

  while (1) {
    /* Grab Data */
    pwrmon_start(pwrmon_callback);
    b = get_barometer();
    get_imu_raw_data(&ir);
    get_gps_data(&gd);
    get_gps_time(&gt);
    ext_temp = get_temperature();

    /* Data Processing */
    if (b->valid) {
      alt = pressure_to_altitude(b->pressure);
    } else {
      alt = -1;
      b->temperature = -1;
    }

    /* Act on the data */
    control_gsm(alt);
    control_cutdown(ticks_until_cutdown, alt);
    control_heater(b->temperature);

    /* Create a protocol string */
    int cutstat;
    if (ticks_until_cutdown == 0) {
      cutstat = -1;
    } else {
      cutstat = ticks_until_cutdown / (RTTY_BAUD*60);
    }
    tx_length = build_communications_frame(tx_string, TX_STRING_LENGTH,
					   &gt, b, &gd, alt, ext_temp, &ir,
					   cutstat,  cutdown_voltage);

    /* Transmit - Quietly fails if another transmission is ongoing */
    rtty_set_string(tx_string, tx_length);

    /* Store */
    if (sd_good) {
      tx_length -= 2; // Remove \n\0
      tx_length += communications_frame_add_extra(tx_string + tx_length,
				     TX_STRING_LENGTH - tx_length, &ir);

      disk_write_next_block((uint8_t*)tx_string, tx_length+1); // Include null terminator
    }

    /* Housekeeping */
    GREEN_TOGGLE();
    feed_watchdog();
  }
}