diff --git a/Mk1Pinout-Outdated.md b/Mk1Pinout-Outdated.md new file mode 100644 index 0000000..430378f --- /dev/null +++ b/Mk1Pinout-Outdated.md @@ -0,0 +1,20 @@ +|Env Sensor|Grey |x|x| | | +|Env Sensor|Green |x|x|White |RGB Array | +|Env Sensor|Blue |x|x|Grey |RGB Array | +| | |x|x| | | +|Env Sensor|Purple|x|x| | | +| | |x|x| | | +| | |x|x|Brown |Power LED | +| | |x|x|Red |Power LED | +| | |x|x| | | +|RGB Array |Black |x|x|Yellow |Button | +| | |x|x|Yellow |Button | +| | |x|x| | | +|Buzzer |Black |x|x| | | +| | |x|x| | | +| | |x|x|Orange |Notification LED| +| | |x|x|Yellow |Notification LED| +|Buzzer |White |x|x|Green |Warning LED | +| | |x|x|Dark Blue|Warning LED | +|White LED |Red |x|x| | | +|White LED |Brown |x|x| | | \ No newline at end of file diff --git a/Pinout.md b/Pinout.md deleted file mode 100644 index addea1d..0000000 --- a/Pinout.md +++ /dev/null @@ -1,20 +0,0 @@ -|Env Sensor|Grey|x|x| | | -|Env Sensor|Green|x|x|White|RGB Array| -|Env Sensor|Blue|x|x|Grey|RGB Array| -| | |x|x| | | -|Env Sensor|Purple|x|x| | | -| | |x|x| | | -| | |x|x|Brown|Power LED| -| | |x|x|Red|Power LED| -| | |x|x| | | -|RGB Array|Black|x|x|Yellow|Button| -| | |x|x|Yellow|Button| -| | |x|x| | | -|Buzzer|Black|x|x| | | -| | |x|x| | | -| | |x|x|Orange|Notification LED| -| | |x|x|Yellow|Notification LED| -|Buzzer|White|x|x|Green|Warning LED| -| | |x|x|Dark Blue|Warning LED| -|White LED|Red|x|x| | | -|White LED|Brown|x|x| | | \ No newline at end of file diff --git a/ServoSkull.sln b/ServoSkull.sln index e9ed18e..5266c87 100644 --- a/ServoSkull.sln +++ b/ServoSkull.sln @@ -17,7 +17,7 @@ EndProject Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{EE38A10C-F0BB-40B5-B1E6-8CB16C6E452C}" ProjectSection(SolutionItems) = preProject .editorconfig = .editorconfig - Pinout.md = Pinout.md + Mk1Pinout-Outdated.md = Mk1Pinout-Outdated.md EndProjectSection EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "skullOS.API", "skullOS.API\skullOS.API.csproj", "{5E1EC385-4B61-4E8C-82C7-46695A33AC72}" diff --git a/skullOS.API/Controllers/CameraController.cs b/skullOS.API/Controllers/CameraController.cs index 0f19f2e..30f1cf4 100644 --- a/skullOS.API/Controllers/CameraController.cs +++ b/skullOS.API/Controllers/CameraController.cs @@ -17,17 +17,15 @@ public CameraController(ILogger logger, ICameraModule camera) } [HttpGet("TakePicture")] - public string TakePicture() + public async Task TakePicture() { - _module.TakePicture(); - return "Picture Taken!"; + await _module.TakePicture(); } [HttpGet("RecordVideo")] - public string RecordVideo() + public async Task RecordVideo() { - _module.RecordShortVideo(); - return "Video Recorded!"; + await _module.RecordShortVideo(); } } } diff --git a/skullOS.API/Program.cs b/skullOS.API/Program.cs index 5b9ba9a..1e92ec2 100644 --- a/skullOS.API/Program.cs +++ b/skullOS.API/Program.cs @@ -1,3 +1,4 @@ +using skullOS.Core; using skullOS.Modules; using skullOS.Modules.Interfaces; @@ -15,13 +16,18 @@ public static void Main(string[] args) // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); - builder.WebHost.UseUrls("http://*:5000;https://*:5001"); + builder.WebHost.UseUrls("http://*:5000;"); + + #region Skull Configuration + FileManager.CreateSkullDirectory(false); + #endregion #region Skull Modules - builder.Services.AddScoped(); - builder.Services.AddScoped(); + builder.Services.AddSingleton(); + builder.Services.AddSingleton(); #endregion + var app = builder.Build(); // Configure the HTTP request pipeline. diff --git a/skullOS.HardwareServices/CameraService.cs b/skullOS.HardwareServices/CameraService.cs index 9392d08..d838caa 100644 --- a/skullOS.HardwareServices/CameraService.cs +++ b/skullOS.HardwareServices/CameraService.cs @@ -1,45 +1,80 @@ -using Iot.Device.Camera.Settings; +using Iot.Device.Camera.Settings; using Iot.Device.Common; -using Iot.Device.Media; +using skullOS.HardwareServices.Exceptions; using skullOS.HardwareServices.Interfaces; +using System.Diagnostics; namespace skullOS.HardwareServices { public class CameraService : ICameraService { - public VideoDevice Camera { get; private set; } + private ProcessSettings _processSettings; + int xResolution; + int yResolution; - private readonly ProcessSettings _processSettings; + public CameraService(int x = 2592, int y = 1944) + { + _processSettings = ProcessSettingsFactory.CreateForLibcamerastill(); + xResolution = x; + yResolution = y; + } - public CameraService(VideoConnectionSettings? cameraSettings = null) + //Why are we back to hard-calling libcamera again?! :( + //Remember that this needs rpicam-apps full to be installed(lite os doesn't come with it) + //TODO: Still needs quality setting + public async Task RecordShortVideoAsync(string fileLocation, bool useMic) { - cameraSettings ??= new(busId: 0, captureSize: (2592, 1944), pixelFormat: VideoPixelFormat.JPEG); - Camera = VideoDevice.Create(cameraSettings); - Camera.Settings.HorizontalFlip = true; - Camera.Settings.VerticalFlip = true; + try + { + using Process videoRecording = new(); + string args = string.Empty; + if (useMic) + { + args = " --codec libav --hflip --vflip --libav-audio --width 1920 --height 1080 -t 30000 -o " + $"{fileLocation}" + + DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp4"; + } + else + { + args = " --codec libav --hflip --vflip --width 1920 --height 1080 -t 30000 -o " + $"{fileLocation}" + + DateTime.Now.ToString("yyyyMMddHHmmss") + ".mp4"; + } + videoRecording.StartInfo.UseShellExecute = false; + videoRecording.StartInfo.FileName = "libcamera-vid"; + videoRecording.StartInfo.Arguments = args; + videoRecording.EnableRaisingEvents = true; +#if DEBUG + await Console.Out.WriteLineAsync("Running:"); + await Console.Out.WriteLineAsync(videoRecording.StartInfo.FileName + videoRecording.StartInfo.Arguments); +#endif + videoRecording.Start(); + await Task.WhenAny(Task.Delay(30000)); + } + catch (CameraErrorException e) + { + await Console.Out.WriteLineAsync(e.Message); + return "Camera errored when recording video!"; + } - _processSettings = ProcessSettingsFactory.CreateForLibcamerastill(); + return $"({DateTime.Now}) Short video recorded!"; } - public async Task TakePictureAsync(string fileLocation, int x = 2592, int y = 1944) + public async Task TakePictureAsync(string fileLocation) { var builder = new CommandOptionsBuilder() .WithTimeout(1) .WithVflip() .WithHflip() .WithPictureOptions(quality: 100) - .WithResolution(x, y); + .WithResolution(xResolution, yResolution); var args = builder.GetArguments(); + _processSettings = ProcessSettingsFactory.CreateForLibcamerastill(); using var proc = new ProcessRunner(_processSettings); - Console.WriteLine("Using the following command line:"); - Console.WriteLine(proc.GetFullCommandLine(args)); - Console.WriteLine(); var timestamp = DateTime.Now.ToString("yyyyMMddHHmmss"); string? filename = fileLocation + timestamp + ".jpg"; - //string? filename = $"{DateTime.Now:yyyyMMddHHmmss}.jpg"; //Fakename + try { using var file = File.OpenWrite(filename); @@ -47,10 +82,10 @@ public async Task TakePictureAsync(string fileLocation, int x = 2592, in } catch (Exception) { - await Console.Out.WriteLineAsync("Cam errored!"); + await Console.Out.WriteLineAsync("Cam errored when taking picture!"); } - return filename; + return $"({DateTime.Now}) Picture taken!"; } } } diff --git a/skullOS.HardwareServices/Exceptions/CameraErrorException.cs b/skullOS.HardwareServices/Exceptions/CameraErrorException.cs new file mode 100644 index 0000000..20c1eb4 --- /dev/null +++ b/skullOS.HardwareServices/Exceptions/CameraErrorException.cs @@ -0,0 +1,14 @@ +namespace skullOS.HardwareServices.Exceptions +{ + public enum CameraMode + { + Picture, + ShortVideo, + LongVideo + } + + public class CameraErrorException(string message, CameraMode modeWhenFailed) : Exception(message) + { + public CameraMode Mode; + } +} diff --git a/skullOS.HardwareServices/Interfaces/ICameraService.cs b/skullOS.HardwareServices/Interfaces/ICameraService.cs index d87e79a..d2268fd 100644 --- a/skullOS.HardwareServices/Interfaces/ICameraService.cs +++ b/skullOS.HardwareServices/Interfaces/ICameraService.cs @@ -3,6 +3,7 @@ namespace skullOS.HardwareServices.Interfaces { public interface ICameraService { - Task TakePictureAsync(string fileLocation, int x = 2592, int y = 1944); + Task TakePictureAsync(string fileLocation); + Task RecordShortVideoAsync(string fileLocation, bool useMic); } } \ No newline at end of file diff --git a/skullOS.HardwareServices/Interfaces/ILedService.cs b/skullOS.HardwareServices/Interfaces/ILedService.cs index 0950d4d..9aa3781 100644 --- a/skullOS.HardwareServices/Interfaces/ILedService.cs +++ b/skullOS.HardwareServices/Interfaces/ILedService.cs @@ -3,8 +3,8 @@ public interface ILedService { void BlinkLight(string light); - void TurnOff(int Pin); - void TurnOn(int Pin); + void TurnOff(string Pin); + void TurnOn(string Pin); Dictionary GetLeds(); } } \ No newline at end of file diff --git a/skullOS.HardwareServices/LedService.cs b/skullOS.HardwareServices/LedService.cs index 5c381b5..b250799 100644 --- a/skullOS.HardwareServices/LedService.cs +++ b/skullOS.HardwareServices/LedService.cs @@ -16,28 +16,29 @@ public LedService(Dictionary leds) public async void BlinkLight(string light) { - int pin = LEDs[light]; - TurnOn(pin); + TurnOn(light); await Task.Delay(750); - TurnOff(pin); + TurnOff(light); } - public void TurnOn(int Pin) + public void TurnOn(string light) { - if (!controller.IsPinOpen(Pin)) + int pin = LEDs[light]; + if (!controller.IsPinOpen(pin)) { - controller.OpenPin(Pin, PinMode.Output); + controller.OpenPin(pin, PinMode.Output); } - controller.Write(Pin, PinValue.High); + controller.Write(pin, PinValue.High); } - public void TurnOff(int Pin) + public void TurnOff(string light) { - if (!controller.IsPinOpen(Pin)) + int pin = LEDs[light]; + if (!controller.IsPinOpen(pin)) { - controller.OpenPin(Pin, PinMode.Output); + controller.OpenPin(pin, PinMode.Output); } - controller.Write(Pin, PinValue.Low); + controller.Write(pin, PinValue.Low); } public Dictionary GetLeds() diff --git a/skullOS.HardwareServices/SpeakerService.cs b/skullOS.HardwareServices/SpeakerService.cs index 5263792..baad4c7 100644 --- a/skullOS.HardwareServices/SpeakerService.cs +++ b/skullOS.HardwareServices/SpeakerService.cs @@ -5,7 +5,8 @@ namespace skullOS.HardwareServices { /// /// Service to communicate with audio output - /// Requires `sudo apt install --no-install-recommends vlc-bin vlc-plugin-base` to have been ran first + /// Requires `sudo apt install --no-install-recommends vlc-bin vlc-plugin-base` to have been ran first which isn't on lite os + /// If deploying to a pizero, may also need to do the following: https://learn.adafruit.com/adafruit-max98357-i2s-class-d-mono-amp/raspberry-pi-usage /// public class SpeakerService : ISpeakerService { diff --git a/skullOS.Modules/Adventure.cs b/skullOS.Modules/Adventure.cs index 333d3b1..e463cb0 100644 --- a/skullOS.Modules/Adventure.cs +++ b/skullOS.Modules/Adventure.cs @@ -30,7 +30,7 @@ public Adventure() private void TakePicture_Elapsed(object? sender, System.Timers.ElapsedEventArgs e) { - cameraService.TakePictureAsync(directory, 1920, 1080); + cameraService.TakePictureAsync(directory); } public override void OnAction(object? sender, EventArgs e) diff --git a/skullOS.Modules/Camera.cs b/skullOS.Modules/Camera.cs index b54302b..95ce260 100644 --- a/skullOS.Modules/Camera.cs +++ b/skullOS.Modules/Camera.cs @@ -1,4 +1,4 @@ -using skullOS.Core; +using skullOS.Core; using skullOS.HardwareServices; using skullOS.Modules.Interfaces; @@ -15,11 +15,15 @@ public class Camera : Module, ICameraModule { public CameraService CameraService; public MicrophoneService? MicrophoneService = null; + public SpeakerService? SpeakerService = null; public LedService? LedService = null; public CameraMode CameraMode = CameraMode.Image; - public BuzzerService BuzzerService; + public BuzzerService? BuzzerService = null; bool useMic = false; + bool useSpeaker = false; + bool useBuzzer = false; + bool isActive = false; public Camera() { @@ -52,32 +56,92 @@ public Camera() LedService = new LedService(pins); } } - - BuzzerService = new BuzzerService(13); + if (cameraSettings.ContainsKey("UseBuzzer")) + { + if (cameraSettings.TryGetValue("UseBuzzer", out string shouldUseBuzzer)) + { + if (bool.Parse(shouldUseBuzzer)) + { + BuzzerService = new BuzzerService(13); + useBuzzer = true; + } + else + { + //No Mic desired + } + } + } + if (cameraSettings.ContainsKey("UseSpeaker")) + { + if (cameraSettings.TryGetValue("UseSpeaker", out string shouldUseSpeaker)) + { + if (bool.Parse(shouldUseSpeaker)) + { + SpeakerService = new SpeakerService(); + useSpeaker = true; + } + else + { + //No Mic desired + } + } + } } - public async void TakePicture() + public async Task TakePicture() { - if (LedService != null && LedService.LEDs.ContainsKey("CameraLight")) + if (!isActive) { - LedService.BlinkLight("CameraLight"); + isActive = true; + if (LedService != null && LedService.LEDs.ContainsKey("CameraLight")) + { + LedService.BlinkLight("CameraLight"); + } + if (useBuzzer) + { + BuzzerService.Buzzer.PlayTone(1500, 500); + } + if (useSpeaker) + { + _ = SpeakerService.PlayAudio(@"Resources\51360__thecheeseman__camera_snap1.mp3"); + } + string result = await CameraService.TakePictureAsync($"{FileManager.GetSkullDirectory()}/Captures/"); + LogMessage(result); + isActive = false; } - BuzzerService.Buzzer.PlayTone(1500, 500); - await CameraService.TakePictureAsync($"{FileManager.GetSkullDirectory()}/Captures/"); - LogMessage($"({DateTime.Now}) Picture taken!"); - //CameraService.Camera.Capture($"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}.jpg"); } - public void RecordShortVideo() + public async Task RecordShortVideo() { - string audioLocation = $"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}.mp3"; - string videoLocation = $"{FileManager.GetSkullDirectory()}/Captures/{DateTime.Now:yyyyMMddHHmmss}"; - //CameraService.RecordVideoAsync(FileManager.GetSkullDirectory() + "/Captures", 30); - if (useMic && MicrophoneService != null) + if (!isActive) { - MicrophoneService.Microphone.Record(30, audioLocation); + isActive = true; + if (LedService != null && LedService.LEDs.ContainsKey("CameraLight")) + { + LedService.TurnOn("CameraLight"); + } + if (useBuzzer) + { + BuzzerService.Buzzer.PlayTone(1500, 500); + } + if (useSpeaker) + { + _ = SpeakerService.PlayAudio(@"Resources\195912__acpascal__start-beep.mp3"); + } + string result = await CameraService.RecordShortVideoAsync($"{FileManager.GetSkullDirectory()}/Captures/", false); + LogMessage(result); + if (LedService != null && LedService.LEDs.ContainsKey("CameraLight")) + { + LedService.TurnOff("CameraLight"); + } + if (useSpeaker) + { + //Play camera stop sound + } + isActive = false; } + } public override void OnEnable(string[] args) @@ -94,15 +158,15 @@ public override string ToString() return "Camera"; } - public override void OnAction(object? sender, EventArgs e) + public override async void OnAction(object? sender, EventArgs e) { switch (CameraMode) { case CameraMode.Image: - TakePicture(); + await TakePicture(); break; case CameraMode.ShortVideo: - RecordShortVideo(); + await RecordShortVideo(); break; case CameraMode.ContinuousVideo: break; diff --git a/skullOS.Modules/Data/CameraSettings.txt b/skullOS.Modules/Data/CameraSettings.txt index 56e98a2..1c90400 100644 --- a/skullOS.Modules/Data/CameraSettings.txt +++ b/skullOS.Modules/Data/CameraSettings.txt @@ -1,2 +1,3 @@ UseMic=False -CameraLight=26 \ No newline at end of file +UseBuzzer=False +CameraLight=6 \ No newline at end of file diff --git a/skullOS.Modules/Data/PropSettings.txt b/skullOS.Modules/Data/PropSettings.txt index 99f3565..10600e6 100644 --- a/skullOS.Modules/Data/PropSettings.txt +++ b/skullOS.Modules/Data/PropSettings.txt @@ -1,3 +1,3 @@ -Sounds=True -Lights=True -Servos=True \ No newline at end of file +Sounds=False +Lights=False +Servos=False \ No newline at end of file diff --git a/skullOS.Modules/Interfaces/ICameraModule.cs b/skullOS.Modules/Interfaces/ICameraModule.cs index 9096b38..5d29d19 100644 --- a/skullOS.Modules/Interfaces/ICameraModule.cs +++ b/skullOS.Modules/Interfaces/ICameraModule.cs @@ -2,7 +2,7 @@ { public interface ICameraModule { - void RecordShortVideo(); - void TakePicture(); + Task RecordShortVideo(); + Task TakePicture(); } } \ No newline at end of file diff --git a/skullOS.Modules/Module.cs b/skullOS.Modules/Module.cs index 256c7d9..ec99ae6 100644 --- a/skullOS.Modules/Module.cs +++ b/skullOS.Modules/Module.cs @@ -15,10 +15,7 @@ public void AttachLogger(SkullLogger logger) public void LogMessage(string message) { - if (logger != null) - { - logger.LogMessage(message); - } + logger?.LogMessage(message); } } } diff --git a/skullOS.Modules/Prop.cs b/skullOS.Modules/Prop.cs index 02125d5..3fe5481 100644 --- a/skullOS.Modules/Prop.cs +++ b/skullOS.Modules/Prop.cs @@ -28,7 +28,9 @@ public Prop() { propSettings = SettingsLoader.LoadConfig(@"Data/PropSettings.txt"); - if (propSettings.ContainsKey("Sounds")) + propSettings.TryGetValue("Sounds", out string soundsState); + bool useSounds = bool.Parse(soundsState); + if (propSettings.ContainsKey("Sounds") && useSounds) { SpeakerService = new SpeakerService(); SpeakerService.PlayAudio(@"Resources/computer-startup-music.mp3"); //This one won't await :( @@ -40,22 +42,28 @@ public Prop() PlayIdleSound.Elapsed += PlayIdleSound_Elapsed; PlayIdleSound.Start(); } - if (propSettings.ContainsKey("Lights")) + + propSettings.TryGetValue("Lights", out string lightsState); + bool useLights = bool.Parse(lightsState); + if (propSettings.ContainsKey("Lights") && useLights) { //Left and right eye, these are next to each other so it should be easy to tell Dictionary pins = new Dictionary { - { "LeftEye", 22 }, - {"RightEye", 23 } + { "LeftEye", 26 }, + {"RightEye", 26 } }; LedService = new LedService(pins); foreach (var item in LedService.GetLeds()) { - int pin = item.Value; + string pin = item.Key; LedService.TurnOn(pin); } } - if (propSettings.ContainsKey("Servos")) + + propSettings.TryGetValue("Servos", out string servosState); + bool useServos = bool.Parse(servosState); + if (propSettings.ContainsKey("Servos") && useServos) { SoftwarePwmChannel leftPWM = new SoftwarePwmChannel(5, 50); leftFlap = new ServoMotor(leftPWM); @@ -71,7 +79,10 @@ private void PlayIdleSound_Elapsed(object? sender, System.Timers.ElapsedEventArg Random random = new Random(); int selection = random.Next(0, numberOfIdles + 1); SpeakerService.PlayAudio(sounds[selection]); - if (propSettings.ContainsKey("Servos")) + + propSettings.TryGetValue("Servos", out string servosState); + bool useServos = bool.Parse(servosState); + if (propSettings.ContainsKey("Servos") && useServos) { if (random.NextSingle() <= 0.5) { diff --git a/skullOS.Modules/Resources/195912__acpascal__start-beep.mp3 b/skullOS.Modules/Resources/195912__acpascal__start-beep.mp3 new file mode 100644 index 0000000..f93a47c Binary files /dev/null and b/skullOS.Modules/Resources/195912__acpascal__start-beep.mp3 differ diff --git a/skullOS.Modules/Resources/51360__thecheeseman__camera_snap1.mp3 b/skullOS.Modules/Resources/51360__thecheeseman__camera_snap1.mp3 new file mode 100644 index 0000000..5bb917f Binary files /dev/null and b/skullOS.Modules/Resources/51360__thecheeseman__camera_snap1.mp3 differ diff --git a/skullOS.Modules/Resources/Sources.txt b/skullOS.Modules/Resources/Sources.txt index afe7d73..646fe0b 100644 --- a/skullOS.Modules/Resources/Sources.txt +++ b/skullOS.Modules/Resources/Sources.txt @@ -1,2 +1,4 @@ No battery - https://freesound.org/people/DAN2008/sounds/710280/ -Haro Sounds - https://www.101soundboards.com/boards/44920-haro-sd-gundam-g-generation-genesis-combat-dialogue-nintendo-switch \ No newline at end of file +Haro Sounds - https://www.101soundboards.com/boards/44920-haro-sd-gundam-g-generation-genesis-combat-dialogue-nintendo-switch +camera_snap1.wav by thecheeseman -- https://freesound.org/s/51360/ -- License: Attribution 4.0 +Start Beep by ACPascal -- https://freesound.org/s/195912/ -- License: Attribution 4.0 \ No newline at end of file diff --git a/skullOS.Modules/skullOS.Modules.csproj b/skullOS.Modules/skullOS.Modules.csproj index 362674e..e393531 100644 --- a/skullOS.Modules/skullOS.Modules.csproj +++ b/skullOS.Modules/skullOS.Modules.csproj @@ -22,9 +22,27 @@ Always - + + Always + + Always + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + diff --git a/skullOS/Data/InputSettings.txt b/skullOS/Data/InputSettings.txt index 0902930..8487b28 100644 --- a/skullOS/Data/InputSettings.txt +++ b/skullOS/Data/InputSettings.txt @@ -1 +1,2 @@ -Camera(Image)=0 \ No newline at end of file +Camera(Image)=0 +Camera(ShortVideo)=0 \ No newline at end of file diff --git a/skullOS/Data/Modules.txt b/skullOS/Data/Modules.txt index 970f95f..35ee7bf 100644 --- a/skullOS/Data/Modules.txt +++ b/skullOS/Data/Modules.txt @@ -1,2 +1,3 @@ -Adventure=True -Camera=True \ No newline at end of file +Camera=True +Prop=True +Adventure=True \ No newline at end of file diff --git a/skullOS/Data/SkullInputSettings.txt b/skullOS/Data/SkullInputSettings.txt deleted file mode 100644 index 0902930..0000000 --- a/skullOS/Data/SkullInputSettings.txt +++ /dev/null @@ -1 +0,0 @@ -Camera(Image)=0 \ No newline at end of file diff --git a/skullOS/Data/SkullModules.txt b/skullOS/Data/SkullModules.txt deleted file mode 100644 index 2fcce2f..0000000 --- a/skullOS/Data/SkullModules.txt +++ /dev/null @@ -1,6 +0,0 @@ -Camera=True -Downlink=True -Uplink=True -Prop=True -QrCodeReader=True -Buzzer=True diff --git a/skullOS/InputManager.cs b/skullOS/InputManager.cs index 44bc179..bc9704a 100644 --- a/skullOS/InputManager.cs +++ b/skullOS/InputManager.cs @@ -8,14 +8,18 @@ namespace skullOS internal class InputManager { GpioButton ActionButton; - int actionButtonPin = 25; - private List? Buttons; + GpioButton ToggleButton; + int actionButtonPin = 24; //25 + int toggleButtonPin = 23; //26 private Module? activeModule; + List<(int, Module, string)> inputModules = []; + int index = 0; private SkullLogger? logger; public InputManager() { ActionButton = new GpioButton(actionButtonPin); + ToggleButton = new GpioButton(toggleButtonPin); } public void SetupSelector(List Modules) @@ -44,17 +48,61 @@ public void SetupSelector(List Modules) args = null; } - var module = Modules.Select(x => x).Where(x => x.ToString() == moduleToLoad).FirstOrDefault(); - if (module == null) + var module = Modules.Select(x => x).Where(x => x.ToString() == moduleToLoad).FirstOrDefault() ?? throw new Exception("Failed to load module for input binding!"); + SetActiveModule(module, args); + } + else + { + int count = 0; + foreach (var item in inputs) { - throw new Exception("Failed to load module for input binding!"); + string moduleToLoad; + string[]? args = new string[1]; + string moduleArguments = string.Empty; + + var match = Regex.Match(item.Key, @"[(]\w*[)]"); + if (match.Success) + { + moduleToLoad = item.Key.Split('(')[0]; + LogMessage("Identifed " + moduleToLoad + " as an input source"); + char[] charsToRemove = { '(', ')' }; + args.SetValue(match.Groups[0].Value.Trim(charsToRemove), 0); + moduleArguments = match.Groups[0].Value.Trim(charsToRemove); + LogMessage("Set argument to " + moduleArguments); + } + else + { + moduleToLoad = item.Key; + args = null; + } + + var module = Modules.Select(x => x).Where(x => x.ToString() == moduleToLoad).FirstOrDefault() ?? throw new Exception("Failed to load module for input binding!"); + inputModules.Add((count, module, moduleArguments)); + count++; } - SetActiveModule(module, args); + Console.WriteLine(count + " options have been registered for input"); + + + SetActiveModule(inputModules.FirstOrDefault().Item2, [inputModules.FirstOrDefault().Item3]); + ToggleButton.ButtonDown += ToggleButton_Press; + } + } + + private void ToggleButton_Press(object? sender, EventArgs e) + { + if (index + 1 < inputModules.Count) + { + index += 1; } else { - //If there's more than one, parse each one in the following pattern: module(args)=pin + index = 0; } + + var moduleToSetActive = inputModules[index]; + LogMessage("Attempting to load " + moduleToSetActive.Item2 + " with the args " + moduleToSetActive.Item3); + ActionButton.Press -= activeModule.OnAction; + SetActiveModule(moduleToSetActive.Item2, [moduleToSetActive.Item3]); } public void SetActiveModule(Module moduleToLoad, string[]? args = null) diff --git a/skullOS/Program.cs b/skullOS/Program.cs index da1a9de..6a65969 100644 --- a/skullOS/Program.cs +++ b/skullOS/Program.cs @@ -40,6 +40,7 @@ public static async Task Main(string[] args) break; } + await Console.Out.WriteLineAsync("Online and running!"); await Task.Delay(Timeout.Infinite); } diff --git a/skullOS/skullOS.csproj b/skullOS/skullOS.csproj index 56f4901..cc04f2a 100644 --- a/skullOS/skullOS.csproj +++ b/skullOS/skullOS.csproj @@ -24,12 +24,6 @@ Always - - Always - - - Always -