Allows users to seamlessly write to 2 or 3 uLCD screens as if they were one large screen.

Dependencies:   4DGL-uLCD-SE mbed-rtos mbed

Files at this revision

API Documentation at this revision

Comitter:
Mkuchnik3
Date:
Wed Mar 11 21:33:18 2015 +0000
Commit message:
First Commit

Changed in this revision

4DGL-uLCD-SE.lib Show annotated file Show diff for this revision Revisions of this file
BackgroundColor.cpp Show annotated file Show diff for this revision Revisions of this file
BackgroundColor.h Show annotated file Show diff for this revision Revisions of this file
BaudRate.cpp Show annotated file Show diff for this revision Revisions of this file
BaudRate.h Show annotated file Show diff for this revision Revisions of this file
Blit.cpp Show annotated file Show diff for this revision Revisions of this file
Blit.h Show annotated file Show diff for this revision Revisions of this file
ClearScreen.cpp Show annotated file Show diff for this revision Revisions of this file
ClearScreen.h Show annotated file Show diff for this revision Revisions of this file
Command.h Show annotated file Show diff for this revision Revisions of this file
DrawPixel.cpp Show annotated file Show diff for this revision Revisions of this file
DrawPixel.h Show annotated file Show diff for this revision Revisions of this file
Reset.cpp Show annotated file Show diff for this revision Revisions of this file
Reset.h Show annotated file Show diff for this revision Revisions of this file
ScreenUpdater.cpp Show annotated file Show diff for this revision Revisions of this file
ScreenUpdater.h Show annotated file Show diff for this revision Revisions of this file
VirtualScreen.h Show annotated file Show diff for this revision Revisions of this file
mbed-rtos.lib Show annotated file Show diff for this revision Revisions of this file
mbed.bld Show annotated file Show diff for this revision Revisions of this file
uLCD_Multiscreen.cpp Show annotated file Show diff for this revision Revisions of this file
uLCD_Multiscreen.h Show annotated file Show diff for this revision Revisions of this file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/4DGL-uLCD-SE.lib	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/Mkuchnik3/code/4DGL-uLCD-SE/#a2da7a7c517b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BackgroundColor.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,8 @@
+#include "BackgroundColor.h"
+#include "uLCD_4DGL.h"
+BackgroundColor::BackgroundColor(int color) {
+    this->color = color;
+}
+void BackgroundColor::execute(uLCD_4DGL* uLCD) {
+    uLCD->background_color(color);     
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BackgroundColor.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,12 @@
+#ifndef BACKGROUNDCOLOR_H
+#define BACKGROUNDCOLOR_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class BackgroundColor: public Command {
+    private:
+        int color;
+    public:
+        BackgroundColor(int color);
+        virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaudRate.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,8 @@
+#include "BaudRate.h"
+#include "uLCD_4DGL.h"
+BaudRate::BaudRate(int rate) {
+    this->rate = rate;
+}
+void BaudRate::execute(uLCD_4DGL* uLCD) {
+    uLCD->baudrate(rate);     
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/BaudRate.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,12 @@
+#ifndef BAUDRATE_H
+#define BAUDRATE_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class BaudRate: public Command {
+    private:
+        int rate;
+    public:
+        BaudRate(int rate);
+        virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Blit.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,14 @@
+#include "Blit.h"
+Blit::Blit(int x, int y, int w, int h, int *colors) {
+    this->x = x;
+    this->y = y;
+    this->w = w;
+    this->h = h;
+    this->colors = new int[w*h];
+    for (int i = 0; i < w*h; i++) {
+        this->colors[i] = colors[i];
+    }
+}
+void Blit::execute(uLCD_4DGL* uLCD) {
+    uLCD->BLIT(x,y,w,h,colors);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Blit.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,16 @@
+#ifndef BLIT_H
+#define BLIT_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class Blit: public Command {
+    private:
+        int x;
+        int y;
+        int w;
+        int h;
+        int *colors;
+    public:
+        Blit(int x, int y, int w, int h, int *colors);
+        virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ClearScreen.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,5 @@
+#include "ClearScreen.h"
+#include "uLCD_4DGL.h"
+void ClearScreen::execute(uLCD_4DGL* uLCD) {
+    uLCD->cls();     
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ClearScreen.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,8 @@
+#ifndef CLEARSCREEN_H
+#define CLEARSCREEN_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class ClearScreen: public Command {
+    virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Command.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,15 @@
+#ifndef COMMAND_H
+#define COMMAND_H
+#include "uLCD_4DGL.h"
+/**
+ * Class represents a uLCD command. 
+ */
+class Command {
+        public:
+        /**
+         * Executes the command on the target uLCD.
+         * @param uLCD the lcd to execute the command on.
+         */
+        virtual void execute(uLCD_4DGL* uLCD) = 0;
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DrawPixel.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,10 @@
+#include "DrawPixel.h"
+#include "uLCD_4DGL.h"
+DrawPixel::DrawPixel(int x, int y, int color) {
+    this->x = x;
+    this->y = y;
+    this->color = color;
+}
+void DrawPixel::execute(uLCD_4DGL* uLCD) {
+    uLCD->pixel(x,y,color);     
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/DrawPixel.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,14 @@
+#ifndef DRAWPIXEL_H
+#define DRAWPIXEL_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class DrawPixel: public Command {
+    private:
+        int x;
+        int y;
+        int color;
+    public:
+        DrawPixel(int x, int y, int color);
+        virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Reset.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,5 @@
+#include "Reset.h"
+#include "uLCD_4DGL.h"
+void Reset::execute(uLCD_4DGL* uLCD) {
+    uLCD->reset();     
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/Reset.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,8 @@
+#ifndef RESET_H
+#define RESET_H
+#include "Command.h"
+#include "uLCD_4DGL.h"
+class Reset: public Command {
+    virtual void execute(uLCD_4DGL* uLCD);
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ScreenUpdater.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,42 @@
+#include "ScreenUpdater.h"
+#include "uLCD_4DGL.h"
+#include "mbed.h"
+static void uLCD_thread_func(void const *args) {
+    //printf("Thread alive.");
+    uLCD_4DGL *lcd = ((uLCD_Thread_Args*)args)->uLCD;
+    std::queue<Command*> *commands = ((uLCD_Thread_Args*)args)->commands;
+    Mutex *commands_mutex = ((uLCD_Thread_Args*)args)->commands_mutex;
+    while (true) {
+        if (!commands->empty()) {
+            commands_mutex->lock();
+            Command *command = commands->front();
+            commands->pop();
+            command->execute(lcd);
+            delete command;
+            commands_mutex->unlock();
+        } else {
+            //printf("empty.");
+            Thread::signal_wait(0x1);
+        }
+    }
+}
+ScreenUpdater::ScreenUpdater(uLCD_4DGL *uLCD) {
+    //printf("ScreenUpdater booting.");
+    uLCD_Thread_Args args = {uLCD, &commands, &commands_mutex};
+    Thread *_thread = new Thread(uLCD_thread_func, &(args), osPriorityHigh);
+    uLCD_thread = _thread;
+    //printf("Thread creation complete\n");
+    this->uLCD = uLCD;
+}
+void ScreenUpdater::addCommand(Command* _command) {
+    //printf("I'm here!");
+    commands_mutex.lock();
+    commands.push(_command);    
+    //printf("Adding command %d. State %d\n", commands.size(), uLCD_thread->get_state());
+    commands_mutex.unlock();
+    uLCD_thread->signal_set(0x1);
+}
+ScreenUpdater::~ScreenUpdater() {
+    //printf("KILLING THREAD!!!!!!!!!!!!!!\n");
+    uLCD_thread->terminate();
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/ScreenUpdater.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,35 @@
+#ifndef SCREENUPDATER_H
+#define SCREENUPDATER_H
+#include <queue>
+#include "rtos.h"
+#include "uLCD_4DGL.h"
+#include "Command.h"
+/**
+ * Attaches a thread to a physical screen and makes it operate on all input instructions.
+ */
+class ScreenUpdater {
+    private:
+        uLCD_4DGL *uLCD;
+        Thread *uLCD_thread;
+        std::queue<Command*> commands;
+        Mutex commands_mutex;
+    public:
+        /**
+         * Attaches an LCD to the updater.
+         */
+        ScreenUpdater(uLCD_4DGL *uLCD);
+        /**
+         * Add a command to the queue.
+         */
+        void addCommand(Command *_command);
+        /**
+         * Destructor. 
+         */
+        ~ScreenUpdater();
+};
+typedef struct uLCD_Thread_Args {
+    uLCD_4DGL* uLCD;
+    std::queue<Command*>* commands;
+    Mutex* commands_mutex;
+} uLCD_Thread_Args;
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/VirtualScreen.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,120 @@
+#ifndef VIRTUALSCREEN_H
+#define VIRTUALSCREEN_H
+#include "ScreenUpdater.h"
+#include "Command.h"
+#include "DrawPixel.h"
+#include "ClearScreen.h"
+#include "BackgroundColor.h"
+#include "Reset.h"
+#include "BaudRate.h"
+#include "Blit.h"
+#include "mbed.h"
+/**
+ * Class represents a virtual screen of arbitrary size. To keep simplicity, screen data should be kept
+ * in a pixel format where it can be read by physical devices.
+ */
+template <class pixelType, class screenType>
+class VirtualScreen {
+    private:
+        std::vector<screenType*> screens;
+        std::vector<ScreenUpdater*> updaters; 
+        int rows;
+        int columns;
+        int screenSize;
+    public:
+        /**
+         * Creates a virtual screen of size rows * columns. This screen is partitioned into different physical
+         * screens. Writing pixels into this screen will transparently write into
+         * these separate screens.
+         *
+         * @param screens A vector of physical screens to be used for drawing on.
+         * @param rows The number of rows in the virtual screen.
+         * @param columns The number of columns in the virtual screen. 
+         */
+        VirtualScreen<pixelType, screenType>(std::vector<screenType*> screens, int rows, int columns) {
+            printf("Virtual Screen Booting.");
+            this->screens = screens;
+            for (typename std::vector<screenType*>::iterator scr_iter = screens.begin(); scr_iter != screens.end(); scr_iter++) {
+                ScreenUpdater *updater = new ScreenUpdater(*scr_iter);
+                updaters.push_back(updater);
+            }    
+            this->rows = rows;
+            this->columns = columns;
+            this->screenSize = 128;
+        }
+        
+        ~VirtualScreen<pixelType, screenType>() {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                delete (*updater_iter);
+            }
+        }
+        
+        /**
+         * Writes a pixel value into the virtual screen at (row, column) index.
+         *
+         * @param x The row to write the pixel to.
+         * @param y The column to write the pixel to.
+         * @param value The value to write to the pixel.
+         */
+        void setPixel(int x, int y, pixelType value) {
+            //printf("Set pixel on row %d, col %d, val %d\n", x, y, value);
+            int screen_number = x / screenSize; 
+            int x_pixel = x % screenSize; 
+            //printf("Predicting screen %d, at col %d\n", screen_number, x_pixel);
+            ScreenUpdater* updater = updaters.at(screen_number); 
+            //printf("Updater made.\n"); 
+            Command *command = new DrawPixel(x_pixel, y, value); 
+           //printf("Adding command.\n");
+            updater->addCommand(command); 
+        }
+        /**
+         * Clears the screens of all attached screens.
+         */
+        void clearScreen() {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                Command* command = new ClearScreen(); 
+                (*updater_iter)->addCommand(command);
+            }
+        }
+        /**
+         * Resets the screens of all attached screens.
+         */
+        void resetScreen() {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                Command* command = new Reset(); 
+                (*updater_iter)->addCommand(command);
+            }
+        }
+        /**
+         * Sets the baud rate for all screens.
+         *
+         * @param rate The desired baud rate.
+         */
+        void setBaudRate(int rate) {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                Command* command = new BaudRate(rate); 
+                (*updater_iter)->addCommand(command);
+            }
+        }
+        /**
+         * draw a block of pixels
+         */
+        void BLIT(int x, int y, int w, int h, int *colors) {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                Command* command = new Blit(x,y,w,h,colors); 
+                (*updater_iter)->addCommand(command);
+            }
+        }
+        /**
+         * Sets the background color for all screens.
+         *
+         * @param color The color of the desired background.
+         */
+        void background_color(int color) {
+            for (typename std::vector<ScreenUpdater*>::iterator updater_iter = updaters.begin(); updater_iter != updaters.end(); updater_iter++) {
+                Command* command = new BackgroundColor(color); 
+                (*updater_iter)->addCommand(command);
+            }
+        }
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed-rtos.lib	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,1 @@
+http://developer.mbed.org/users/Mkuchnik3/code/mbed-rtos/#8b4ab67d92b2
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/7e07b6fb45cf
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uLCD_Multiscreen.cpp	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,121 @@
+#include "uLCD_Multiscreen.h"
+#include "mbed.h"
+uLCD_Multiscreen::uLCD_Multiscreen(vector<uLCD_4DGL*> screens) : virtualScreen(screens, 128, 128 * screens.size())
+{
+    printf("Multiscreen Booting.");
+}
+
+void uLCD_Multiscreen::unfilledRectangle(int x, int y, int w, int h, int color)
+{
+    for(int i = x; i <= x + w; i++) {
+        virtualScreen.setPixel(i, y, color);
+    }
+    for(int i = x; i <= x + w; i++) {
+        virtualScreen.setPixel(i, y + h, color);
+    }
+    
+    for(int i = y; i <= y + h; i++) {
+        virtualScreen.setPixel(x, i, color);
+    }
+    for(int i = y; i <= y + h; i++) {
+        virtualScreen.setPixel(x + w, i, color);
+    }
+
+}
+
+void uLCD_Multiscreen::drawLine(int x1, int y1, int  x2, int  y2, int color)
+{
+    int delta_x(x2 - x1);
+    // if x1 == x2, then it does not matter what we set here
+    signed char const ix((delta_x > 0) - (delta_x < 0));
+    delta_x = std::abs(delta_x) << 1;
+ 
+    int delta_y(y2 - y1);
+    // if y1 == y2, then it does not matter what we set here
+    signed char const iy((delta_y > 0) - (delta_y < 0));
+    delta_y = std::abs(delta_y) << 1;
+ 
+    virtualScreen.setPixel(x1, y1, color);
+ 
+    if (delta_x >= delta_y)
+    {
+        // error may go below zero
+        int error(delta_y - (delta_x >> 1));
+ 
+        while (x1 != x2)
+        {
+            if ((error >= 0) && (error || (ix > 0)))
+            {
+                error -= delta_x;
+                y1 += iy;
+            }
+            // else do nothing
+ 
+            error += delta_y;
+            x1 += ix;
+ 
+            virtualScreen.setPixel(x1, y1, color);
+        }
+    }
+    else
+    {
+        // error may go below zero
+        int error(delta_x - (delta_y >> 1));
+ 
+        while (y1 != y2)
+        {
+            if ((error >= 0) && (error || (iy > 0)))
+            {
+                error -= delta_y;
+                x1 += ix;
+            }
+            // else do nothing
+ 
+            error += delta_x;
+            y1 += iy;
+ 
+            virtualScreen.setPixel(x1, y1, color);
+        }
+    }
+}
+
+void uLCD_Multiscreen::unfilledCircle(int x0, int y0, int radius, int color)
+{
+    int x = radius;
+  int y = 0;
+  int radiusError = 1-x;
+ 
+  while(x >= y)
+  {
+    virtualScreen.setPixel(x + x0, y + y0, color);
+    virtualScreen.setPixel(y + x0, x + y0, color);
+    virtualScreen.setPixel(-x + x0, y + y0, color);
+    virtualScreen.setPixel(-y + x0, x + y0, color);
+    virtualScreen.setPixel(-x + x0, -y + y0, color);
+    virtualScreen.setPixel(-y + x0, -x + y0, color);
+    virtualScreen.setPixel(x + x0, -y + y0, color);
+    virtualScreen.setPixel(y + x0, -x + y0, color);
+    y++;
+    if (radiusError<0)
+    {
+      radiusError += 2 * y + 1;
+    }
+    else
+    {
+      x--;
+      radiusError += 2 * (y - x) + 1;
+    }
+  }
+}
+
+void uLCD_Multiscreen::cls() {
+    virtualScreen.clearScreen();
+}
+
+
+void uLCD_Multiscreen::changeBackground(int color) {
+    virtualScreen.background_color(color);
+}
+void uLCD_Multiscreen::setBaudRate(int rate) {
+    virtualScreen.setBaudRate(rate);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/uLCD_Multiscreen.h	Wed Mar 11 21:33:18 2015 +0000
@@ -0,0 +1,44 @@
+#ifndef ULCD_MULTISCREEN_H
+#define ULCD_MULTISCREEN_H
+#include "VirtualScreen.h"
+#include "uLCD_4DGL.h"
+/**
+ * CLass represents an interface for seemlessly writing to multiple uLCD screens
+ * in parallel.
+ */
+class uLCD_Multiscreen {
+    private:
+        VirtualScreen<int, uLCD_4DGL> virtualScreen;
+        int screen_count;
+    public:
+        /**
+         * Makes a Multiscreen interface.
+         * @param screens Pointer to physical screens oriented from left to right in the vector.
+         */
+        uLCD_Multiscreen(vector<uLCD_4DGL*> screens);
+        /**
+         * Clears screen.
+         */
+        void cls();
+        /**
+         * Makes an unfilled rectangle.
+         */
+        void unfilledRectangle(int x, int y, int w, int h, int color);
+        /**
+         * Draws a line.
+         */
+        void drawLine(int x1,int y1,int  x2, int  y2, int color);
+        /**
+         * Draws an unfilled circle.
+         */
+        void unfilledCircle(int x0, int y0, int radius, int color);
+        /**
+         * Changes the background of the LCDs.
+         */
+        void changeBackground(int color);
+        /**
+         * Sets the baud rate for all screens. It is recommended to set this high.
+         */
+        void setBaudRate(int rate);
+};
+#endif