Anyone want to give me some pointers on what I might try to clean up my memory usage? I am pretty sure there’s something I’m doing in the use of the first class that’s causing me to not dereference strings and they linger through GC’s, but I can’t spot it…
Sorry about the huge code posting and very wide question :naughty:
namespace Poundy.Devices
{
public class EMIC2
{
private static SerialPort emic;
private static byte[] readBuf = new byte[1];
public EMIC2()
{
emic = new SerialPort("com1", 9600, Parity.None, 8, StopBits.One);
setupEmic();
}
public EMIC2(string portname)
{
emic = new SerialPort(portname, 9600, Parity.None, 8, StopBits.One);
setupEmic();
}
private void setupEmic()
{
// emic.ReadTimeout = Timeout.Infinite;
// emic.WriteTimeout = Timeout.Infinite;
emic.ReadTimeout = 500;
emic.WriteTimeout = 500;
try
{
emic.Open();
}
catch
{
throw new Exception("Unhandled failure to open serial port");
}
}
public bool isConnected()
{
if (emic != null)
{
return true;
}
else
return false;
}
public bool isReady()
{
if (emic != null)
{
// wait for serial ":" or send CR and get ":" back
return true;
}
else
return false;
}
public bool Say(string sentence)
{
if (this.isConnected())
{
while (sentence.Length > 1020)
{
string sub;
sub = sentence.Substring(0, 1020);
sendString(sub);
sentence = sentence.Substring(1021, sentence.Length - 1020);
}
sendString("S" + sentence);
Debug.GC(true);
return true;
}
else
return false;
}
public void changeVoice(int voice)
{
if (this.isConnected())
{
//send N
//wait for ":"
if (voice > 8)
voice = 8;
else if (voice < 0)
voice = 0;
string buffer = "N" + voice.ToString();
sendString(buffer);
}
}
public void changeLanguage(int lang)
{
if (this.isConnected())
{
//send L
//wait for ":"
if (lang > 2)
lang = 2;
else if (lang < 0)
lang = 0;
string buffer = "L" + lang.ToString();
sendString(buffer);
}
}
public void changeVolume(int volume)
{
if (this.isConnected())
{
//send V
//wait for ":"
if (volume > 18)
volume = 18;
else if (volume < -48)
volume = -48;
string buffer = "V" + volume.ToString();
sendString(buffer);
}
}
public void changeSpeed(int speed)
{
if (this.isConnected())
{
//send W
//wait for ":"
if (speed > 600)
speed = 600;
else if (speed < 75)
speed = 75;
string buffer = "W" + speed.ToString();
sendString(buffer);
}
}
public void changeParser(int parser)
{
if (this.isConnected())
{
//send P
if (parser != 0 || parser != 1)
parser = 1;
string buffer = "P" + parser.ToString();
sendString(buffer);
}
}
private bool sendString(string str)
{
string buffer = str + "\r\n";
Debug.Print("Sending:");
Debug.Print(buffer);
emic.Write(UTF8Encoding.UTF8.GetBytes(buffer), 0, buffer.Length);
// wait for the ":" after processing the instruction
bool returnVal = ReadLine(emic, (int)':');
Debug.GC(true);
if (returnVal == true)
Debug.Print("readval True ");
else
Debug.Print("readval false");
return returnVal;
}
public static bool ReadLine(SerialPort port, int delim = 10)
{
//CR 13 LF 10 = "\r\n"
bool keepGoing = true;
int curPos = 0;
readBuf[curPos] = 0;
int read = 0;
while (keepGoing && readBuf[curPos] != delim)
{
read = port.Read(readBuf, curPos, 1);
if (read > 0)
{
Debug.Print("Read= " + (char)readBuf[curPos]);
if (readBuf[curPos] == delim)
{
// we got a delimeter; it might only be in a stream of chars, so try a read-ahead
keepGoing = false;
read = port.Read(readBuf, curPos, 1);
if (read != 0)
{
// if we read a character here, the timeout didn't come into play, therefore the delimeter we picked up was not the terminator and we have to keep reading the serial port
Debug.Print("Read_ = " + (char)readBuf[curPos]);
keepGoing = true;
}
}
}
}
Debug.GC(true);
if (readBuf[curPos] == delim)
return true;
else
return false;
}
}
}
public partial class Program
{
Font f = Resources.GetFont(Resources.FontResources.NinaB);
EMIC2 myEmic;
GT.Timer timer = new GT.Timer(1000);
static bool RoastState;
static DateTime RoastStart;
static DateTime RoastEnd;
static DateTime Roast;
static TimeSpan Duration;
static string MyTimer;
GT.Socket MultiIO;
InterruptPort btn1_Engage_Rly;
InputPort btn2_StartStop;
InputPort btn3_Event;
OutputPort btn1_Rly_Control;
// This method is run when the mainboard is powered up or reset.
void ProgramStarted()
{
/*******************************************************************************************
Modules added in the Program.gadgeteer designer view are used by typing
their name followed by a period, e.g. button. or camera.
Many modules generate useful events. Type +=<tab><tab> to add a handler to an event, e.g.:
button.ButtonPressed +=<tab><tab>
If you want to do something periodically, use a GT.Timer and handle its Tick event, e.g.:
GT.Timer timer = new GT.Timer(1000); // every second (1000ms)
timer.Tick +=<tab><tab>
timer.Start();
*******************************************************************************************/
Utility.SetLocalTime(new DateTime(2013, 11, 17, 12, 00, 00));
timer.Tick += timer_Tick;
timer.Start();
joystick.JoystickPressed += joystick_JoystickPressed;
myEmic = new EMIC2("com2");
myEmic.changeVolume(12);
myEmic.changeVolume(13);
myEmic.changeVoice(3);
disp.SimpleGraphics.DisplayTextInRectangle("Coffee Roaster Control", 0,0,disp.Width,40, GT.Color.Red, f, GTM.Module.DisplayModule.SimpleGraphicsInterface.TextAlign.Center, GTM.Module.DisplayModule.SimpleGraphicsInterface.WordWrap.Wrap, GTM.Module.DisplayModule.SimpleGraphicsInterface.Trimming.WordEllipsis, GTM.Module.DisplayModule.SimpleGraphicsInterface.ScaleText.None);
MultiIO = GT.Socket.GetSocket(7, true, null, "Multi");
btn1_Engage_Rly = new InterruptPort(MultiIO.ReservePin(Gadgeteer.Socket.Pin.Three, null), true, Port.ResistorMode.PullUp, Port.InterruptMode.InterruptEdgeLow);
btn2_StartStop = new InputPort(MultiIO.ReservePin(Gadgeteer.Socket.Pin.Four, null), false, Port.ResistorMode.PullUp);
btn3_Event = new InputPort(MultiIO.ReservePin(Gadgeteer.Socket.Pin.Five, null), false, Port.ResistorMode.PullUp);
btn1_Rly_Control = new OutputPort(MultiIO.ReservePin(Gadgeteer.Socket.Pin.Eight, null), false);
btn1_Engage_Rly.OnInterrupt += btn1_Engage_Rly_OnInterrupt;
Debug.Print("Program Started");
}
void btn1_Engage_Rly_OnInterrupt(uint data1, uint data2, DateTime time)
{
if (RoastState == false)
{
Debug.Print("Roast Starting " + DateTime.Now.ToString());
RoastState = true;
RoastStart = DateTime.Now;
disp.Clear();
myEmic.Say("Starting roast");
Debug.GC(true);
}
else
{
Debug.Print("Roast Ending " + DateTime.Now.ToString());
RoastState = false;
RoastEnd = DateTime.Now;
myEmic.Say("Roast done");
Duration = RoastEnd - RoastStart;
myEmic.Say("Roast took " + Duration.Minutes.ToString() + " minutes and " + Duration.Seconds.ToString() + " seconds");
Debug.GC(true);
}
}
void joystick_JoystickPressed(Joystick sender, Joystick.JoystickState state)
{
Debug.Print("Joystick pressed - nothing happens here !");
}
void timer_Tick(GT.Timer timer)
{
PulseDebugLED();
if (RoastState == true)
{
Duration = DateTime.Now - RoastStart;
if (Duration.Minutes<10)
MyTimer="0"+Duration.Minutes.ToString();
else
MyTimer=Duration.Minutes.ToString();
if (Duration.Seconds<10)
MyTimer+=":0"+Duration.Seconds.ToString();
else
MyTimer+=":"+Duration.Seconds.ToString();
if (Duration.Seconds == 0 && Duration.Minutes>0)
{
myEmic.Say(Duration.Minutes.ToString() + " mins");
}
Debug.Print("Dur: " + MyTimer);
disp.SimpleGraphics.DisplayRectangle(GT.Color.DarkGray, 2, GT.Color.Black, 0, 40, disp.Width, 60);
disp.SimpleGraphics.DisplayTextInRectangle(MyTimer, 0, 40, disp.Width, 60, GT.Color.Blue, f, GTM.Module.DisplayModule.SimpleGraphicsInterface.TextAlign.Center, GTM.Module.DisplayModule.SimpleGraphicsInterface.WordWrap.Wrap, GTM.Module.DisplayModule.SimpleGraphicsInterface.Trimming.CharacterEllipsis, GTM.Module.DisplayModule.SimpleGraphicsInterface.ScaleText.None);
}
Debug.GC(true);
}
}
}