top of page

C# Twentyfirst Century EtchSketch

This was my final project for my embedded C#/C++ course. I designed a game controller using a Netduino and external USB serial port for an Etch-A-Sketch type Windows application using Visual Studio. This project is a fun example of the unique nature of this Electronics and Computer Engineering Technlogy program, in that it incorportates circuit design, prototyping, and coding.

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
using System.Threading;

/* Etch A Sketch type game that is controlled by a Netduino 3 Wifi
 * through a USB module.
 * Written by Sarah Busch, December 2015
 * for ELEX231 final exam
 * */

namespace etchSketch
{
    public partial class etchSketchForm : Form
    {
        ////////////////////////////
        // Set up safe Threading  //
        ////////////////////////////

        //This delegate enables asynchronous calls for setting
        //the text property on a TextBox control.
        delegate void SetTextCallBack(string text);

        //This thread is used to demonstrate both thread-safe and
        //unsafe ways to call a Windows Forms control.
        private Thread demoThread = null;

        string packet;

        private void ThreadProcSafe()
        {
            this.SetText(packet);
        }

        private void SetText(string text)
        {
            //InvokeRequired required compares the thread ID of the 
            //calling thread to the thread ID of the creating thread.
            //If these threads are different, it returns true.
            if (this.readPacket.InvokeRequired)
            {
                SetTextCallBack d = new SetTextCallBack(SetText);
                this.Invoke(d, new object[] { text });
            }
            else
            {
                this.readPacket.Text = "";
                this.readPacket.Text += text;
                parsePacket();
            }
        }

        ////////////////////////////////////////////
        // Establish communication with Netduino  //
        ////////////////////////////////////////////

        public etchSketchForm()
        {
            InitializeComponent();
            String[] ports = SerialPort.GetPortNames(); //find available ports
            commPort.Items.AddRange(ports); //and display them in dropdown menu
        }

        private void commPort_SelectedIndexChanged(object sender, EventArgs e)
        {
            serialPort1.PortName = commPort.Text; //default is COM4, drop down menu shows other available options
            openButton.Enabled = true;
        }       

        private void etchSketchForm_Load(object sender, EventArgs e)
        {
            openComm(); //opens communication with netduino on form load
        }
        
        private void openButton_Click(object sender, EventArgs e)
        {
            openComm(); //if comm is closed this button is activated so it can be reopened
        }

        private void openComm()
        {
            serialPort1.PortName = commPort.Text;
            serialPort1.BaudRate = 115200; //matches firmware on netduino
            serialPort1.Open();
            openButton.Enabled = false;
            closeButton.Enabled = true;
            serialPort1.Write(sendPacket.Text);
        }

        private void closeButton_Click(object sender, EventArgs e)
        {
            serialPort1.Close();
            openButton.Enabled = true;
            closeButton.Enabled = false;
        }

        private void viewDebugPanelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            debugPanel.Visible = true; //menu item makes debug panel visible
        }

        private void hideDebugPanelToolStripMenuItem_Click(object sender, EventArgs e)
        {
            debugPanel.Visible = false; //menu item hides debug panel
        }

        ///////////////////////////////////
        // Receive packet from Netduino  //
        ///////////////////////////////////

        //etchSketch variables
        Point startPoint = new Point();
        Point endPoint = new Point();
        bool drawFlag = false;
        string redLed;
        string startStopBtn;
        string greenLed;
        string shakeBtn;
        string colourBtn;
        string R;
        string G;
        string B;
        int penColour = 0;

        private void serialPort1_DataReceived(object sender, SerialDataReceivedEventArgs e)
        {
            packet = serialPort1.ReadLine();

            this.demoThread =
                new Thread(new ThreadStart(this.ThreadProcSafe));
            this.demoThread.Start();
        }

        private void parsePacket()
        {
            boxPacket.Text = packet.Substring(3, 3); //packet #

            boxA0.Text = packet.Substring(6, 4); //left pot
            boxA1.Text = packet.Substring(10, 4);
            boxA2.Text = packet.Substring(14, 4);
            boxA3.Text = packet.Substring(18, 4);
            boxA4.Text = packet.Substring(22, 4);
            boxA5.Text = packet.Substring(26, 4); //right pot

            boxButton.Text = packet.Substring(30 ,1); //onboard button

            boxD7.Text = packet.Substring(31, 1); //redLed
            boxD6.Text = packet.Substring(32, 1); //startStopBtn
            boxD5.Text = packet.Substring(33, 1); //greenLed
            boxD4.Text = packet.Substring(34, 1); //shakeBtn
            boxD3.Text = packet.Substring(35, 1); //colourBtn
            boxD2.Text = packet.Substring(36, 1); //R
            boxD1.Text = packet.Substring(37, 1); //G
            boxD0.Text = packet.Substring(38, 1); //B

            //assign parsed packet values to etchSketch variables
            redLed = boxD7.Text; 
            startStopBtn = boxD6.Text; 
            greenLed = boxD5.Text; 
            shakeBtn = boxD4.Text; 
            colourBtn = boxD3.Text; 
            R = boxD2.Text; 
            G = boxD1.Text; 
            B = boxD0.Text; 
        }

