mirror of
https://github.com/blw1138/MercurySim.git
synced 2025-12-17 08:38:12 +00:00
Initial commit
This commit is contained in:
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
/Source Audio/
|
||||||
|
/venv/
|
||||||
|
/src/video/
|
||||||
464
MercuryController/MercuryController.ino
Normal file
464
MercuryController/MercuryController.ino
Normal file
@@ -0,0 +1,464 @@
|
|||||||
|
// Mercury Control Panel Controller
|
||||||
|
// Brett Williams
|
||||||
|
// March 2017
|
||||||
|
|
||||||
|
#include <SerialCommand.h>
|
||||||
|
#include <Servo.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Adafruit_PWMServoDriver.h>
|
||||||
|
|
||||||
|
//Servo globe_servo;
|
||||||
|
|
||||||
|
//Define Pins
|
||||||
|
const int globeServo = 0;
|
||||||
|
const int globeMotor = 3;
|
||||||
|
const int ploadPin = 13;
|
||||||
|
const int switchLatchPin = 11;
|
||||||
|
const int ledLatchPin = 9;
|
||||||
|
const int clockPin = 12;
|
||||||
|
const int dataPin = 10;
|
||||||
|
|
||||||
|
//Shift Register Buffer
|
||||||
|
byte leds[3];
|
||||||
|
byte switches[3];
|
||||||
|
|
||||||
|
//Servo Data
|
||||||
|
Adafruit_PWMServoDriver servos = Adafruit_PWMServoDriver(0x65);
|
||||||
|
#define SERVOMIN 202 // this is the 'minimum' pulse length count (out of 4096)
|
||||||
|
#define SERVOMAX 700 // this is the 'maximum' pulse length count (out of 4096)
|
||||||
|
int servo_pwm[16];
|
||||||
|
bool move_globe;
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
bool ledState;
|
||||||
|
long onTime;
|
||||||
|
unsigned long startMillis;
|
||||||
|
} LED;
|
||||||
|
|
||||||
|
#define LED_COUNT 24
|
||||||
|
#define DEFAULT_LED_TIME 8000
|
||||||
|
|
||||||
|
LED led_list[LED_COUNT];
|
||||||
|
|
||||||
|
SerialCommand SCmd;
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
pinMode(ploadPin, OUTPUT);
|
||||||
|
pinMode(switchLatchPin, OUTPUT);
|
||||||
|
pinMode(ledLatchPin, OUTPUT);
|
||||||
|
pinMode(dataPin, OUTPUT);
|
||||||
|
pinMode(clockPin, OUTPUT);
|
||||||
|
|
||||||
|
digitalWrite(clockPin, LOW);
|
||||||
|
digitalWrite(ploadPin, HIGH);
|
||||||
|
all_leds_off();
|
||||||
|
|
||||||
|
servos.begin();
|
||||||
|
servos.setPWMFreq(60); // Analog servos run at ~60 Hz updates
|
||||||
|
|
||||||
|
serial_setup();
|
||||||
|
|
||||||
|
move_globe = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
// byte switchBuffer[3];
|
||||||
|
// readSwitches(switchBuffer);
|
||||||
|
update_leds();
|
||||||
|
advance_globe();
|
||||||
|
SCmd.readSerial();
|
||||||
|
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== SERIAL METHODS ==== */
|
||||||
|
|
||||||
|
void serial_setup()
|
||||||
|
{
|
||||||
|
Serial.begin(9600);
|
||||||
|
SCmd.addDefaultHandler(unrecognized);
|
||||||
|
//LED Commands
|
||||||
|
SCmd.addCommand("led", process_led_command);
|
||||||
|
SCmd.addCommand("led_red", led_red);
|
||||||
|
SCmd.addCommand("led_all_on", cycle_all_leds);
|
||||||
|
SCmd.addCommand("led_all_off", all_leds_off);
|
||||||
|
SCmd.addCommand("led_cycle", cycle_all_leds);
|
||||||
|
//Servo Commands
|
||||||
|
SCmd.addCommand("servo_zero", zero_all_servos);
|
||||||
|
SCmd.addCommand("servo_min", zero_all_servos);
|
||||||
|
SCmd.addCommand("servo_center", center_all_servos);
|
||||||
|
SCmd.addCommand("servo_max", max_all_servos);
|
||||||
|
SCmd.addCommand("servo", process_servo_command);
|
||||||
|
//Globe Commands
|
||||||
|
SCmd.addCommand("globe", globe);
|
||||||
|
Serial.println(F("Mercury Control Ready"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void unrecognized()
|
||||||
|
{
|
||||||
|
Serial.println(F("Unrecognized Command"));
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_led_command()
|
||||||
|
{
|
||||||
|
int ledPin;
|
||||||
|
String ledStatusText;
|
||||||
|
bool ledStatus;
|
||||||
|
char *arg;
|
||||||
|
|
||||||
|
arg = SCmd.next();
|
||||||
|
if (arg != NULL)
|
||||||
|
{
|
||||||
|
ledPin = atoi(arg); // Converts a char string to an integer
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println("Error: No pin number");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = SCmd.next();
|
||||||
|
if (arg != NULL)
|
||||||
|
{
|
||||||
|
ledStatusText = String(arg);
|
||||||
|
ledStatus = ledStatusText.equals("on");
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println("Error: No pin status");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print(F("Turning LED #"));
|
||||||
|
Serial.print(ledPin);
|
||||||
|
if (ledStatus){
|
||||||
|
Serial.println(" on");
|
||||||
|
}else{
|
||||||
|
Serial.println(" off");
|
||||||
|
}
|
||||||
|
|
||||||
|
set_led_state(ledPin, ledStatus, DEFAULT_LED_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void process_servo_command()
|
||||||
|
{
|
||||||
|
int servo_num;
|
||||||
|
int percent;
|
||||||
|
int duration = 0;
|
||||||
|
char *arg;
|
||||||
|
|
||||||
|
arg = SCmd.next();
|
||||||
|
if (arg != NULL)
|
||||||
|
{
|
||||||
|
servo_num=atoi(arg); // Converts a char string to an integer
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println(F("Error: No servo number"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (servo_num == globeServo){
|
||||||
|
Serial.println(F("Error: Cannot move globe"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = SCmd.next();
|
||||||
|
if (arg != NULL)
|
||||||
|
{
|
||||||
|
percent=atol(arg);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
Serial.println(F("Error: No servo move percent"));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
arg = SCmd.next();
|
||||||
|
if (arg != NULL)
|
||||||
|
{
|
||||||
|
duration=atol(arg);
|
||||||
|
}
|
||||||
|
|
||||||
|
Serial.print(F("Moving servo #"));
|
||||||
|
Serial.print(servo_num);
|
||||||
|
Serial.print(" to ");
|
||||||
|
Serial.print(percent);
|
||||||
|
Serial.println("%");
|
||||||
|
|
||||||
|
if (duration > 0){
|
||||||
|
move_servo_to_percent_timed(servo_num, percent, duration);
|
||||||
|
}
|
||||||
|
else{
|
||||||
|
move_servo_to_percent(servo_num, percent);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== SWITCH METHODS ==== */
|
||||||
|
|
||||||
|
void readSwitches(byte switchBuffer[])
|
||||||
|
{
|
||||||
|
pinMode(dataPin, INPUT);
|
||||||
|
|
||||||
|
//Collect Data
|
||||||
|
digitalWrite(switchLatchPin, HIGH);
|
||||||
|
digitalWrite(ploadPin, LOW);
|
||||||
|
delayMicroseconds(20);
|
||||||
|
digitalWrite(ploadPin, HIGH);
|
||||||
|
digitalWrite(switchLatchPin, LOW);
|
||||||
|
|
||||||
|
//Shift data in
|
||||||
|
switchBuffer[0] = shiftIn(dataPin, clockPin, MSBFIRST);
|
||||||
|
switchBuffer[1] = shiftIn(dataPin, clockPin, MSBFIRST);
|
||||||
|
switchBuffer[2] = shiftIn(dataPin, clockPin, MSBFIRST);
|
||||||
|
|
||||||
|
//Look for any changes
|
||||||
|
for (int x = 0; x < 3; x++) {
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
if (bitRead(switchBuffer[x], i) != bitRead(switches[x], i)) {
|
||||||
|
int pin_number = (x * 8) + i;
|
||||||
|
//set_pin_status(pin_number, 1);
|
||||||
|
Serial.print("Pin - ");
|
||||||
|
Serial.print(pin_number);
|
||||||
|
if (bitRead(switchBuffer[x], i) > 0)
|
||||||
|
Serial.print("HIGH");
|
||||||
|
else
|
||||||
|
Serial.print("LOW");
|
||||||
|
Serial.print("\r\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
switches[x] = switchBuffer[x];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== LED METHODS ==== */
|
||||||
|
|
||||||
|
void update_leds() {
|
||||||
|
|
||||||
|
for (int pin = 0; pin < LED_COUNT; pin++) {
|
||||||
|
if (led_list[pin].ledState == true) {
|
||||||
|
long timeDiff = millis() - led_list[pin].startMillis;
|
||||||
|
|
||||||
|
if (timeDiff > led_list[pin].onTime) {
|
||||||
|
led_list[pin].ledState = false;
|
||||||
|
led_list[pin].startMillis = 0;
|
||||||
|
set_pin_status(pin, false);
|
||||||
|
Serial.print("turning off led #");
|
||||||
|
Serial.println(pin);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_led_state(byte pin, bool onState, long duration) {
|
||||||
|
|
||||||
|
if (onState == led_list[pin].ledState) {
|
||||||
|
return;
|
||||||
|
} else if ((onState == true) && (duration > 0)) {
|
||||||
|
Serial.print("Turning on LED #");
|
||||||
|
Serial.print(pin);
|
||||||
|
Serial.print(" for ");
|
||||||
|
Serial.print(duration / 1000);
|
||||||
|
Serial.println(" seconds");
|
||||||
|
led_list[pin].startMillis = millis();
|
||||||
|
led_list[pin].onTime = duration;
|
||||||
|
Serial.println(duration);
|
||||||
|
set_pin_status(pin, true);
|
||||||
|
} else {
|
||||||
|
Serial.print("Turning off LED #");
|
||||||
|
Serial.println(pin);
|
||||||
|
led_list[pin].startMillis = 0;
|
||||||
|
set_pin_status(pin, false);
|
||||||
|
}
|
||||||
|
|
||||||
|
led_list[pin].ledState = onState;
|
||||||
|
}
|
||||||
|
|
||||||
|
void cycle_all_leds()
|
||||||
|
{
|
||||||
|
for (int x = 0; x < 3; x++)
|
||||||
|
{
|
||||||
|
for (int i = 0; i < 8; i++)
|
||||||
|
{
|
||||||
|
Serial.print("LED #");
|
||||||
|
int led_num = (x * 8) + i;
|
||||||
|
Serial.println(led_num);
|
||||||
|
bitSet(leds[x], i);
|
||||||
|
updateShiftRegister();
|
||||||
|
delay(2000);
|
||||||
|
bitClear(leds[x], i);
|
||||||
|
updateShiftRegister();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
void all_leds_off()
|
||||||
|
{
|
||||||
|
leds[0] = 0;
|
||||||
|
leds[1] = 0;
|
||||||
|
leds[2] = 0;
|
||||||
|
updateShiftRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void led_red(){
|
||||||
|
set_led_state(2, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(7, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(8, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(11, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(13, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(15, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(16, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(19, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(21, true, DEFAULT_LED_TIME);
|
||||||
|
set_led_state(23, true, DEFAULT_LED_TIME);
|
||||||
|
}
|
||||||
|
|
||||||
|
void set_pin_status(int pinNumber, bool pinStatus) {
|
||||||
|
|
||||||
|
byte idx = 0;
|
||||||
|
|
||||||
|
while (pinNumber >= 8) {
|
||||||
|
pinNumber -= 8;
|
||||||
|
idx++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pinStatus == true) {
|
||||||
|
//Serial.println("LED ON");
|
||||||
|
bitSet(leds[idx], pinNumber);
|
||||||
|
} else {
|
||||||
|
//Serial.println("LED OFF");
|
||||||
|
bitClear(leds[idx], pinNumber);
|
||||||
|
}
|
||||||
|
|
||||||
|
updateShiftRegister();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateShiftRegister()
|
||||||
|
{
|
||||||
|
pinMode(dataPin, OUTPUT);
|
||||||
|
digitalWrite(ledLatchPin, LOW);
|
||||||
|
shiftOut(dataPin, clockPin, MSBFIRST, leds[2]);
|
||||||
|
shiftOut(dataPin, clockPin, MSBFIRST, leds[1]);
|
||||||
|
shiftOut(dataPin, clockPin, MSBFIRST, leds[0]);
|
||||||
|
digitalWrite(ledLatchPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== SERVO METHODS ==== */
|
||||||
|
|
||||||
|
void zero_all_servos() {
|
||||||
|
Serial.println("Setting all servos to zero");
|
||||||
|
for (int x = 1; x < 16; x++) {
|
||||||
|
servos.setPWM(x, 0, SERVOMAX);
|
||||||
|
servo_pwm[x] = SERVOMAX;
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
void center_all_servos() {
|
||||||
|
Serial.println("Setting all servos to center");
|
||||||
|
for (int x = 1; x < 16; x++) {
|
||||||
|
move_servo_to_percent(x, 50);
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
void max_all_servos() {
|
||||||
|
Serial.println("Setting all servos to maximum");
|
||||||
|
for (int x = 1; x < 16; x++) {
|
||||||
|
servos.setPWM(x, 0, SERVOMIN);
|
||||||
|
servo_pwm[x] = SERVOMIN;
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_servo_to_degree(byte servo_num, int degrees) {
|
||||||
|
int pulselength = map(degrees, 0, 180, SERVOMAX, SERVOMIN);
|
||||||
|
servos.setPWM(servo_num, 0, pulselength);
|
||||||
|
servo_pwm[servo_num] = pulselength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_servo_to_percent(byte servo_num, int percentage) {
|
||||||
|
int pulselength = map(percentage, 0, 100, SERVOMAX, SERVOMIN);
|
||||||
|
servos.setPWM(servo_num, 0, pulselength);
|
||||||
|
servo_pwm[servo_num] = pulselength;
|
||||||
|
}
|
||||||
|
|
||||||
|
void move_servo_to_percent_timed(byte servo_num, int percentage, int duration){
|
||||||
|
int new_pulselength = map(percentage, 0, 100, SERVOMAX, SERVOMIN);
|
||||||
|
int old_pulselength = servo_pwm[servo_num];
|
||||||
|
int duration_millis = (duration * 1000) / 40; //200
|
||||||
|
|
||||||
|
int millis_interval = (new_pulselength - old_pulselength) / duration_millis;
|
||||||
|
Serial.println(new_pulselength);
|
||||||
|
Serial.println(old_pulselength);
|
||||||
|
|
||||||
|
for (int i=0; i <= duration_millis; i++){
|
||||||
|
int pulselength = old_pulselength + (i * millis_interval);
|
||||||
|
servos.setPWM(servo_num, 0, pulselength);
|
||||||
|
delay(40);
|
||||||
|
}
|
||||||
|
servos.setPWM(servo_num, 0, new_pulselength);
|
||||||
|
servo_pwm[servo_num] = new_pulselength;
|
||||||
|
Serial.println("Ready");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ==== SERVO METHODS ==== */
|
||||||
|
|
||||||
|
void globe(){
|
||||||
|
|
||||||
|
if (move_globe == true){
|
||||||
|
move_globe = false;
|
||||||
|
analogWrite(globeMotor, 0);
|
||||||
|
move_servo_to_percent(0, 50);
|
||||||
|
Serial.println("Globe movement off");
|
||||||
|
}else{
|
||||||
|
move_globe = true;
|
||||||
|
analogWrite(globeMotor, 50);
|
||||||
|
Serial.println("Globe movement on");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
void advance_globe() {
|
||||||
|
|
||||||
|
// Orbital period 88.5 minutes - 5310 seconds
|
||||||
|
// 6283 time slices
|
||||||
|
// Updates every 845 milliseconds
|
||||||
|
|
||||||
|
if (move_globe == false){
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const int orbital_period = 5310;
|
||||||
|
const int inclination = 90;
|
||||||
|
const float sine_increment = 0.001;
|
||||||
|
const float two_pi = 6.283;
|
||||||
|
const float time_delta = (orbital_period / (two_pi / sine_increment)) * 1000;
|
||||||
|
|
||||||
|
static float x = 0;
|
||||||
|
static unsigned long last_update = 0;
|
||||||
|
unsigned long current_millis = millis();
|
||||||
|
|
||||||
|
// Update if time delta has passed or never updated
|
||||||
|
if ((current_millis - last_update) >= time_delta || last_update == 0) {
|
||||||
|
|
||||||
|
float val = sin(x) * inclination + inclination;
|
||||||
|
|
||||||
|
move_servo_to_degree(globeServo, int(val));
|
||||||
|
//HIGH_servo.write(int(val));
|
||||||
|
|
||||||
|
x += sine_increment;
|
||||||
|
|
||||||
|
// Rollover angle
|
||||||
|
if (x >= two_pi) {
|
||||||
|
x = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
last_update = current_millis;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
16
src/MercuryController.py
Normal file
16
src/MercuryController.py
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import serial
|
||||||
|
|
||||||
|
|
||||||
|
class MercuryController:
|
||||||
|
def __init__(self, port, baud):
|
||||||
|
self.serial = serial.Serial(port, baud)
|
||||||
|
self.serial.flushInput()
|
||||||
|
|
||||||
|
def led_on(self, pin):
|
||||||
|
self.serial.write("LED {} on".format(pin))
|
||||||
|
|
||||||
|
def led_off(self, pin):
|
||||||
|
self.serial.write("LED {} off".format(pin))
|
||||||
|
|
||||||
|
def set_servo_percent(self, servo, percent):
|
||||||
|
self.serial.write("servo {0} {1}".format(servo, percent))
|
||||||
491
src/SimController.py
Normal file
491
src/SimController.py
Normal file
@@ -0,0 +1,491 @@
|
|||||||
|
#! /usr/bin/env python
|
||||||
|
import datetime
|
||||||
|
import math
|
||||||
|
import sys
|
||||||
|
import os
|
||||||
|
import time
|
||||||
|
import subprocess
|
||||||
|
import random
|
||||||
|
import csv
|
||||||
|
import serial
|
||||||
|
import json
|
||||||
|
# import keyboard
|
||||||
|
import logging
|
||||||
|
from numpy import interp
|
||||||
|
from threading import Thread
|
||||||
|
from distutils.spawn import find_executable
|
||||||
|
from MercuryController import *
|
||||||
|
|
||||||
|
|
||||||
|
class MercurySim:
|
||||||
|
def __init__(self):
|
||||||
|
|
||||||
|
self.config = json.loads(open('config.json').read())
|
||||||
|
|
||||||
|
# Mission Time
|
||||||
|
self.running = False
|
||||||
|
self.launch_time = None
|
||||||
|
self.mission_time = None
|
||||||
|
|
||||||
|
self.running_thread = None
|
||||||
|
|
||||||
|
# Scenes
|
||||||
|
self.current_scene = 0
|
||||||
|
self.scenes = list(csv.DictReader(open('scenes.csv')))
|
||||||
|
|
||||||
|
# Mission Events
|
||||||
|
self.mission_events = list(csv.DictReader(open('events_launch.csv')))
|
||||||
|
self.retrograde_time = t_time_to_seconds([x for x in self.mission_events if x['name'] == "retrofire"][0]['time'])
|
||||||
|
self.event_history = []
|
||||||
|
|
||||||
|
# Window
|
||||||
|
# self.window = WindowDisplay()
|
||||||
|
|
||||||
|
# Displays
|
||||||
|
self.time_display = TimeDisplay()
|
||||||
|
self.time_display.set_retrograde_time(self.retrograde_time)
|
||||||
|
|
||||||
|
# Audio Devices
|
||||||
|
self.sfx_audio = AudioController("sfx", output=0, volume='100%')
|
||||||
|
self.capcom_audio = AudioController("capcom", output=1, volume='40%')
|
||||||
|
|
||||||
|
# LEDs
|
||||||
|
self.leds = {}
|
||||||
|
for x in csv.DictReader(open('led_mapping.csv')):
|
||||||
|
if x['name']:
|
||||||
|
self.leds[x['name']] = x['number']
|
||||||
|
|
||||||
|
# Servos
|
||||||
|
self.servos = {}
|
||||||
|
for x in csv.DictReader(open('servo_mapping.csv')):
|
||||||
|
if x['name']:
|
||||||
|
self.servos[x['name']] = x
|
||||||
|
|
||||||
|
# Draw default stars
|
||||||
|
subprocess.Popen('fbi -a stars.jpg -d /dev/fb0 -T 1 --noverbose', shell=True)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.controller = MercuryController(None, 9600)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Unable to connect to Mercury Arduino: {}".format(e))
|
||||||
|
self.controller = None
|
||||||
|
|
||||||
|
def teardown(self):
|
||||||
|
logging.info('')
|
||||||
|
logging.info('{:-^40}'.format(' Teardown '))
|
||||||
|
|
||||||
|
AudioController.stop_all_audio()
|
||||||
|
subprocess.Popen(['sudo', 'killall', 'omxplayer.bin']) # stop video
|
||||||
|
|
||||||
|
|
||||||
|
# -- Mission Clock
|
||||||
|
|
||||||
|
def update_time(self):
|
||||||
|
time = time_from(self.launch_time)
|
||||||
|
updated_time = self.mission_time != time
|
||||||
|
self.mission_time = time
|
||||||
|
return updated_time
|
||||||
|
|
||||||
|
# -- Servos
|
||||||
|
|
||||||
|
def set_servo_value(self, val, servo):
|
||||||
|
x = interp(val,[float(servo['minval']),float(servo['maxval'])],[float(servo['minpercent']),float(servo['maxpercent'])])
|
||||||
|
logging.debug("Set servo {} value to {}".format(servo['name'], x))
|
||||||
|
if self.controller:
|
||||||
|
self.controller.set_servo_percent(servo['number'], x)
|
||||||
|
|
||||||
|
# -- Audio
|
||||||
|
|
||||||
|
def play_timed_audio(self):
|
||||||
|
|
||||||
|
# Play timed capcom files
|
||||||
|
if self.mission_time < 1:
|
||||||
|
timed_capcom = "capcom_{}.wav".format(abs(self.mission_time))
|
||||||
|
else:
|
||||||
|
timed_capcom = "capcom_p{}.wav".format(abs(self.mission_time))
|
||||||
|
if timed_capcom in self.capcom_audio.files:
|
||||||
|
self.capcom_audio.play_file(timed_capcom)
|
||||||
|
|
||||||
|
def update_time_display(self):
|
||||||
|
# Update time display
|
||||||
|
time_to_retrograde = max(self.retrograde_time - max(self.mission_time, 0), 0)
|
||||||
|
self.time_display.set_time_to_retrograde(time_to_retrograde)
|
||||||
|
self.time_display.set_time_from_launch(max(self.mission_time, 0))
|
||||||
|
|
||||||
|
def trigger_event(self, event_name, allow_failure=False):
|
||||||
|
|
||||||
|
# Don't trigger event if already done
|
||||||
|
if event_name in self.event_history:
|
||||||
|
logging.error("{} already triggered".format(event_name))
|
||||||
|
return
|
||||||
|
|
||||||
|
# Trigger videos first
|
||||||
|
if 'video' in event_name:
|
||||||
|
video_file = [x for x in os.listdir('video') if event_name.split('-')[-1] in x]
|
||||||
|
if video_file:
|
||||||
|
logging.info("Playing video file: {}".format(video_file))
|
||||||
|
play_video(video_file[0])
|
||||||
|
|
||||||
|
good_led = self.leds.get(event_name, None) or self.leds.get(event_name + "_green", None)
|
||||||
|
succeed = True if not allow_failure else not (random.randint(1, 10) == 5 and bool(good_led))
|
||||||
|
|
||||||
|
if succeed:
|
||||||
|
logging.info("Mission Event: " + event_name)
|
||||||
|
sfx_file = self.sfx_audio.file_with_name(event_name)
|
||||||
|
capcom_file = self.capcom_audio.file_with_name(event_name)
|
||||||
|
|
||||||
|
if sfx_file:
|
||||||
|
self.sfx_audio.play_file(sfx_file)
|
||||||
|
if capcom_file:
|
||||||
|
self.capcom_audio.play_file(capcom_file)
|
||||||
|
if good_led and self.controller:
|
||||||
|
self.controller.led_on(good_led)
|
||||||
|
self.event_history.append(event_name)
|
||||||
|
else:
|
||||||
|
logging.info("Mission Event (Failure): " + event_name)
|
||||||
|
bad_led = self.leds.get(event_name + "_red", None)
|
||||||
|
if bad_led and self.controller:
|
||||||
|
self.controller.led_on(bad_led)
|
||||||
|
|
||||||
|
def key_press(self, event):
|
||||||
|
|
||||||
|
key = event.name
|
||||||
|
|
||||||
|
if key in ['a', 'b', 'c', 'd']:
|
||||||
|
|
||||||
|
logging.info('Pressed {} key'.format(key))
|
||||||
|
self.running = False
|
||||||
|
if self.running_thread:
|
||||||
|
logging.info('-------Stopping thread-------')
|
||||||
|
self.running_thread.join()
|
||||||
|
if key == 'a': # start sim
|
||||||
|
self.running_thread = Thread(target=self.run_simulation)
|
||||||
|
else: # start scene
|
||||||
|
idx = ord(key) - 98 # convert char to int (i.e. b into 0, c into 1, etc)
|
||||||
|
self.running_thread = Thread(target=self.run_scene, args=(idx,))
|
||||||
|
self.running_thread.daemon = True
|
||||||
|
self.running_thread.start()
|
||||||
|
# elif key is not None:
|
||||||
|
# logging.error('Unknown key!')
|
||||||
|
|
||||||
|
def run_scene(self, scene_number):
|
||||||
|
|
||||||
|
logging.info('')
|
||||||
|
|
||||||
|
logging.info('{:-^40}'.format(' Starting Scene #{} '.format(scene_number)))
|
||||||
|
|
||||||
|
scene = self.scenes[scene_number]
|
||||||
|
play_video(scene['video'], loop=True, random_orientation=True)
|
||||||
|
# self.sfx_audio.play_file(scene['audio'], loop=True)
|
||||||
|
|
||||||
|
# Play ambient audio
|
||||||
|
self.sfx_audio.play_file("sfx_cabin_loop.wav", loop=True)
|
||||||
|
|
||||||
|
next_misc_capcom = 0
|
||||||
|
|
||||||
|
self.running = True
|
||||||
|
while self.running:
|
||||||
|
if not next_misc_capcom:
|
||||||
|
capcom_timings = self.config['capcom'][scene['mission_phase']]
|
||||||
|
next_misc_capcom = random.randint(capcom_timings['min'], capcom_timings['max'])
|
||||||
|
logging.info('next capcom in {}s'.format(t_time(next_misc_capcom)))
|
||||||
|
|
||||||
|
time.sleep(1)
|
||||||
|
|
||||||
|
next_misc_capcom -= 1
|
||||||
|
if not next_misc_capcom:
|
||||||
|
self.capcom_audio.play_random_file(scene['mission_phase'])
|
||||||
|
self.teardown()
|
||||||
|
|
||||||
|
def get_acceleration(self):
|
||||||
|
|
||||||
|
# Find Mission Events
|
||||||
|
old_events = [x for x in self.mission_events if t_time_to_seconds(x.get("time")) < self.mission_time and x.get('acceleration')]
|
||||||
|
next_events = [x for x in self.mission_events if t_time_to_seconds(x.get("time")) >= self.mission_time and x.get('acceleration')]
|
||||||
|
|
||||||
|
if old_events and next_events:
|
||||||
|
last_event = old_events[-1]
|
||||||
|
next_event = next_events[0]
|
||||||
|
if last_event['acceleration'] == next_event['acceleration']:
|
||||||
|
return float(next_event['acceleration'])
|
||||||
|
else:
|
||||||
|
x = interpolated_value(start_time=t_time_to_seconds(last_event["time"]), start_val=last_event['acceleration'],
|
||||||
|
end_time=t_time_to_seconds(next_event['time']), end_val=next_event['acceleration'],
|
||||||
|
current_time=self.mission_time, rate=2)
|
||||||
|
return x
|
||||||
|
elif old_events:
|
||||||
|
return float(old_events[-1].get('acceleration'))
|
||||||
|
elif next_events:
|
||||||
|
return float(next_events[0].get('acceleration'))
|
||||||
|
else:
|
||||||
|
logging.error('Get acceleration - Cannot find any events!')
|
||||||
|
|
||||||
|
def run_simulation(self):
|
||||||
|
|
||||||
|
logging.info('')
|
||||||
|
logging.info('{:-^40}'.format(' Starting Sim '))
|
||||||
|
|
||||||
|
# Setup launch time
|
||||||
|
self.launch_time = datetime.datetime.now() + datetime.timedelta(seconds=(self.config['prelaunch_time'] + 1))
|
||||||
|
orbit_time = [x for x in self.mission_events if 'orbit_phase' in x['name']][0]['time']
|
||||||
|
|
||||||
|
# Clear history
|
||||||
|
del self.event_history[:]
|
||||||
|
self.capcom_audio.clear_history()
|
||||||
|
self.sfx_audio.clear_history()
|
||||||
|
|
||||||
|
# Play video
|
||||||
|
play_video('launch.mp4', loop=False)
|
||||||
|
|
||||||
|
# Play ambient audio
|
||||||
|
self.sfx_audio.play_file("sfx_cabin_loop.wav", loop=True)
|
||||||
|
|
||||||
|
self.running = True
|
||||||
|
next_misc_capcom = None
|
||||||
|
while self.running:
|
||||||
|
|
||||||
|
# Don't kill CPU
|
||||||
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
# Look for button updates
|
||||||
|
# self.controller.has_updates()
|
||||||
|
|
||||||
|
# Trigger automatic functions
|
||||||
|
if self.update_time():
|
||||||
|
|
||||||
|
# Mission Time
|
||||||
|
current_t_time = t_time(self.mission_time)
|
||||||
|
acceleration = self.get_acceleration()
|
||||||
|
|
||||||
|
logging.info("{} - Accel: {:.1f}g".format(current_t_time, acceleration))
|
||||||
|
self.play_timed_audio()
|
||||||
|
self.update_time_display()
|
||||||
|
|
||||||
|
# Update Servos
|
||||||
|
self.set_servo_value(acceleration, self.servos['acceleration'])
|
||||||
|
|
||||||
|
# logging.info("Acceleration - {}".format(self.get_acceleration()))
|
||||||
|
|
||||||
|
# Trigger mission events
|
||||||
|
now_events = [x for x in self.mission_events if x.get("time") == current_t_time]
|
||||||
|
for event in now_events:
|
||||||
|
self.trigger_event(event['name'], allow_failure=self.config['allow_failures'])
|
||||||
|
|
||||||
|
if self.mission_time < 0:
|
||||||
|
mission_phase = 'prelaunch'
|
||||||
|
elif self.mission_time < t_time_to_seconds(orbit_time):
|
||||||
|
mission_phase = 'launch'
|
||||||
|
else:
|
||||||
|
mission_phase = 'orbit'
|
||||||
|
|
||||||
|
# Play Capcom Random
|
||||||
|
if next_misc_capcom == self.mission_time:
|
||||||
|
|
||||||
|
self.capcom_audio.play_random_file(mission_phase)
|
||||||
|
next_misc_capcom = None
|
||||||
|
|
||||||
|
# Setup next random capcom
|
||||||
|
if not next_misc_capcom:
|
||||||
|
capcom_timings = self.config['capcom'][mission_phase]
|
||||||
|
next_misc_capcom = random.randint(capcom_timings['min'], capcom_timings['max']) + self.mission_time
|
||||||
|
while True:
|
||||||
|
next_ttime = t_time(next_misc_capcom)
|
||||||
|
next_ttime_plus = t_time(next_misc_capcom + 1) # 1s padding
|
||||||
|
collision = any(next_ttime in x['time'] or next_ttime_plus in x['time'] for x in self.mission_events)
|
||||||
|
timed_format = 'capcom_{}'.format(abs(next_misc_capcom)) if next_misc_capcom < 0 else 'capcom_p{}'.format(abs(next_misc_capcom))
|
||||||
|
collision = collision or any(timed_format in x for x in self.capcom_audio.files)
|
||||||
|
if collision:
|
||||||
|
# logging.info('possible capcom collision. adding 2')
|
||||||
|
# logging.info('was: {}'.format(next_misc_capcom))
|
||||||
|
next_misc_capcom += 2
|
||||||
|
# logging.info('now: {}'.format(next_misc_capcom))
|
||||||
|
else:
|
||||||
|
break
|
||||||
|
|
||||||
|
logging.info('Next misc capcom at {}'.format(next_misc_capcom))
|
||||||
|
|
||||||
|
self.teardown()
|
||||||
|
|
||||||
|
class AudioController:
|
||||||
|
def __init__(self, type, output, volume):
|
||||||
|
self.player = find_executable('afplay') or find_executable('aplay')
|
||||||
|
self.type = type
|
||||||
|
self.play_history = []
|
||||||
|
self.files = [f for f in os.listdir('audio') if self.type in f]
|
||||||
|
self.output = str(output)
|
||||||
|
|
||||||
|
# Set volume to 100% on Pi
|
||||||
|
if "aplay" in self.player:
|
||||||
|
subprocess.call(['amixer', '-c', self.output, 'set', 'PCM', '--', volume])
|
||||||
|
logging.info('Setting volume on output {0} to {1}'.format(self.output, volume))
|
||||||
|
|
||||||
|
def play_random_file(self, prefix):
|
||||||
|
prefix = '_' + prefix + '_misc'
|
||||||
|
misc_audio = [f for f in self.files if prefix in f]
|
||||||
|
unplayed_audio = [m for m in misc_audio if m not in self.play_history]
|
||||||
|
if not unplayed_audio:
|
||||||
|
logging.info('Used all available audio. Resetting history')
|
||||||
|
self.clear_history()
|
||||||
|
unplayed_audio = misc_audio
|
||||||
|
while True:
|
||||||
|
misc_file = random.choice(unplayed_audio)
|
||||||
|
if misc_file not in self.play_history:
|
||||||
|
break
|
||||||
|
self.play_file(misc_file)
|
||||||
|
|
||||||
|
def file_with_name(self, name):
|
||||||
|
found_file = None
|
||||||
|
files = [f for f in self.files if os.path.splitext(f)[0].endswith(name)]
|
||||||
|
if files:
|
||||||
|
found_file = files[0]
|
||||||
|
return found_file
|
||||||
|
|
||||||
|
def play_file(self, filename, loop=False):
|
||||||
|
logging.info("Playing {0} audio file: {1}".format(self.type, filename))
|
||||||
|
dir_path = os.path.dirname(os.path.realpath(__file__))
|
||||||
|
filepath = os.path.join(dir_path, "audio", filename)
|
||||||
|
|
||||||
|
if self.output and "aplay" in self.player:
|
||||||
|
if loop:
|
||||||
|
# only omxplayer can loop
|
||||||
|
command = ['omxplayer', '--no-keys', '--no-osd', '--loop', filepath]
|
||||||
|
else:
|
||||||
|
# aplay for everything else
|
||||||
|
command = [self.player, '-D', 'default:{}'.format(self.output), '-c', '1', filepath]
|
||||||
|
else:
|
||||||
|
# macOS
|
||||||
|
command = [self.player, filepath]
|
||||||
|
|
||||||
|
subprocess.Popen(command)
|
||||||
|
self.play_history.append(filename)
|
||||||
|
|
||||||
|
def clear_history(self):
|
||||||
|
del self.play_history[:]
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def stop_all_audio(cls):
|
||||||
|
logging.info("Stopping all audio")
|
||||||
|
player = find_executable('afplay') or find_executable('aplay')
|
||||||
|
subprocess.call(["killall", os.path.basename(player)])
|
||||||
|
|
||||||
|
|
||||||
|
class TimeDisplay:
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
try:
|
||||||
|
self.arduino = serial.Serial('COM1', 115200, timeout=.1)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error("Cannot connect to TimeDisplay: {}".format(e))
|
||||||
|
|
||||||
|
def set_time_from_launch(self, time):
|
||||||
|
if hasattr(self, "arduino"):
|
||||||
|
self.arduino.write("time_from {}".format(time))
|
||||||
|
|
||||||
|
def set_time_to_retrograde(self, time):
|
||||||
|
if hasattr(self, "arduino"):
|
||||||
|
self.arduino.write("time_to {}".format(time))
|
||||||
|
|
||||||
|
def set_retrograde_time(self, time):
|
||||||
|
if hasattr(self, "arduino"):
|
||||||
|
self.arduino.write("retrograde {}".format(time))
|
||||||
|
|
||||||
|
|
||||||
|
def play_video(filename, loop=False, random_orientation=False, random_start=False):
|
||||||
|
player = find_executable('omxplayer')
|
||||||
|
if player:
|
||||||
|
logging.info("Playing video file: {}".format(filename))
|
||||||
|
filepath = os.path.join("video", filename)
|
||||||
|
|
||||||
|
commands = ['sudo', player, '--no-keys', '--no-osd', filepath, '--layer', '10']
|
||||||
|
# else:
|
||||||
|
# commands = ['sudo', player, '--no-keys', '--no-osd', filepath, '--layer', '10']
|
||||||
|
|
||||||
|
if loop:
|
||||||
|
commands.append('--loop')
|
||||||
|
|
||||||
|
if random_start:
|
||||||
|
commands.append('-p')
|
||||||
|
commands.append(random.randint(0, 60))
|
||||||
|
|
||||||
|
if random_orientation:
|
||||||
|
commands.append('--orientation')
|
||||||
|
commands.append(random.choice(['0', '180']))
|
||||||
|
|
||||||
|
p = subprocess.Popen(commands, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
|
||||||
|
time.sleep(0.2) # wait for video to start to not conflict with audio
|
||||||
|
else:
|
||||||
|
logging.error('No video player found')
|
||||||
|
|
||||||
|
|
||||||
|
# -- Functions --
|
||||||
|
|
||||||
|
|
||||||
|
def t_time_to_seconds(t_time_val):
|
||||||
|
raw_time = t_time_val[2:].split(":")
|
||||||
|
seconds = time_to_seconds(raw_time[0], raw_time[1], raw_time[2])
|
||||||
|
if t_time_val[:2] == "T-":
|
||||||
|
seconds = -seconds
|
||||||
|
return seconds
|
||||||
|
|
||||||
|
|
||||||
|
def time_to_seconds(hours=0, minutes=0, seconds=0):
|
||||||
|
# Define the constants
|
||||||
|
SECONDS_PER_MINUTE = 60
|
||||||
|
SECONDS_PER_HOUR = 3600
|
||||||
|
total_seconds = int(hours) * SECONDS_PER_HOUR
|
||||||
|
total_seconds = total_seconds + (int(minutes) * SECONDS_PER_MINUTE)
|
||||||
|
total_seconds = total_seconds + int(seconds)
|
||||||
|
|
||||||
|
return total_seconds
|
||||||
|
|
||||||
|
|
||||||
|
def time_from(from_time):
|
||||||
|
now = datetime.datetime.now()
|
||||||
|
return int((now - from_time).total_seconds())
|
||||||
|
|
||||||
|
|
||||||
|
def formatted_time(time_val):
|
||||||
|
time_val = abs(time_val)
|
||||||
|
hour = time_val // 3600
|
||||||
|
time_val %= 3600
|
||||||
|
minutes = time_val // 60
|
||||||
|
time_val %= 60
|
||||||
|
seconds = time_val
|
||||||
|
|
||||||
|
return "%02d:%02d:%02d" % (hour, minutes, seconds)
|
||||||
|
|
||||||
|
|
||||||
|
def t_time(time):
|
||||||
|
prefix = "T-" if time < 0 else "T+"
|
||||||
|
t_time = prefix + formatted_time(time)
|
||||||
|
return t_time
|
||||||
|
|
||||||
|
def interpolated_value(start_time, start_val, end_time, end_val, current_time, rate):
|
||||||
|
|
||||||
|
multiplier = math.pow(current_time-start_time, rate) / math.pow(end_time-start_time, rate)
|
||||||
|
current_val = (float(end_val)-float(start_val)) * multiplier + float(start_val)
|
||||||
|
|
||||||
|
return current_val
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
format = "%(asctime)s: %(message)s"
|
||||||
|
logging.basicConfig(format=format, level=logging.INFO)
|
||||||
|
|
||||||
|
# set cwd
|
||||||
|
os.chdir(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
|
||||||
|
try:
|
||||||
|
sim = MercurySim()
|
||||||
|
# keyboard.on_press(sim.key_press)
|
||||||
|
sim.run_simulation()
|
||||||
|
logging.info('Ready')
|
||||||
|
# play_video('launch.mp4')
|
||||||
|
while True:
|
||||||
|
time.sleep(0.1)
|
||||||
|
except KeyboardInterrupt:
|
||||||
|
logging.info("User Interrupt")
|
||||||
|
subprocess.Popen(['sudo', 'killall', 'fbi'])
|
||||||
|
sim.running = False
|
||||||
|
sim.teardown()
|
||||||
|
sys.exit(0)
|
||||||
BIN
src/audio/capcom_1.wav
Normal file
BIN
src/audio/capcom_1.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_10-old.wav
Normal file
BIN
src/audio/capcom_10-old.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_11.wav
Normal file
BIN
src/audio/capcom_11.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_15.wav
Normal file
BIN
src/audio/capcom_15.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_2.wav
Normal file
BIN
src/audio/capcom_2.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_3.wav
Normal file
BIN
src/audio/capcom_3.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_30.wav
Normal file
BIN
src/audio/capcom_30.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_35.wav
Normal file
BIN
src/audio/capcom_35.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_4.wav
Normal file
BIN
src/audio/capcom_4.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_40.wav
Normal file
BIN
src/audio/capcom_40.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_5.wav
Normal file
BIN
src/audio/capcom_5.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_6.wav
Normal file
BIN
src/audio/capcom_6.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_60.wav
Normal file
BIN
src/audio/capcom_60.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_7.wav
Normal file
BIN
src/audio/capcom_7.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_8.wav
Normal file
BIN
src/audio/capcom_8.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_9.wav
Normal file
BIN
src/audio/capcom_9.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_engine_start.wav
Normal file
BIN
src/audio/capcom_engine_start.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_go_1.wav
Normal file
BIN
src/audio/capcom_go_1.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_go_2.wav
Normal file
BIN
src/audio/capcom_go_2.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_go_3.wav
Normal file
BIN
src/audio/capcom_go_3.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_go_4.wav
Normal file
BIN
src/audio/capcom_go_4.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_1.wav
Normal file
BIN
src/audio/capcom_launch_misc_1.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_10.wav
Normal file
BIN
src/audio/capcom_launch_misc_10.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_11.wav
Normal file
BIN
src/audio/capcom_launch_misc_11.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_12.wav
Normal file
BIN
src/audio/capcom_launch_misc_12.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_13.wav
Normal file
BIN
src/audio/capcom_launch_misc_13.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_14.wav
Normal file
BIN
src/audio/capcom_launch_misc_14.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_15.wav
Normal file
BIN
src/audio/capcom_launch_misc_15.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_16.wav
Normal file
BIN
src/audio/capcom_launch_misc_16.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_17.wav
Normal file
BIN
src/audio/capcom_launch_misc_17.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_18.wav
Normal file
BIN
src/audio/capcom_launch_misc_18.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_19.wav
Normal file
BIN
src/audio/capcom_launch_misc_19.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_2.wav
Normal file
BIN
src/audio/capcom_launch_misc_2.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_20.wav
Normal file
BIN
src/audio/capcom_launch_misc_20.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_3.wav
Normal file
BIN
src/audio/capcom_launch_misc_3.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_4.wav
Normal file
BIN
src/audio/capcom_launch_misc_4.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_5.wav
Normal file
BIN
src/audio/capcom_launch_misc_5.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_6.wav
Normal file
BIN
src/audio/capcom_launch_misc_6.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_7.wav
Normal file
BIN
src/audio/capcom_launch_misc_7.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_8.wav
Normal file
BIN
src/audio/capcom_launch_misc_8.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_launch_misc_9.wav
Normal file
BIN
src/audio/capcom_launch_misc_9.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_liftoff.wav
Normal file
BIN
src/audio/capcom_liftoff.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_mark.wav
Normal file
BIN
src/audio/capcom_mark.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_max_q.wav
Normal file
BIN
src/audio/capcom_max_q.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_mission_start.wav
Normal file
BIN
src/audio/capcom_mission_start.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_1.wav
Normal file
BIN
src/audio/capcom_orbit_misc_1.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_10.wav
Normal file
BIN
src/audio/capcom_orbit_misc_10.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_11.wav
Normal file
BIN
src/audio/capcom_orbit_misc_11.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_12.wav
Normal file
BIN
src/audio/capcom_orbit_misc_12.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_13.wav
Normal file
BIN
src/audio/capcom_orbit_misc_13.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_14.wav
Normal file
BIN
src/audio/capcom_orbit_misc_14.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_15.wav
Normal file
BIN
src/audio/capcom_orbit_misc_15.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_16.wav
Normal file
BIN
src/audio/capcom_orbit_misc_16.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_17.wav
Normal file
BIN
src/audio/capcom_orbit_misc_17.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_18.wav
Normal file
BIN
src/audio/capcom_orbit_misc_18.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_19.wav
Normal file
BIN
src/audio/capcom_orbit_misc_19.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_2.wav
Normal file
BIN
src/audio/capcom_orbit_misc_2.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_20.wav
Normal file
BIN
src/audio/capcom_orbit_misc_20.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_21.wav
Normal file
BIN
src/audio/capcom_orbit_misc_21.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_22.wav
Normal file
BIN
src/audio/capcom_orbit_misc_22.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_23.wav
Normal file
BIN
src/audio/capcom_orbit_misc_23.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_24.wav
Normal file
BIN
src/audio/capcom_orbit_misc_24.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_25.wav
Normal file
BIN
src/audio/capcom_orbit_misc_25.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_26.wav
Normal file
BIN
src/audio/capcom_orbit_misc_26.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_27.wav
Normal file
BIN
src/audio/capcom_orbit_misc_27.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_28.wav
Normal file
BIN
src/audio/capcom_orbit_misc_28.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_29.wav
Normal file
BIN
src/audio/capcom_orbit_misc_29.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_3.wav
Normal file
BIN
src/audio/capcom_orbit_misc_3.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_30.wav
Normal file
BIN
src/audio/capcom_orbit_misc_30.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_31.wav
Normal file
BIN
src/audio/capcom_orbit_misc_31.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_32.wav
Normal file
BIN
src/audio/capcom_orbit_misc_32.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_33.wav
Normal file
BIN
src/audio/capcom_orbit_misc_33.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_4.wav
Normal file
BIN
src/audio/capcom_orbit_misc_4.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_5.wav
Normal file
BIN
src/audio/capcom_orbit_misc_5.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_6.wav
Normal file
BIN
src/audio/capcom_orbit_misc_6.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_7.wav
Normal file
BIN
src/audio/capcom_orbit_misc_7.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_8.wav
Normal file
BIN
src/audio/capcom_orbit_misc_8.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_misc_9.wav
Normal file
BIN
src/audio/capcom_orbit_misc_9.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbit_phase.wav
Normal file
BIN
src/audio/capcom_orbit_phase.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_orbits.wav
Normal file
BIN
src/audio/capcom_orbits.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_p40.wav
Normal file
BIN
src/audio/capcom_p40.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc1.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc1.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc10.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc10.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc11.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc11.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc12.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc12.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc13.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc13.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc14.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc14.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc15.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc15.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc16.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc16.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc17.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc17.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc18.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc18.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc19.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc19.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc2.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc2.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc20.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc20.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc21.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc21.wav
Normal file
Binary file not shown.
BIN
src/audio/capcom_prelaunch_misc22.wav
Normal file
BIN
src/audio/capcom_prelaunch_misc22.wav
Normal file
Binary file not shown.
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user