Display text on LCD displays (even on multiple ones). Allow to create windows (frames) on display, and to combine them (split, add, duplicate, scroll). See http://mbed.org/users/hlipka/notebook/lcdwindow/ for more information.

Dependents:   Mbell

Files at this revision

API Documentation at this revision

Comitter:
hlipka
Date:
Sun Nov 28 22:09:54 2010 +0000
Parent:
2:5ac5bab7daaf
Child:
4:aa08e82834dc
Commit message:
Made LCD driver thread safe (to allow usage from timers)

Changed in this revision

dogm_spi.cpp Show annotated file Show diff for this revision Revisions of this file
dogm_spi.h Show annotated file Show diff for this revision Revisions of this file
hd44780_8bit.cpp Show annotated file Show diff for this revision Revisions of this file
ks0108_8bit.cpp Show annotated file Show diff for this revision Revisions of this file
lcd.h Show annotated file Show diff for this revision Revisions of this file
multiwindow.cpp Show annotated file Show diff for this revision Revisions of this file
semaphore.cpp Show annotated file Show diff for this revision Revisions of this file
semaphore.h Show annotated file Show diff for this revision Revisions of this file
subwindow.cpp Show annotated file Show diff for this revision Revisions of this file
teewindow.cpp Show annotated file Show diff for this revision Revisions of this file
terminal.cpp Show annotated file Show diff for this revision Revisions of this file
window.cpp Show annotated file Show diff for this revision Revisions of this file
window.h Show annotated file Show diff for this revision Revisions of this file
--- a/dogm_spi.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/dogm_spi.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -50,15 +50,18 @@
 void DogmLCDSPI::character(int column, int row, int c)
 {
     int address=(row)*0x40+(column);
+    _guard->take();
     sendCmd((char)address|0x80);
     wait_ms(1);
     sendData(c);
+    _guard->release();
     wait_ms(1);
 }
 
 void DogmLCDSPI::writeText(const unsigned int column, const unsigned int row, const char text[])
 {
     int address=(row)*0x40+(column);
+    _guard->take();
     sendCmd((char)address|0x80);
     wait_ms(1);
     
@@ -69,10 +72,13 @@
         wait_ms(1);
         i++;
     }
+    _guard->release();
 }
 
 void DogmLCDSPI::clear()
 {
+    _guard->take();
     sendCmd(1);
+    _guard->release();
 }
 
--- a/dogm_spi.h	Sat Nov 27 22:54:13 2010 +0000
+++ b/dogm_spi.h	Sun Nov 28 22:09:54 2010 +0000
@@ -1,17 +1,17 @@
 /*
  * mbed LCDWindow library
 * Copyright (c) 2010 Hendrik Lipka
-* 
+*
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
-* 
+*
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
-* 
+*
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
@@ -28,28 +28,27 @@
 
 #include "DigitalOut.h"
 #include "SPI.h"
+#include "semaphore.h"
 
-using namespace mbed; 
+using namespace mbed;
 
 /**
  * class for connecting a DOGM16x LCD display, from electronic assembly (www.lcd-module.com )
 */