        ////////////////////
        // Game controls  //
        ////////////////////        

        private void etchSketch() //creates graphics in response to controller
        {
            Graphics line = drawingPanel.CreateGraphics(); //drawing area is limited to the drawing panel

            if (drawFlag == true)
            {
                endPoint = getPotValues();
                
                if (penColour == 1)
                {
                    Pen pen = new Pen(Brushes.Green);
                    pen.Width = 5;
                    line.DrawLine(pen, startPoint, endPoint);
                }
                else if (penColour == 2)
                {
                    Pen pen = new Pen(Brushes.Blue);
                    pen.Width = 5;
                    line.DrawLine(pen, startPoint, endPoint);
                }
                else if (penColour == 3)
                {
                    Pen pen = new Pen(Brushes.DarkViolet);
                    pen.Width = 5;
                    line.DrawLine(pen, startPoint, endPoint);
                }
                else
                {
                    Pen pen = new Pen(Brushes.Red);
                    pen.Width = 5;
                    line.DrawLine(pen, startPoint, endPoint);
                }

                startPoint = endPoint;
            }
        }            

        private void boxD6_TextChanged(object sender, EventArgs e)
        {
            //drawBtn toggles start and stop drawing
            parsePacket();

            if (startStopBtn == "1") //buton pressed
            {
                if (redLed == "1") //drwing enabled
                {
                    greenLed = "1";
                    redLed = "0";
                    drawFlag = true;
                    startPoint = getPotValues();
                }
                else //drawing disabled
                {
                    greenLed = "0";
                    redLed = "1";
                    drawFlag = false;
                }

                txData(); //send data to netduino
            }
        }
        
        private Point getPotValues() //pots control drawing coordinates
        {
            Point point = new Point(0,0);
            
            point.X = Int32.Parse(boxA0.Text);
            point.Y = Int32.Parse(boxA5.Text);

            point.X /= 12; //to keep the lines in the drawingPanel
            point.Y /= 12;

            point.X += 10;
            point.Y += 10;
            
            pointBox.Text = point.ToString(); //display point in debug window
            return point;
        }

        private void boxA0_TextChanged(object sender, EventArgs e)
        {
            etchSketch(); //when the pots are turned add to drawing
        }

        private void boxA5_TextChanged(object sender, EventArgs e)
        {
            etchSketch(); //when the pots are turned add to drawing
        }

        private void boxD4_TextChanged(object sender, EventArgs e)
        {
            //shakeBtn erases drawing
            parsePacket();

            if (shakeBtn == "1")
            {
                this.Refresh();
                txData();
            }
        }

        private void boxD3_TextChanged(object sender, EventArgs e)
        {
            //colourBtn toggle pen colours
            if (colourBtn == "1")
            {
                switch(penColour)
                {
                    case 0: 
                        penColour = 1;  //green                    
                        R = "1";
                        G = "0";
                        B = "1";
                        break;
                    case 1: 
                        penColour = 2;  //blue
                        R = "1";
                        G = "1";
                        B = "0";
                        break;
                    case 2: 
                        penColour = 3; //purple                       
                        R = "0";
                        G = "1";
                        B = "0";
                        break;
                    case 3: 
                        penColour = 0;  //red
                        R = "0";
                        G = "1";
                        B = "1";
                        break; 
                    default: 
                        penColour = 0;  //red
                        break;
                }
                txData();
            }
        }

        private void txData() //send packet to netduino
        {
            int chkSum = 0;
            string dataOut = "###" + redLed + startStopBtn + greenLed + shakeBtn + colourBtn + R + G + B;
            //add bytes to checksum code
            for (int i = 3; i < 11; i++) //does not include ###
            {
                chkSum += (int)dataOut[i];
            }
            dataOut += chkSum.ToString("d3"); //three chars
            sendPacket.Text = dataOut;
            serialPort1.Write(sendPacket.Text);
        }

    }
}
 

bottom of page