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
Revision 0:15002a72309b, committed 2015-03-11
- Comitter:
- Mkuchnik3
- Date:
- Wed Mar 11 21:33:18 2015 +0000
- Commit message:
- First Commit
Changed in this revision
diff -r 000000000000 -r 15002a72309b 4DGL-uLCD-SE.lib --- /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
diff -r 000000000000 -r 15002a72309b BackgroundColor.cpp --- /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); +}
diff -r 000000000000 -r 15002a72309b BackgroundColor.h --- /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
diff -r 000000000000 -r 15002a72309b BaudRate.cpp --- /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); +}
diff -r 000000000000 -r 15002a72309b BaudRate.h --- /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
diff -r 000000000000 -r 15002a72309b Blit.cpp --- /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); +}
diff -r 000000000000 -r 15002a72309b Blit.h --- /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
diff -r 000000000000 -r 15002a72309b ClearScreen.cpp --- /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(); +}
diff -r 000000000000 -r 15002a72309b ClearScreen.h --- /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
diff -r 000000000000 -r 15002a72309b Command.h --- /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
diff -r 000000000000 -r 15002a72309b DrawPixel.cpp --- /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); +}
diff -r 000000000000 -r 15002a72309b DrawPixel.h --- /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
diff -r 000000000000 -r 15002a72309b Reset.cpp --- /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(); +}
diff -r 000000000000 -r 15002a72309b Reset.h --- /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
diff -r 000000000000 -r 15002a72309b ScreenUpdater.cpp --- /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(); +}
diff -r 000000000000 -r 15002a72309b ScreenUpdater.h --- /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
diff -r 000000000000 -r 15002a72309b VirtualScreen.h --- /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
diff -r 000000000000 -r 15002a72309b mbed-rtos.lib --- /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
diff -r 000000000000 -r 15002a72309b mbed.bld --- /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
diff -r 000000000000 -r 15002a72309b uLCD_Multiscreen.cpp --- /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); +}
diff -r 000000000000 -r 15002a72309b uLCD_Multiscreen.h --- /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