-class DogmLCDSPI: public SPILCDBase
-{
-    public:
-        /**
-         * @param columns number of chars per line
-         * @param rows number of lines (currently only 1 and 2 work)
-         * @param the SPI object used for sending data (set to 1MHz)
-         * @param enable the pin name for the enable line (0=active, connected to /CSB)
-         * @param rs the pin name for the register select line (0=cmd, 1=data)
-        */
-        DogmLCDSPI(unsigned int columns, unsigned int rows, SPI *spi, PinName enable, PinName rs); 
-        virtual void init();
-        virtual void writeText(const unsigned int column, const unsigned int row, const char text[]);
-        virtual void clear();
-        virtual void character(int column, int row, int c);
-
+class DogmLCDSPI: public SPILCDBase {
+public:
+    /**
+     * @param columns number of chars per line
+     * @param rows number of lines (currently only 1 and 2 work)
+     * @param the SPI object used for sending data (set to 1MHz)
+     * @param enable the pin name for the enable line (0=active, connected to /CSB)
+     * @param rs the pin name for the register select line (0=cmd, 1=data)
+    */
+    DogmLCDSPI(unsigned int columns, unsigned int rows, SPI *spi, PinName enable, PinName rs);
+    virtual void init();
+    virtual void writeText(const unsigned int column, const unsigned int row, const char text[]);
+    virtual void clear();
+    virtual void character(int column, int row, int c);
 };
 
 #endif
\ No newline at end of file
--- a/hd44780_8bit.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/hd44780_8bit.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -30,9 +30,11 @@
 void HD44780LCD8bit::character(int column, int row, int c)
 {
     int address=(row)*0x40+(column);
+    _guard->take();
     sendCmd((unsigned char)address|0x80);
     wait_us(30);
     sendData(c);
+    _guard->release();
     wait_us(30);
 }
 
@@ -40,6 +42,7 @@
 void HD44780LCD8bit::writeText(const unsigned int column, const unsigned int row, const char text[]) {
 //    printf("print to %d,%d {%s}\n",line,pos,text);
     int address=row*0x40+column;
+    _guard->take();
     sendCmd((unsigned char)address|0x80);
     wait_us(30);
 
@@ -49,10 +52,13 @@
         wait_us(30);
         i++;
     }
+    _guard->release();
 }
 
 void HD44780LCD8bit::clear() {
+    _guard->take();
     sendCmd(1);
+    _guard->release();
 }
 
 void HD44780LCD8bit::sendCmd(const unsigned char cmd) {
--- a/ks0108_8bit.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/ks0108_8bit.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -39,9 +39,11 @@
 }
 
 void KS0108LCD8bit::clear() {
+    _guard->take();
     clearHalf(_left);
     if (NULL!=_right)
         clearHalf(_right);
+    _guard->release();
 }
 
 void KS0108LCD8bit::clearHalf(DigitalOut* cs) {
@@ -74,6 +76,7 @@
     if (NULL==cs)
         return;
     
+    _guard->take();
     sendCmd(0xb8|row,cs); // set x page    
 
     unsigned int y=icolumn*8;
@@ -85,6 +88,7 @@
         sendData(font_data[c][i],cs);
     }
     
+    _guard->release();
 }
 
 KS0108LCD8bit::KS0108LCD8bit
--- a/lcd.h	Sat Nov 27 22:54:13 2010 +0000
+++ b/lcd.h	Sun Nov 28 22:09:54 2010 +0000
@@ -42,9 +42,10 @@
     protected:
         const unsigned int _columns;
         const unsigned int _rows;
-        TextLCDBase(unsigned int columns, unsigned int rows):_columns(columns),_rows(rows)
+        TextLCDBase(unsigned int columns, unsigned int rows):Window(),_columns(columns),_rows(rows)
         {
-        } 
+        };
+        void test(){printf("x");};
 };
 
 #endif /*LCD_H_*/
--- a/multiwindow.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/multiwindow.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -23,7 +23,7 @@
 
 #include "multiwindow.h"
 
