Exemplo n.º 1
0
int
BlinkM::play_script(const char *script_name)
{
	/* handle HTML colour encoding */
	if (isxdigit(script_name[0]) && (strlen(script_name) == 6)) {
		char code[3];
		uint8_t r, g, b;

		code[2] = '\0';

		code[0] = script_name[1];
		code[1] = script_name[2];
		r = strtol(code, 0, 16);
		code[0] = script_name[3];
		code[1] = script_name[4];
		g = strtol(code, 0, 16);
		code[0] = script_name[5];
		code[1] = script_name[6];
		b = strtol(code, 0, 16);

		stop_script();
		return set_rgb(r, g, b);
	}

	for (unsigned i = 0; script_names[i] != nullptr; i++)
		if (!strcasecmp(script_name, script_names[i]))
			return play_script(i);

	return -1;
}
Exemplo n.º 2
0
int
BlinkM::setMode(int mode)
{
	if(mode == 1) {
		if(systemstate_run == false) {
			stop_script();
			set_rgb(0,0,0);
			systemstate_run = true;
			work_queue(LPWORK, &_work, (worker_t)&BlinkM::led_trampoline, this, 1);
		}
	} else {
		systemstate_run = false;
	}

	return OK;
}
Exemplo n.º 3
0
int
BlinkM::init()
{
	int ret;
	ret = I2C::init();

	if (ret != OK) {
		warnx("I2C init failed");
		return ret;
	}

	stop_script();
	set_rgb(0,0,0);

	return OK;
}
Exemplo n.º 4
0
void
BlinkM::led()
{

	static int vehicle_status_sub_fd;
	static int vehicle_gps_position_sub_fd;

	static int num_of_cells = 0;
	static int detected_cells_runcount = 0;

	static int t_led_color[8] = { 0, 0, 0, 0, 0, 0, 0, 0};
	static int t_led_blink = 0;
	static int led_thread_runcount=0;
	static int led_interval = 1000;

	static int no_data_vehicle_status = 0;
	static int no_data_vehicle_gps_position = 0;

	static bool topic_initialized = false;
	static bool detected_cells_blinked = false;
	static bool led_thread_ready = true;

	int num_of_used_sats = 0;

	if(!topic_initialized) {
		vehicle_status_sub_fd = orb_subscribe(ORB_ID(vehicle_status));
		orb_set_interval(vehicle_status_sub_fd, 1000);

		vehicle_gps_position_sub_fd = orb_subscribe(ORB_ID(vehicle_gps_position));
		orb_set_interval(vehicle_gps_position_sub_fd, 1000);

		topic_initialized = true;
	}

	if(led_thread_ready == true) {
		if(!detected_cells_blinked) {
			if(num_of_cells > 0) {
				t_led_color[0] = LED_PURPLE;
			}
			if(num_of_cells > 1) {
				t_led_color[1] = LED_PURPLE;
			}
			if(num_of_cells > 2) {
				t_led_color[2] = LED_PURPLE;
			}
			if(num_of_cells > 3) {
				t_led_color[3] = LED_PURPLE;
			}
			if(num_of_cells > 4) {
				t_led_color[4] = LED_PURPLE;
			}
			t_led_color[5] = LED_OFF;
			t_led_color[6] = LED_OFF;
			t_led_color[7] = LED_OFF;
			t_led_blink = LED_BLINK;
		} else {
			t_led_color[0] = led_color_1;
			t_led_color[1] = led_color_2;
			t_led_color[2] = led_color_3;
			t_led_color[3] = led_color_4;
			t_led_color[4] = led_color_5;
			t_led_color[5] = led_color_6;
			t_led_color[6] = led_color_7;
			t_led_color[7] = led_color_8;
			t_led_blink = led_blink;
		}
		led_thread_ready = false;
	}

	if (led_thread_runcount & 1) {
		if (t_led_blink)
			setLEDColor(LED_OFF);
		led_interval = LED_OFFTIME;
	} else {
		setLEDColor(t_led_color[(led_thread_runcount / 2) % 8]);
		//led_interval = (led_thread_runcount & 1) : LED_ONTIME;
		led_interval = LED_ONTIME;
	}

	if (led_thread_runcount == 15) {
		/* obtained data for the first file descriptor */
		struct vehicle_status_s vehicle_status_raw;
		struct vehicle_gps_position_s vehicle_gps_position_raw;

		memset(&vehicle_status_raw, 0, sizeof(vehicle_status_raw));
		memset(&vehicle_gps_position_raw, 0, sizeof(vehicle_gps_position_raw));

		bool new_data_vehicle_status;
		bool new_data_vehicle_gps_position;

		orb_check(vehicle_status_sub_fd, &new_data_vehicle_status);

		if (new_data_vehicle_status) {
			orb_copy(ORB_ID(vehicle_status), vehicle_status_sub_fd, &vehicle_status_raw);
			no_data_vehicle_status = 0;
		} else {
			no_data_vehicle_status++;
			if(no_data_vehicle_status >= 3)
				no_data_vehicle_status = 3;
		}

		orb_check(vehicle_gps_position_sub_fd, &new_data_vehicle_gps_position);

		if (new_data_vehicle_gps_position) {
			orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub_fd, &vehicle_gps_position_raw);
			no_data_vehicle_gps_position = 0;
		} else {
			no_data_vehicle_gps_position++;
			if(no_data_vehicle_gps_position >= 3)
				no_data_vehicle_gps_position = 3;
		}



		/* get number of used satellites in navigation */
		num_of_used_sats = 0;
		//for(int satloop=0; satloop<20; satloop++) {
		for(int satloop=0; satloop<sizeof(vehicle_gps_position_raw.satellite_used); satloop++) {
			if(vehicle_gps_position_raw.satellite_used[satloop] == 1) {
				num_of_used_sats++;
			}
		}

		if(new_data_vehicle_status || no_data_vehicle_status < 3){
			if(num_of_cells == 0) {
				/* looking for lipo cells that are connected */
				printf("<blinkm> checking cells\n");
				for(num_of_cells = 2; num_of_cells < 7; num_of_cells++) {
					if(vehicle_status_raw.voltage_battery < num_of_cells * MAX_CELL_VOLTAGE) break;
				}
				printf("<blinkm> cells found:%u\n", num_of_cells);

			} else {
				if(vehicle_status_raw.battery_warning == VEHICLE_BATTERY_WARNING_WARNING) {
					/* LED Pattern for battery low warning */
					led_color_1 = LED_YELLOW;
					led_color_2 = LED_YELLOW;
					led_color_3 = LED_YELLOW;
					led_color_4 = LED_YELLOW;
					led_color_5 = LED_YELLOW;
					led_color_6 = LED_YELLOW;
					led_color_7 = LED_YELLOW;
					led_color_8 = LED_YELLOW;
					led_blink = LED_BLINK;

				} else if(vehicle_status_raw.battery_warning == VEHICLE_BATTERY_WARNING_ALERT) {
					/* LED Pattern for battery critical alerting */
					led_color_1 = LED_RED;
					led_color_2 = LED_RED;
					led_color_3 = LED_RED;
					led_color_4 = LED_RED;
					led_color_5 = LED_RED;
					led_color_6 = LED_RED;
					led_color_7 = LED_RED;
					led_color_8 = LED_RED;
					led_blink = LED_BLINK;

				} else {
					/* no battery warnings here */

					if(vehicle_status_raw.flag_system_armed == false) {
						/* system not armed */
						led_color_1 = LED_RED;
						led_color_2 = LED_RED;
						led_color_3 = LED_RED;
						led_color_4 = LED_RED;
						led_color_5 = LED_RED;
						led_color_6 = LED_RED;
						led_color_7 = LED_RED;
						led_color_8 = LED_RED;
						led_blink = LED_NOBLINK;

					} else {
						/* armed system - initial led pattern */
						led_color_1 = LED_RED;
						led_color_2 = LED_RED;
						led_color_3 = LED_RED;
						led_color_4 = LED_OFF;
						led_color_5 = LED_OFF;
						led_color_6 = LED_OFF;
						led_color_7 = LED_OFF;
						led_color_8 = LED_OFF;
						led_blink = LED_BLINK;

						/* handle 4th led - flightmode indicator */
						switch((int)vehicle_status_raw.flight_mode) {
							case VEHICLE_FLIGHT_MODE_MANUAL:
								led_color_4 = LED_AMBER;
								break;

							case VEHICLE_FLIGHT_MODE_STAB:
								led_color_4 = LED_YELLOW;
								break;

							case VEHICLE_FLIGHT_MODE_HOLD:
								led_color_4 = LED_BLUE;
								break;

							case VEHICLE_FLIGHT_MODE_AUTO:
								led_color_4 = LED_GREEN;
								break;
						}

						if(new_data_vehicle_gps_position || no_data_vehicle_gps_position < 3) {
							/* handling used sat´s */
							if(num_of_used_sats >= 7) {
								led_color_1 = LED_OFF;
								led_color_2 = LED_OFF;
								led_color_3 = LED_OFF;
							} else if(num_of_used_sats == 6) {
								led_color_2 = LED_OFF;
								led_color_3 = LED_OFF;
							} else if(num_of_used_sats == 5) {
								led_color_3 = LED_OFF;
							}

						} else {
							/* no vehicle_gps_position data */
							led_color_1 = LED_WHITE;
							led_color_2 = LED_WHITE;
							led_color_3 = LED_WHITE;

						}

					}
				}
			}
		} else {
			/* LED Pattern for general Error - no vehicle_status can retrieved */
			led_color_1 = LED_WHITE;
			led_color_2 = LED_WHITE;
			led_color_3 = LED_WHITE;
			led_color_4 = LED_WHITE;
			led_color_5 = LED_WHITE;
			led_color_6 = LED_WHITE;
			led_color_7 = LED_WHITE;
			led_color_8 = LED_WHITE;
			led_blink = LED_BLINK;

		}

		/*
		printf( "<blinkm> Volt:%8.4f\tArmed:%4u\tMode:%4u\tCells:%4u\tNDVS:%4u\tNDSAT:%4u\tSats:%4u\tFix:%4u\tVisible:%4u\n",
		vehicle_status_raw.voltage_battery,
		vehicle_status_raw.flag_system_armed,
		vehicle_status_raw.flight_mode,
		num_of_cells,
		no_data_vehicle_status,
		no_data_vehicle_gps_position,
		num_of_used_sats,
		vehicle_gps_position_raw.fix_type,
		vehicle_gps_position_raw.satellites_visible);
		*/

		led_thread_runcount=0;
		led_thread_ready = true;
		led_interval = LED_OFFTIME;

		if(detected_cells_runcount < 4){
			detected_cells_runcount++;
		} else {
			detected_cells_blinked = true;
		}

	} else {
		led_thread_runcount++;
	}

	if(systemstate_run == true) {
		/* re-queue ourselves to run again later */
		work_queue(LPWORK, &_work, (worker_t)&BlinkM::led_trampoline, this, led_interval);
	} else {
		stop_script();
		set_rgb(0,0,0);
	}
}
Exemplo n.º 5
0
void t9()
{
   int s, oc, c, e;
   uint32_t p[10];

   printf("Script store/run/status/stop/delete tests.\n");

   gpio_write(GPIO, 0); /* need known state */

   /*
   100 loops per second
   p0 number of loops
   p1 GPIO
   */
   char *script="\
   lda p0\
   sta v0\
   tag 0\
   w p1 1\
   mils 5\
   w p1 0\
   mils 5\
   dcr v0\
   lda v0\
   sta p9\
   jp 0";

   callback(GPIO, RISING_EDGE, t9cbf);

   s = store_script(script);
   oc = t9_count;
   p[0] = 99;
   p[1] = GPIO;
   run_script(s, 2, p);
   time_sleep(2);
   c = t9_count - oc;
   CHECK(9, 1, c, 100, 0, "store/run script");

   oc = t9_count;
   p[0] = 200;
   p[1] = GPIO;
   run_script(s, 2, p);
   while (1)
   {
      e = script_status(s, p);
      if (e != PI_SCRIPT_RUNNING) break;
      time_sleep(0.5);
   }
   c = t9_count - oc;
   time_sleep(0.1);
   CHECK(9, 2, c, 201, 0, "run script/script status");

   oc = t9_count;
   p[0] = 2000;
   p[1] = GPIO;
   run_script(s, 2, p);
   while (1)
   {
      e = script_status(s, p);
      if (e != PI_SCRIPT_RUNNING) break;
      if (p[9] < 1900) stop_script(s);
      time_sleep(0.1);
   }
   c = t9_count - oc;
   time_sleep(0.1);
   CHECK(9, 3, c, 110, 10, "run/stop script/script status");

   e = delete_script(s);
   CHECK(9, 4, e, 0, 0, "delete script");
}
Exemplo n.º 6
0
void
BlinkM::led()
{

	if (!topic_initialized) {
		vehicle_status_sub_fd = orb_subscribe(ORB_ID(vehicle_status));
		orb_set_interval(vehicle_status_sub_fd, 250);

		vehicle_control_mode_sub_fd = orb_subscribe(ORB_ID(vehicle_control_mode));
		orb_set_interval(vehicle_control_mode_sub_fd, 250);

		actuator_armed_sub_fd = orb_subscribe(ORB_ID(actuator_armed));
		orb_set_interval(actuator_armed_sub_fd, 250);

		vehicle_gps_position_sub_fd = orb_subscribe(ORB_ID(vehicle_gps_position));
		orb_set_interval(vehicle_gps_position_sub_fd, 250);

		/* Subscribe to safety topic */
		safety_sub_fd = orb_subscribe(ORB_ID(safety));
		orb_set_interval(safety_sub_fd, 250);

		topic_initialized = true;
	}

	if (led_thread_ready == true) {
		if (!detected_cells_blinked) {
			if (num_of_cells > 0) {
				t_led_color[0] = LED_PURPLE;
			}

			if (num_of_cells > 1) {
				t_led_color[1] = LED_PURPLE;
			}

			if (num_of_cells > 2) {
				t_led_color[2] = LED_PURPLE;
			}

			if (num_of_cells > 3) {
				t_led_color[3] = LED_PURPLE;
			}

			if (num_of_cells > 4) {
				t_led_color[4] = LED_PURPLE;
			}

			if (num_of_cells > 5) {
				t_led_color[5] = LED_PURPLE;
			}

			t_led_color[6] = LED_OFF;
			t_led_color[7] = LED_OFF;
			t_led_blink = LED_BLINK;

		} else {
			t_led_color[0] = led_color_1;
			t_led_color[1] = led_color_2;
			t_led_color[2] = led_color_3;
			t_led_color[3] = led_color_4;
			t_led_color[4] = led_color_5;
			t_led_color[5] = led_color_6;
			t_led_color[6] = led_color_7;
			t_led_color[7] = led_color_8;
			t_led_blink = led_blink;
		}

		led_thread_ready = false;
	}

	if (led_thread_runcount & 1) {
		if (t_led_blink) {
			setLEDColor(LED_OFF);
		}

		led_interval = LED_OFFTIME;

	} else {
		setLEDColor(t_led_color[(led_thread_runcount / 2) % 8]);
		//led_interval = (led_thread_runcount & 1) : LED_ONTIME;
		led_interval = LED_ONTIME;
	}

	if (led_thread_runcount == 15) {
		/* obtained data for the first file descriptor */
		struct vehicle_status_s vehicle_status_raw;
		struct vehicle_control_mode_s vehicle_control_mode;
		struct actuator_armed_s actuator_armed;
		struct vehicle_gps_position_s vehicle_gps_position_raw;
		struct safety_s safety;

		memset(&vehicle_status_raw, 0, sizeof(vehicle_status_raw));
		memset(&vehicle_gps_position_raw, 0, sizeof(vehicle_gps_position_raw));
		memset(&safety, 0, sizeof(safety));

		bool new_data_vehicle_status;
		bool new_data_vehicle_control_mode;
		bool new_data_actuator_armed;
		bool new_data_vehicle_gps_position;
		bool new_data_safety;

		orb_check(vehicle_status_sub_fd, &new_data_vehicle_status);

		int no_data_vehicle_status = 0;
		int no_data_vehicle_control_mode = 0;
		int no_data_actuator_armed = 0;
		int no_data_vehicle_gps_position = 0;

		if (new_data_vehicle_status) {
			orb_copy(ORB_ID(vehicle_status), vehicle_status_sub_fd, &vehicle_status_raw);
			no_data_vehicle_status = 0;

		} else {
			no_data_vehicle_status++;

			if (no_data_vehicle_status >= 3) {
				no_data_vehicle_status = 3;
			}
		}

		orb_check(vehicle_control_mode_sub_fd, &new_data_vehicle_control_mode);

		if (new_data_vehicle_control_mode) {
			orb_copy(ORB_ID(vehicle_control_mode), vehicle_control_mode_sub_fd, &vehicle_control_mode);
			no_data_vehicle_control_mode = 0;

		} else {
			no_data_vehicle_control_mode++;

			if (no_data_vehicle_control_mode >= 3) {
				no_data_vehicle_control_mode = 3;
			}
		}

		orb_check(actuator_armed_sub_fd, &new_data_actuator_armed);

		if (new_data_actuator_armed) {
			orb_copy(ORB_ID(actuator_armed), actuator_armed_sub_fd, &actuator_armed);
			no_data_actuator_armed = 0;

		} else {
			no_data_actuator_armed++;

			if (no_data_actuator_armed >= 3) {
				no_data_actuator_armed = 3;
			}
		}

		orb_check(vehicle_gps_position_sub_fd, &new_data_vehicle_gps_position);

		if (new_data_vehicle_gps_position) {
			orb_copy(ORB_ID(vehicle_gps_position), vehicle_gps_position_sub_fd, &vehicle_gps_position_raw);
			no_data_vehicle_gps_position = 0;

		} else {
			no_data_vehicle_gps_position++;

			if (no_data_vehicle_gps_position >= 3) {
				no_data_vehicle_gps_position = 3;
			}
		}

		/* update safety topic */
		orb_check(safety_sub_fd, &new_data_safety);

		if (new_data_safety) {
			orb_copy(ORB_ID(safety), safety_sub_fd, &safety);
		}

		/* get number of used satellites in navigation */
		num_of_used_sats = vehicle_gps_position_raw.satellites_used;

		if (new_data_vehicle_status || no_data_vehicle_status < 3) {
			if (num_of_cells == 0) {
				/* looking for lipo cells that are connected */
				printf("<blinkm> checking cells\n");

				for (num_of_cells = 2; num_of_cells < 7; num_of_cells++) {
					if (vehicle_status_raw.battery_voltage < num_of_cells * MAX_CELL_VOLTAGE) { break; }
				}

				printf("<blinkm> cells found:%d\n", num_of_cells);

			} else {
				if (vehicle_status_raw.battery_warning == vehicle_status_s::VEHICLE_BATTERY_WARNING_CRITICAL) {
					/* LED Pattern for battery critical alerting */
					led_color_1 = LED_RED;
					led_color_2 = LED_RED;
					led_color_3 = LED_RED;
					led_color_4 = LED_RED;
					led_color_5 = LED_RED;
					led_color_6 = LED_RED;
					led_color_7 = LED_RED;
					led_color_8 = LED_RED;
					led_blink = LED_BLINK;

				} else if (vehicle_status_raw.rc_signal_lost) {
					/* LED Pattern for FAILSAFE */
					led_color_1 = LED_BLUE;
					led_color_2 = LED_BLUE;
					led_color_3 = LED_BLUE;
					led_color_4 = LED_BLUE;
					led_color_5 = LED_BLUE;
					led_color_6 = LED_BLUE;
					led_color_7 = LED_BLUE;
					led_color_8 = LED_BLUE;
					led_blink = LED_BLINK;

				} else if (vehicle_status_raw.battery_warning == vehicle_status_s::VEHICLE_BATTERY_WARNING_LOW) {
					/* LED Pattern for battery low warning */
					led_color_1 = LED_YELLOW;
					led_color_2 = LED_YELLOW;
					led_color_3 = LED_YELLOW;
					led_color_4 = LED_YELLOW;
					led_color_5 = LED_YELLOW;
					led_color_6 = LED_YELLOW;
					led_color_7 = LED_YELLOW;
					led_color_8 = LED_YELLOW;
					led_blink = LED_BLINK;

				} else {
					/* no battery warnings here */

					if (actuator_armed.armed == false) {
						/* system not armed */
						if (safety.safety_off) {
							led_color_1 = LED_ORANGE;
							led_color_2 = LED_ORANGE;
							led_color_3 = LED_ORANGE;
							led_color_4 = LED_ORANGE;
							led_color_5 = LED_ORANGE;
							led_color_6 = LED_ORANGE;
							led_color_7 = LED_ORANGE;
							led_color_8 = LED_ORANGE;
							led_blink = LED_BLINK;

						} else {
							led_color_1 = LED_CYAN;
							led_color_2 = LED_CYAN;
							led_color_3 = LED_CYAN;
							led_color_4 = LED_CYAN;
							led_color_5 = LED_CYAN;
							led_color_6 = LED_CYAN;
							led_color_7 = LED_CYAN;
							led_color_8 = LED_CYAN;
							led_blink = LED_NOBLINK;
						}

					} else {
						/* armed system - initial led pattern */
						led_color_1 = LED_RED;
						led_color_2 = LED_RED;
						led_color_3 = LED_RED;
						led_color_4 = LED_OFF;
						led_color_5 = LED_OFF;
						led_color_6 = LED_OFF;
						led_color_7 = LED_OFF;
						led_color_8 = LED_OFF;
						led_blink = LED_BLINK;

						if (new_data_vehicle_control_mode || no_data_vehicle_control_mode < 3) {
							/* indicate main control state */
							if (vehicle_status_raw.main_state == vehicle_status_s::MAIN_STATE_POSCTL) {
								led_color_4 = LED_GREEN;
							}

							/* TODO: add other Auto modes */
							else if (vehicle_status_raw.main_state == vehicle_status_s::MAIN_STATE_AUTO_MISSION) {
								led_color_4 = LED_BLUE;

							} else if (vehicle_status_raw.main_state == vehicle_status_s::MAIN_STATE_ALTCTL) {
								led_color_4 = LED_YELLOW;

							} else if (vehicle_status_raw.main_state == vehicle_status_s::MAIN_STATE_MANUAL) {
								led_color_4 = LED_WHITE;

							} else {
								led_color_4 = LED_OFF;
							}

							led_color_5 = led_color_4;
						}

						if (new_data_vehicle_gps_position || no_data_vehicle_gps_position < 3) {
							/* handling used satus */
							if (num_of_used_sats >= 7) {
								led_color_1 = LED_OFF;
								led_color_2 = LED_OFF;
								led_color_3 = LED_OFF;

							} else if (num_of_used_sats == 6) {
								led_color_2 = LED_OFF;
								led_color_3 = LED_OFF;

							} else if (num_of_used_sats == 5) {
								led_color_3 = LED_OFF;
							}

						} else {
							/* no vehicle_gps_position data */
							led_color_1 = LED_WHITE;
							led_color_2 = LED_WHITE;
							led_color_3 = LED_WHITE;

						}

					}
				}
			}

		} else {
			/* LED Pattern for general Error - no vehicle_status can retrieved */
			led_color_1 = LED_WHITE;
			led_color_2 = LED_WHITE;
			led_color_3 = LED_WHITE;
			led_color_4 = LED_WHITE;
			led_color_5 = LED_WHITE;
			led_color_6 = LED_WHITE;
			led_color_7 = LED_WHITE;
			led_color_8 = LED_WHITE;
			led_blink = LED_BLINK;

		}

		/*
		printf( "<blinkm> Volt:%8.4f\tArmed:%4u\tMode:%4u\tCells:%4u\tNDVS:%4u\tNDSAT:%4u\tSats:%4u\tFix:%4u\tVisible:%4u\n",
		vehicle_status_raw.voltage_battery,
		vehicle_status_raw.flag_system_armed,
		vehicle_status_raw.flight_mode,
		num_of_cells,
		no_data_vehicle_status,
		no_data_vehicle_gps_position,
		num_of_used_sats,
		vehicle_gps_position_raw.fix_type,
		vehicle_gps_position_raw.satellites_visible);
		*/

		led_thread_runcount = 0;
		led_thread_ready = true;
		led_interval = LED_OFFTIME;

		if (detected_cells_runcount < 4) {
			detected_cells_runcount++;

		} else {
			detected_cells_blinked = true;
		}

	} else {
		led_thread_runcount++;
	}

	if (systemstate_run == true) {
		/* re-queue ourselves to run again later */
		work_queue(LPWORK, &_work, (worker_t)&BlinkM::led_trampoline, this, led_interval);

	} else {
		stop_script();
		set_rgb(0, 0, 0);
	}
}
Exemplo n.º 7
0
void t9(int pi)
{
   int s, oc, c, e, id;
   uint32_t p[10];

   printf("Script store/run/status/stop/delete tests.\n");

   gpio_write(pi, GPIO, 0); /* need known state */

   /*
   100 loops per second
   p0 number of loops
   p1 GPIO
   */
   char *script="\
   ld p9 p0\
   tag 0\
   w p1 1\
   mils 5\
   w p1 0\
   mils 5\
   dcr p9\
   jp 0";

   id = callback(pi, GPIO, RISING_EDGE, t9cbf);

   s = store_script(pi, script);

   /* Wait for script to finish initing. */
   while (1)
   {
      time_sleep(0.1);
      e = script_status(pi, s, p);
      if (e != PI_SCRIPT_INITING) break;
   }

   oc = t9_count;
   p[0] = 99;
   p[1] = GPIO;
   run_script(pi, s, 2, p);
   time_sleep(2);
   c = t9_count - oc;
   CHECK(9, 1, c, 100, 0, "store/run script");

   oc = t9_count;
   p[0] = 200;
   p[1] = GPIO;
   run_script(pi, s, 2, p);
   while (1)
   {
      time_sleep(0.1);
      e = script_status(pi, s, p);
      if (e != PI_SCRIPT_RUNNING) break;
   }
   c = t9_count - oc;
   time_sleep(0.1);
   CHECK(9, 2, c, 201, 0, "run script/script status");

   oc = t9_count;
   p[0] = 2000;
   p[1] = GPIO;
   run_script(pi, s, 2, p);
   while (1)
   {
      time_sleep(0.1);
      e = script_status(pi, s, p);
      if (e != PI_SCRIPT_RUNNING) break;
      if (p[9] < 1600) stop_script(pi, s);
   }
   c = t9_count - oc;
   time_sleep(0.1);
   CHECK(9, 3, c, 410, 10, "run/stop script/script status");

   e = delete_script(pi, s);
   CHECK(9, 4, e, 0, 0, "delete script");

   callback_cancel(id);
}