/** \brief Light & proximity sensor demo application entry
 *
 * After initializing the Xplained platform and sensor boards, this application
 * attaches descriptors to the ambient light and proximity sensor devices on
 * an Xplained inertial sensor board.  The sensor data, which is formatted and
 * printed via printf() after being read, can be viewed with a serial terminal
 * application on a machine attached to the USB interface on the Xplained
 * board.
 */
int main(void)
{
	sensor_t light_dev;     /* Light sensor device descriptor */
	sensor_t prox_dev;      /* Proximity sensor device descriptor */

	/* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards)
	 * I/O pin mappings and any other configurable resources selected in
	 * the build configuration.
	 */
	sensor_platform_init();

	/* Attach descriptors to the defined sensor devices. */
	sensor_attach(&light_dev, SENSOR_TYPE_LIGHT, 0, 0);
	sensor_attach(&prox_dev, SENSOR_TYPE_PROXIMITY, 0, 0);

	if (light_dev.err || prox_dev.err) {
		puts("\rSensor initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

	/* Print sensor information */
	if (PRINT_BANNER) {
		static const char *const banner_format
			= "%s\r\nID = 0x%02x ver. 0x%02x\r\n"
				"Bandwidth = %d Hz  Range = +/- %d\r\n\n";

		uint32_t id;
		uint8_t version;
		int16_t freq, range;

		sensor_device_id(&light_dev, &id, &version);
		sensor_get_bandwidth(&light_dev, &freq);
		sensor_get_range(&light_dev, &range);

		printf(banner_format, light_dev.drv->caps.name,
				(unsigned)id, (unsigned)version, freq, range);

		sensor_device_id(&prox_dev, &id, &version);
		sensor_get_bandwidth(&prox_dev, &freq);
		sensor_get_range(&prox_dev, &range);

		printf(banner_format, prox_dev.drv->caps.name,
				(unsigned)id, (unsigned)version, freq, range);

		delay_ms(500);
	}

	/* Set sample interval for the light sensor */
	if (sensor_set_sample_rate(&light_dev, LIGHT_SAMPLE_RATE) != true) {
		printf("Error setting light sensor sample rate.\r\n");
	}

	/* Set sample interval for the proximity sensor */
	if (sensor_set_sample_rate(&prox_dev, PROX_SAMPLE_RATE) != true) {
		printf("Error setting proximity sensor sample rate.\r\n");
	}

	/* Select all proximity sensor channels */
	sensor_set_channel(&prox_dev, SENSOR_CHANNEL_ALL);

#if (SET_PROX_THRESHOLD == true)
	/* Manually set proximity threshold values for each channel */
	/* Otherwise, sensor will use values previously stored in nvram. */
	sensor_set_threshold(&prox_dev, SENSOR_THRESHOLD_NEAR_PROXIMITY,
			PROX_THRESHOLD);
#endif

#if (SET_PROX_CURRENT == true)
	/* Manually set LED current value for each channel */
	/* Otherwise, sensor will use default values. */
	sensor_set_current(&prox_dev, PROX_CURRENT_mA);
#endif

	/* Initialize sensor data descriptors for scaled vs. raw data. */
	static sensor_data_t light_data = {.scaled = SCALED_DATA};
	static sensor_data_t prox_data  = {.scaled = SCALED_DATA};

	while (true) {
		LED_Toggle(ACTIVITY_LED);

		/* Read sensor values */
		sensor_get_light(&light_dev, &light_data);
		sensor_get_proximity(&prox_dev, &prox_data);

		/* Print sensor values */
		if (SCALED_DATA) {
			printf("light = [%5d]\r\n",
					(int16_t)light_data.light.value);

			printf("prox  = 1:%s 2:%s 3:%s\r\n",
					prox_labels[prox_data.proximity.value[0]],
					prox_labels[prox_data.proximity.value[1]],
					prox_labels[prox_data.proximity.value[2]]);
		} else {
			printf("light = [%5d]\r\n",
					(int16_t)light_data.light.value);

			printf("prox = [%.5x, %.5x, %.5x]\r\n",
					(int16_t)prox_data.proximity.value[0],
					(int16_t)prox_data.proximity.value[1],
					(int16_t)prox_data.proximity.value[2]);
		}

		delay_ms(500);
	}

	return 0;
}
Example #2
0
/** \brief Inertial sensor demo application entry
 *
 * After initializing the Xplained platform and sensor boards, this application
 * attaches descriptors to the accelerometer and gyroscope devices on
 * an Xplained inertial sensor board.  The sensor data, which is formatted and
 * printed via printf() after being read, can be viewed with a serial terminal
 * application on a machine attached to the USB interface on the Xplained
 * board.
 */
int main(void)
{
	/* Initialize the Xplained (UC3 or XMEGA) platform & sensor boards. */
	sensor_platform_init();

	LED_On(ACTIVITY_LED);

	/* Initialize the MCU sleep manager API and specify a sleep mode. */
	sleepmgr_init();
	sleepmgr_lock_mode(SLEEP_MODE);

#if (USE_ACCEL == true)
	/* Attach accelerometer */
	sensor_attach(&accelerometer, SENSOR_TYPE_ACCELEROMETER, 0, 0);

	if (accelerometer.err) {
		puts("\r\nAccelerometer initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

	/* Enable motion event */
	sensor_set_threshold(&accelerometer, SENSOR_THRESHOLD_MOTION,
			ACCEL_MOT_THRESH);

	sensor_add_event(&accelerometer, SENSOR_EVENT_MOTION,
			acceleration_event, 0, true);

	/* Put the accelerometer into a low-power mode (if available) */
	sensor_set_state(&accelerometer, SENSOR_STATE_LOW_POWER);
#endif

#if (USE_GYRO == true)
	/* Attach gyroscope */
	sensor_attach(&gyroscope, SENSOR_TYPE_GYROSCOPE, 0, 0);

	if (gyroscope.err) {
		puts("\r\nGyroscope initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

	sensor_set_sample_rate(&gyroscope, GYRO_SAMPLE_RATE);

#  if (GYRO_WAKE == true)
	/* Enable gyroscope new data event for wakeup */
	sensor_add_event(&gyroscope, SENSOR_EVENT_NEW_DATA,
			rotation_event, 0, true);
#  elif (GYRO_SLEEP == true)
	/* Put gyro in low-power sleep mode until accelerometer wakes system up */
	sensor_set_state(&gyroscope, SENSOR_STATE_SLEEP);
#  endif
#endif

	while (true) {
		LED_Off(ACTIVITY_LED);/* turn off while asleep */

		/* Put device in low power sleep mode until woken up by an interrupt */
		sleepmgr_enter_sleep(); /* enter specified sleep mode */

		/* Device has woken up */
		LED_On(ACTIVITY_LED);             /* turn on while awake */

#if ((USE_GYRO == true) && (GYRO_WAKE == false))
#  if (GYRO_SLEEP == true)
		/* Wake up gyroscope, wait for device to settle */
		sensor_set_state(&gyroscope, SENSOR_STATE_NORMAL);
		delay_ms(GYRO_RESTART_DELAY);

		/* Read gyroscope and put it back to sleep */
		sensor_get_rotation(&gyroscope, &rotation);
		sensor_set_state(&gyroscope, SENSOR_STATE_SLEEP);
#  else
		/* Read gyro in response to accelerometer wake */
		sensor_get_rotation(&gyroscope, &rotation); /* read gyro now */
#  endif
#endif

#if (USE_PRINTF == true)
		const char *const format = SCALED_DATA ?
				"acc = [%5d, %5d, %5d]  rot = [%5d, %5d, %5d]\r\n"
				:
				"acc = [%.5x, %.5x, %.5x]  rot = [%.5x, %.5x, %.5x]\r\n";

		/* Print accelerometer & gyroscope values */
		printf(format,
				/* data from motion event handler */
				(int16_t)acceleration.axis.x,
				(int16_t)acceleration.axis.y,
				(int16_t)acceleration.axis.z,
				
				/* data from sensor_get_rotation() (if GYRO_WAKE==false), or 
				 * from the gyro new data event handler */
				(int16_t)rotation.axis.x,
				(int16_t)rotation.axis.y,
				(int16_t)rotation.axis.z
		);
#endif

		/* Minimum active time is 100 msec */
		delay_ms(100);
	}

	return 0;
}
Example #3
0
/** \brief Proximity Sensor gesture recognition demo application entry
 *
 * This application uses a 3-channel proximity sensor to recognize simple
 * gestures.  When a proximity event occurs, the routine will wake up from
 * a low-power sleep mode and begin repeatedly sampling the proximity
 * sensor, until the proximity of the object is no longer detected.  Then
 * the beginning and ending sensor readings are compared, and the overall
 * direction of the object's movement is determined based on a lookup table.
 *
 * Once the direction is determined, it is indicate by turning on one of the
 * LEDs on the controller board and (optionally) by serial output to a
 * terminal device.  If the direction cannot be determined, all indicator
 * LEDs will be blinked rapidly.
 *
 * The application then resets by returning to a low-power sleep mode until
 * the next proximity event is detected.
 */
int main(void)
{
	uint8_t start_channels;    /* First channels detecting proximity */
	uint8_t current_channels;  /* Current channels detecting proximity */
	uint8_t end_channels;      /* Final channels detecting proximity */
	direction_t direction;     /* Calculated gesture direction */
	int i;

	/* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards)
	 * I/O pin mappings and any other configurable resources selected in
	 * the build configuration.
	 */
	sensor_platform_init();

	/* Turn on LEDs while initialization completes */
	LED_On(UP_LED);
	LED_On(DOWN_LED);
	LED_On(LEFT_LED);
	LED_On(RIGHT_LED);

	/* Initialize the MCU sleep manager API and specify a sleep mode. */
	sleepmgr_init();
	sleepmgr_lock_mode(SLEEP_MODE);

	/* Attach and initialize proximity sensor */
	sensor_attach(&prox_dev, SENSOR_TYPE_PROXIMITY, 0, 0);

	if (prox_dev.err) {
		puts("\r\nProximity sensor initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

#if (USE_PRINTF == true)
	uint32_t id;      /* Device ID */
	uint8_t version;  /* Device version */

	sensor_device_id(&prox_dev, &id, &version);
	printf("\r\nProximity sensor: %s    ID = 0x%02x ver. 0x%02x\r\n",
			prox_dev.drv->caps.name, (unsigned)id,
			(unsigned)version);
#endif

	/* Set sample rate */
	sensor_set_sample_rate(&prox_dev, PROX_SAMPLE_RATE);

	/* Select all proximity sensor channels */
	sensor_set_channel(&prox_dev, SENSOR_CHANNEL_ALL);
	
#if (SET_PROX_THRESHOLD == true)
	/* Manually  set proximity threshold values for each channel */
	/*  Otherwise, sensor will use values previously stored in nvram. */
	sensor_set_threshold(&prox_dev, SENSOR_THRESHOLD_NEAR_PROXIMITY,
			PROX_THRESHOLD);
#endif

#if (SET_PROX_CURRENT == true)
	/* Manually set LED current value for each channel */
	/*  Otherwise, sensor will use default values */
	sensor_set_current(&prox_dev, PROX_CURRENT_mA);
#endif

	/* Set up close proximity event to wakeup system */
	sensor_add_event(&prox_dev, SENSOR_EVENT_NEAR_PROXIMITY,
			prox_event_handler, 0, false);

	while (true) {
		/* Enable proximity event */
		sensor_enable_event(&prox_dev, SENSOR_EVENT_NEAR_PROXIMITY);

		/* Delay before putting device to sleep */
		delay_ms(10);

		/* Put device in low power sleep mode; wait for an interrupt to
		 * wake. */
		LED_Off(UP_LED);
		LED_Off(DOWN_LED);
		LED_Off(LEFT_LED);
		LED_Off(RIGHT_LED);

		/* Enter specified sleep mode */
		sleepmgr_enter_sleep();

		/* Only do sensor processing if proximity event woke device up */
		if (prox_event_occurred) {
			prox_event_occurred = false;

			/* Disable new proximity events during gesture sampling */
			sensor_disable_event(&prox_dev,
					SENSOR_EVENT_NEAR_PROXIMITY);

			/* Get starting value saved by event handler routine */
			start_channels = test_channels(&prox_data);
			end_channels = start_channels;

			/* Loop until no longer detecting proximity */
			do {
				/* Get new readings from sensor */
				sensor_get_proximity(&prox_dev, &prox_data);

				current_channels = test_channels(&prox_data);

				/* Update end value if proximity is still
				 * detected */
				if (current_channels != CHAN_NONE) {
					end_channels = current_channels;
				}
			} while (current_channels != CHAN_NONE);

			/* Get direction from lookup table based on start/end
			 * channel sets */
			direction = dir_tbl [start_channels] [end_channels];

#if USE_PRINTF
			/* Display direction */
			printf("Start: %s  End: %s  Direction: %s \r\n",
					channel_labels[start_channels],
					channel_labels[end_channels],
					direction_labels[direction]);
#endif

			/* Use LEDs to display direction */
			switch (direction) {
			case UP:
				LED_On(UP_LED);
				break;

			case DOWN:
				LED_On(DOWN_LED);
				break;

			case LEFT:
				LED_On(LEFT_LED);
				break;

			case RIGHT:
				LED_On(RIGHT_LED);
				break;

			default: 
				/* Unknown - blink all LEDs to indicate */
				for (i = 0; i < (ERR_BLINK_COUNT * 2); i++) {
					LED_Toggle(UP_LED);
					LED_Toggle(DOWN_LED);
					LED_Toggle(LEFT_LED);
					LED_Toggle(RIGHT_LED);

					delay_ms(50);
				}
				break;
			}
		}
		
		delay_ms(500);
	}
	
	return 0;
}
/** \brief Inertial sensor demo application entry
 *
 * After initializing the Xplained platform and sensor boards, this application
 * attaches descriptors to the accelerometer, gyroscope, and compass devices on
 * an Xplained inertial sensor board.  The sensor data, which is formatted and
 * printed via printf() after being read, can be viewed with a serial terminal
 * application on a machine attached to the USB interface on the Xplained
 * board.
 */
int main(void)
{
	sensor_t light_dev;  /* Light sensor device descriptor */
	sensor_t prox_dev;   /* Proximity sensor device descriptor */

	/* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards)
	 * I/O pin mappings and any other configurable resources selected in
	 * the build configuration.
	 */
	sensor_platform_init();

	/* Attach descriptors to the defined sensor devices. */
	sensor_attach(&light_dev, SENSOR_TYPE_LIGHT, 0, 0);
	sensor_attach(&prox_dev, SENSOR_TYPE_PROXIMITY, 0, 0);

	if (light_dev.err || prox_dev.err) {
		puts("\rSensor initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

	/* Set sample rates for light and proximity sensors */
	if (sensor_set_sample_rate(&light_dev, LIGHT_SAMPLE_RATE) != true) {
		printf("Error setting light sensor sample rate.\r\n");
	}

	if (sensor_set_sample_rate(&prox_dev, PROX_SAMPLE_RATE) != true) {
		printf("Error setting proximity sensor sample rate.\r\n");
	}

	/* Select all proximity sensor channels */
	sensor_set_channel(&prox_dev, SENSOR_CHANNEL_ALL);

#if (SET_PROX_THRESHOLD == true)
	/* Manually  set proximity threshold values for each channel */
	/* Otherwise, sensor will use values previously stored in nvram. */
	sensor_set_threshold(&prox_dev, SENSOR_THRESHOLD_NEAR_PROXIMITY,
			PROX_THRESHOLD);
#endif

#if (SET_PROX_CURRENT == true)
	/* Manually set LED current value for each channel */
	/* Otherwise, sensor will use default values. */
	sensor_set_current(&prox_dev, PROX_CURRENT_mA);
#endif

	/* Initialize sensor data descriptors for scaled vs. raw data. */
	static sensor_data_t light_data = {.scaled = SCALED_DATA};
	static sensor_data_t prox_data  = {.scaled = false};

	/* Wait for user to push button before continuing */
	LED_Off(ALL_LEDS);

	while (!SWITCH_PRESSED) {
		/* Just blink LED until button is pushed */
		LED_Toggle(PROMPT_LED);

		delay_ms(50);
	}

	LED_Off(PROMPT_LED);

	while (SWITCH_PRESSED) {
		/* wait until button is released */
	}

	/* Enable output streams for Atmel Data Visualizer (ADV) */
	visual_stream_init();

	while (true) {
		LED_Toggle(PROMPT_LED);

		/* Read sensor values */
		prox_data.scaled = false;
		sensor_get_light(&light_dev, &light_data);

		adv_data_send_1(LIGHT_STREAM_NUM, light_data.timestamp,
				light_data.light.value);

		delay_ms(15);
		sensor_get_proximity(&prox_dev, &prox_data);

		adv_data_send_3(PROX_STREAM_NUM, light_data.timestamp,
				prox_data.proximity.value[0],
				prox_data.proximity.value[1],
				prox_data.proximity.value[2]);

		delay_ms(15);
		prox_data.scaled = true;
		sensor_get_proximity(&prox_dev, &prox_data);

		adv_data_send_3(PROX_THRESHOLD_STREAM_NUM, light_data.timestamp,
				prox_data.proximity.value[0],
				prox_data.proximity.value[1],
				prox_data.proximity.value[2]);
	}

	return 0;
}
Example #5
0
/** \brief Inertial sensor demo application entry
 *
 * After initializing the Xplained platform and sensor boards, this application
 * attaches descriptors to the ambient light and proximity sensor devices on
 * an Xplained inertial sensor board.  The sensors are configured to wake up
 * the processor if given threshold values are surpassed.
 */
int main(void)
{
#if (USE_PRINTF == true)
	uint32_t id;      /* Device ID */
	uint8_t version;  /* Device version */
#endif

	/* Initialize the board (Xplained UC3 or XMEGA & Xplained Sensor boards)
	 * I/O pin mappings and any other configurable resources selected in
	 * the build configuration.
	 */
	sensor_platform_init();

	LED_On(ACTIVITY_LED);

#if (USE_PRINTF == true)
	printf("\r\n");
#endif

	/* Initialize the MCU sleep manager API and specify a sleep mode. */
	sleepmgr_init();
	sleepmgr_lock_mode(SLEEP_MODE);

#if (LIGHT_WAKE == true)
	/* Attach light sensor */
	sensor_attach(&light_dev, SENSOR_TYPE_LIGHT, 0, 0);

	if (light_dev.err) {
		puts("\r\nLight sensor initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

#  if (USE_PRINTF == true)
	sensor_device_id(&light_dev, &id, &version);
	printf("Light sensor: %s    ID = 0x%02x ver. 0x%02x\r\n",
			light_dev.drv->caps.name, (unsigned)id,
			(unsigned)version);
#  endif

	sensor_set_sample_rate(&light_dev, LIGHT_SAMPLE_RATE);

	sensor_set_threshold(&light_dev, SENSOR_THRESHOLD_HIGH_LIGHT,
			LIGHT_THRESH);

	/* Enable high light level event for wakeup */
	sensor_add_event(&light_dev, SENSOR_EVENT_HIGH_LIGHT,
			light_event, 0, true);
#endif

#if (PROX_WAKE == true)
	/* Attach proximity sensor */
	sensor_attach(&prox_dev, SENSOR_TYPE_PROXIMITY, 0, 0);

	if (prox_dev.err) {
		puts("\r\nProximity sensor initialization error.");

		while (true) {
			/* Error occurred, loop forever */
		}
	}

#  if (USE_PRINTF == true)
	sensor_device_id(&prox_dev, &id, &version);
	printf("Proximity sensor: %s    ID = 0x%02x ver. 0x%02x\r\n",
			prox_dev.drv->caps.name, (unsigned)id,
			(unsigned)version);
#  endif

	sensor_set_sample_rate(&prox_dev, PROX_SAMPLE_RATE);

	/* Select all proximity sensor channels */
	sensor_set_channel(&prox_dev, 0);

#  if (SET_PROX_THRESHOLD == true)
	/* Manually set proximity threshold values for each channel */
	/* Otherwise, sensor will use values previously stored in nvram. */
	sensor_set_threshold(&prox_dev, SENSOR_THRESHOLD_NEAR_PROXIMITY,
			PROX_THRESHOLD);
#  endif

#  if (SET_PROX_CURRENT == true)
	/* Manually set LED current value for each channel */
	/* Otherwise, sensor will use default values. */
	sensor_set_current(&prox_dev, PROX_CURRENT_mA);
#  endif

	/* Enable near proximity event for wakeup */
	sensor_add_event(&prox_dev, SENSOR_EVENT_NEAR_PROXIMITY,
			prox_event, 0, true);
#endif

	while (true) {
		LED_Off(ACTIVITY_LED);

		/* Put device in low power sleep mode; wait for an interrupt to
		 * wake. */
		sleepmgr_enter_sleep();

		/* Device has woken up */
		LED_On(ACTIVITY_LED);

#if (USE_PRINTF == true)
#  if (LIGHT_WAKE == true)
		if (light_event_occurred) {
			light_event_occurred = false;
			
			printf("light level = %5d\r\n",
					(int16_t)light_data.light.value);
		}
#  endif

#  if (PROX_WAKE == true)
		if (prox_event_occurred) {
			prox_event_occurred = false;

			printf("proximity: source channel=%d  time=%010ld  ",
					prox_channel, prox_data.timestamp);

			if (SCALED_DATA) {
				printf("Chan1:%s Chan2:%s Chan3:%s\r\n",
						prox_labels[prox_data.proximity.value[0]],
						prox_labels[prox_data.proximity.value[1]],
						prox_labels[prox_data.proximity.value[2]]);
			} else {
				printf("Chan1:%4d Chan2:%4d Chan3:%4d\r\n",
						(int16_t)prox_data.proximity.value[0],
						(int16_t)prox_data.proximity.value[1],
						(int16_t)prox_data.proximity.value[2]);
			}
		}
#  endif
#endif

		delay_ms(500);
	}

	return 0;
}
Example #6
0
/**
 * \brief Example application entry routine
 */
int main(void)
{
	/* The sensor_platform_init() function will initialize the system
	 * clock and sensor bus support in addition to configuring the
	 * XMEGA-A3BU and Sensor Xplained boards.
	 *
	 * Use gfx_mono_init() to initialize the monochrome graphical system
	 * API then write a splash screen after enabling the LCD display
	 * backlight and setting the contrast.
	 *
	 * The MCU is going to be put in a sleep mode, so initialize the
	 * sleep manager API with a call to the sleepmgr_init() routine.
	 */
	sensor_platform_init();
	gfx_mono_init();
	sleepmgr_init();

	gpio_set_pin_high(NHD_C12832A1Z_BACKLIGHT);
	st7565r_set_contrast(ST7565R_DISPLAY_CONTRAST_MIN);

	/* Attach an accelerometer on a Sensors Xplained board. */
	sensor_t accelerometer;
	sensor_attach(&accelerometer, SENSOR_TYPE_ACCELEROMETER, 0, 0);

	/* Enable the accelerometer low-g (free fall) event. */
	sensor_enable_event(&accelerometer, SENSOR_EVENT_LOW_G);

	/* Set the free fall threshold (low-g event), bandwidth and range. */
	sensor_set_threshold(&accelerometer, SENSOR_THRESHOLD_LOW_G,
			LOW_G_THRESHOLD);
	sensor_set_bandwidth(&accelerometer, BANDWIDTH);
	sensor_set_range(&accelerometer, RANGE);

	while (true) {
		/* Put the accelerometer into a low-power mode (if available). */
		sensor_set_state(&accelerometer, SENSOR_STATE_LOW_POWER);

		LED_Off(ACCEL_LED);

		clear_screen();

		/* Display the "armed" message and put the MCU in sleep mode. */
		gfx_mono_draw_string("ATMEL Drop Demo\r\nXMEGA Powered Down\r\n"
				"g Sensor Armed", 1, 5, &sysfont);

		sleepmgr_lock_mode(SLEEP_MODE);
		sleepmgr_enter_sleep();

		/* The following runs after the MCU has been woken by an
		 * external low-g interrupt from the accelerometer.
		 *
		 * Turn on the red LED while falling and put the accelerometer
		 * into a high-power mode (if available) to sample date points.
		 */
		LED_On(ACCEL_LED);

		sensor_set_state(&accelerometer, SENSOR_STATE_HIGHEST_POWER);

		static scalar_t acceleration_waveform[DATA_SAMPLE_COUNT];
		scalar_t acceleration_max = 0;

		for (int data_count = 0; data_count < DATA_SAMPLE_COUNT;
				++data_count) {
			acceleration_waveform[data_count] = 0;

			for (int i = 0; i < SAMPLE_AVG_COUNT; ++i) {
				/* Calculate the gravity vector magnitude. */
				vector3_t gvec;
				sensor_get_vector(&accelerometer, &gvec);

				scalar_t const acceleration_magnitude
					= vector3_magnitude(&gvec);

				/* Store the maximum g magnitude for this
				 * sub-group. */
				if (acceleration_magnitude >
						acceleration_waveform[data_count]) {
					acceleration_waveform[data_count]
						= acceleration_magnitude;
				}

				/* Store the maximum g magnitude for the whole
				 * data set. */
				if (acceleration_magnitude > acceleration_max) {
					acceleration_max = acceleration_magnitude;
				}
			}
		}

		clear_screen();

		/* Turn the max acceleration into a string and convert to g. */
		static char max_g_string[20];

		if (acceleration_max > LOW_G_SATURATION) {
			sprintf(max_g_string, "g Sensor Saturated");
		} else {
			sprintf(max_g_string, "Peak = %02.2f g",
					acceleration_max / 1000);
		}

		/* Print the max g on the monochrome display. */
		gfx_mono_draw_string("Drop Detected", 1, 5, &sysfont);
		gfx_mono_draw_string(max_g_string, 1, 13, &sysfont);
		gfx_mono_draw_string("Press SW1 for chart", 1, 21, &sysfont);

		do {
			LED_Toggle(ACCEL_LED);
			delay_ms(100);
		} while (!switch_pressed(SW1));

		/* Plot the collected data points to create the waveform chart. */
		clear_screen();
		screen_border();

		for (int data_count = 0; data_count < DATA_SAMPLE_COUNT; ++data_count) {
			gfx_mono_draw_filled_circle(data_count,
					32 -
					(acceleration_waveform[data_count] / 500), 1,
					GFX_PIXEL_SET, GFX_WHOLE);
		}

		do {
			LED_Toggle(PROMPT_LED);
			delay_ms(100);
		} while (!switch_pressed(SW1));

		LED_Off(PROMPT_LED);
	}
}