-MultiWindow::MultiWindow(vector<Window*> lcds) {
+MultiWindow::MultiWindow(vector<Window*> lcds):Window() {
     _lcds=lcds;
     int len=_lcds.size();
     _rows=0;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/semaphore.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -0,0 +1,39 @@
+/**
+ * code from Igor Skochinsky
+ * taken from http://mbed.org/forum/mbed/post/799/
+*/
+
+#include "semaphore.h"
+
+  Semaphore::Semaphore(): s(SemFree) {};
+  
+  bool Semaphore::take(bool block)
+  {
+    int oldval;
+#if defined(TARGET_LPC1768) // on Cortex-M3 we can use ldrex/strex
+    do {
+      // read the semaphore value
+      oldval = __ldrex(&s);
+      // loop again if it is locked and we are blocking
+      // or setting it with strex failed
+    }
+    while ( (block && oldval == SemTaken) || __strex(SemTaken, &s) != 0 );
+    if ( !block ) __clrex(); // clear exclusive lock set by ldrex
+#else // on arm7 there's only swp
+    do {
+      // swp sets the pointed data to the given value and returns the previous one
+      oldval = __swp(SemTaken, &s);
+      // if blocking, loop until the previous value becomes 0
+      // which would mean we have successfully taken the lock
+    }
+    while (block && oldval == SemTaken);
+#endif
+    return oldval == SemFree;
+  }
+  
+  // release the semaphore
+  void Semaphore::release()
+  {
+    s = SemFree;
+  }
+  
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/semaphore.h	Sun Nov 28 22:09:54 2010 +0000
@@ -0,0 +1,28 @@
+/**
+ * code from Igor Skochinsky
+ * taken from http://mbed.org/forum/mbed/post/799/
+*/
+
+#ifndef SEMAPHORE_H_
+#define SEMAPHORE_H_
+
+class Semaphore
+{
+public:
+  // constructor
+  Semaphore();
+  
+  // try to take the semaphore and return success
+  // by default block until succeeded
+  bool take(bool block = true);
+  // release the semaphore
+  void release();
+  
+ private:
+   enum { SemFree, SemTaken };
+  // semaphore value
+  int s;  
+
+};
+
+#endif
--- a/subwindow.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/subwindow.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -25,7 +25,8 @@
 
 #include "string.h"
 
-SubWindow::SubWindow(Window* lcd, const unsigned int columnOffset, const unsigned int rowOffset, const unsigned int columns, const unsigned int rows) {
+SubWindow::SubWindow(Window* lcd, const unsigned int columnOffset, const unsigned int rowOffset, const unsigned int columns, const unsigned int rows)
+:Window() {
     _lcd=lcd;
     _columnOffset=columnOffset;
     _rowOffset=rowOffset;
--- a/teewindow.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/teewindow.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -23,7 +23,7 @@
 
 #include "teewindow.h"
 
-TeeWindow::TeeWindow(vector<Window*> lcds) {
+TeeWindow::TeeWindow(vector<Window*> lcds):Window() {
     _lcds=lcds;
     int len=_lcds.size();
     _columns=_lcds[0]->getColumns();
--- a/terminal.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/terminal.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -24,7 +24,7 @@
 #include "terminal.h"
 #include "string.h"
 
-Terminal::Terminal(Window* window) {
+Terminal::Terminal(Window* window):Window() {
     _window=window;
     _columns=window->getColumns();
     _rows=window->getRows();
--- a/window.cpp	Sat Nov 27 22:54:13 2010 +0000
+++ b/window.cpp	Sun Nov 28 22:09:54 2010 +0000
@@ -47,4 +47,9 @@
         }
     }
     return value;
+}
+
+Window::Window()
+{
+    _guard=new Semaphore();
 }
\ No newline at end of file
--- a/window.h	Sat Nov 27 22:54:13 2010 +0000
+++ b/window.h	Sun Nov 28 22:09:54 2010 +0000
@@ -25,6 +25,7 @@
 #define WINDOW_H_
 
 #include "Stream.h"
+#include "semaphore.h"
 
 using namespace mbed;
 
@@ -55,7 +56,7 @@
     */
     virtual void clear()=0;
 
-    /** 
+    /**
     * set (internal) cursor to a screen column and row
     *
     * @param column  The horizontal position from the left, indexed from 0
@@ -74,7 +75,7 @@
     virtual void character(int column, int row, int c)=0;
 
 #if DOXYGEN_ONLY
-    /** 
+    /**
      * Write a character to the LCD, on the position specified by the cursor
      * sets the cursor to the next position, and wraps (from right to left, next line, and from bottom back to top)
      *
@@ -82,7 +83,7 @@
      */
     int putc(int c);
 
-    /** 
+    /**
      * Write a formated string to the LCD, on the position specified by the cursor
      * does wrap around (as specified by putc)
      *
@@ -92,6 +93,12 @@
     int printf(const char* format, ...);
 #endif
 protected:
+    /**
+     * base constructor
+     * initializes the _guard semaphore needed for syncing parallel writes
+    */
+    Window();
+
     // Stream implementation functions
     virtual int _putc(int value);
     virtual int _getc() {
@@ -100,6 +107,8 @@
 
     int _column;
     int _row;
+
+    Semaphore *_guard;
 };
 
 #endif /*WINDOW_H_*/