This repo is archived. You can view files and clone it, but cannot push or open issues or pull requests.

261 lines
9.3 KiB
C#
Raw Normal View History

2021-10-06 15:25:50 +13:00
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.IO.Ports;
using System.IO;
using System.Threading;
namespace RadioBroadcaster.Server
{
static class SerialManager
{
static bool _continue;
static SerialPort _serialPort;
/// <summary>
/// Data is sent at a predetermined rate. As the arduino can only process one piece of data at a time,
/// we add each command to the buffer; which will be sent as soon as possible
/// </summary>
static string[] SendBuffer = new string[0];
static int SendBufferSize = 64;
static int currentBufferPos = 0; // The current line to send
static int lastBufferAddition = -1; // The last position added to within the buffer
private static System.Timers.Timer CarouselTimer;
private static System.Timers.Timer SendBufferTimer;
const string FileName = "PortSelection.txt";
public static void Init()
{
Thread readThread = new Thread(Read);
SendBuffer = new string[SendBufferSize];
_serialPort = new SerialPort();
_serialPort.BaudRate = 9600;
SendBufferTimer = new System.Timers.Timer(610); // We tick at the same rate as the arduino. There may be clashing
// Due to timing differences, but so long as we always take longer than it takes to process data, we
// we will ensure data arrives correctly. Make sure this is delayed while serial gets set-up.
// Currently, as the carousel works on a 2 second timer, we can send at least 3 packets of data before
// a new one is routinely added.
SendBufferTimer.Elapsed += SendBufferTimer_Elapsed;
CarouselTimer = new System.Timers.Timer(2000);
CarouselTimer.Elapsed += CarouselTimer_Elapsed;
string[] AvailablePorts;
string s = System.Reflection.Assembly.GetExecutingAssembly().Location;
try
{
AvailablePorts = File.ReadAllText(s.Remove(s.LastIndexOf("\\")) + "\\" + FileName).Replace(Environment.NewLine, "\n").Split('\n');
}
catch
{
AvailablePorts = SerialPort.GetPortNames();
File.WriteAllLines(s.Remove(s.LastIndexOf("\\")) + "\\" + FileName, AvailablePorts);
}
bool[] removedPorts = new bool[AvailablePorts.Length];
for (int i = 0; i < AvailablePorts.Length; i++)
{
if (AvailablePorts[i].StartsWith("//"))
{
removedPorts[i] = true;
}
else
{
removedPorts[i] = false;
}
}
_serialPort.PortName = AvailablePorts[Array.IndexOf(removedPorts,false)];
try
{
_serialPort.Open();
LogManager.Write("Serial port opened successfully");
}
catch
{
LogManager.Write("Couldn't access " + _serialPort.PortName + ", loading first port as a default");
_serialPort.PortName = SerialPort.GetPortNames()[0];
_serialPort.Open();
}
_continue = true;
readThread.Start();
SendBufferTimer.Start();
Console.Write("Ready to write data to the port");
}
static bool SendBufferLock = false;
static int waitTicks = 0;
/// <summary>
/// Sends data, if there is any, at every timer tick. Allows a queue of commands
/// to be executed without clashing.
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private static void SendBufferTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
if(waitTicks > 5)
{
if (!SendBufferLock)
{
SendBufferLock = true;
if (SendBuffer[currentBufferPos] != null)
{
string s = SendBuffer[currentBufferPos].Trim();
if (s == "" || s == null)
{
}
else
{
LogManager.WriteSerial("\tOut: " + s);
_serialPort.WriteLine(s);
SendBuffer[currentBufferPos] = "";
if (currentBufferPos >= SendBufferSize - 1)
{
currentBufferPos = 0;
}
else
{
currentBufferPos++;
}
}
}
SendBufferLock = false;
}
}
else
{
waitTicks++;
}
}
static string currentIteration = "";
public static void SetRDSStationName(string setStationName, bool useCarousel = false, bool stopCarousel = false)
{
if (useCarousel)
{
LogManager.Write("Starting carousel...");
CarouselTimer.Stop();
if(setStationName.Last() != ' ') // Make sure there is a space between the first and last char
{
setStationName = setStationName + " ";
}
currentIteration = setStationName;
CarouselTimer.Start();
}
else
{
if (setStationName.Length < 9)
{
Write("RDSName" + setStationName);
}
else
{
Write("RDSName" + setStationName.Remove(8));
}
}
if (stopCarousel)
{
}
}
public static void SetRDSStationData(string data)
{
Write("RDSData" + data);
}
public static void SetFrequency(string Frequency)
{
string temp = Frequency.ToLower();
if (temp.Contains("mhz"))
{
temp = temp.Remove(temp.IndexOf("mhz"));
}
temp = temp.Replace(".", "");
temp = temp.Trim();
Write("StatFreq" + temp);
}
public static void SetTXPower(string power)
{
string s = power.Trim();
Write("TXpower" + s);
}
private static void CarouselTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
{
char one = currentIteration[0];
currentIteration = currentIteration.Remove(0, 1) + one;
SetRDSStationName(currentIteration);
}
/// <summary>
/// Adds the data to the write queue
/// </summary>
/// <param name="message"></param>
static void Write(string message)
{
if(message.Trim() != "")
{
lastBufferAddition = lastBufferAddition + 1;
if (lastBufferAddition > SendBufferSize -1)
{
lastBufferAddition = 0;
}
SendBuffer[lastBufferAddition] = message;
}
}
static void Read()
{
while (_continue)
{
try
{
string message = _serialPort.ReadLine();
LogManager.WriteSerial(message);
if (message == "beat")
{
// We recieved a heartbeat
}
else if (message.Trim() != "")
{
Console.WriteLine(message);
switch (message.Remove(message.IndexOf(":")))
{
case "Freq":
break;
case "TXPower":
break;
case "InLevel":
break;
case "ASQ":
break;
default:
break;
}
}
}
catch (TimeoutException) { }
}
}
public static bool carouselContinue = false;
public static void RDSStationNameCarousel(string StationName, SerialPort serialPort)
{
string originalName = StationName;
string currentIteration = originalName;
carouselContinue = true;
while (carouselContinue)
{
char one = currentIteration[0];
currentIteration = currentIteration.Remove(0, 1) + one;
if (currentIteration.Length < 9)
{
serialPort.WriteLine("RDSName" + currentIteration);
}
else
{
serialPort.WriteLine("RDSName" + currentIteration.Remove(8));
}
Thread.Sleep(1000);
}
}
}
}