261 lines
9.3 KiB
C#
261 lines
9.3 KiB
C#
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);
|
|
}
|
|
}
|
|
}
|
|
}
|