Matt Lesslaw / Mbed 2 deprecated ST7066U_demo

Dependencies:   mbed

Files at this revision

API Documentation at this revision

Comitter:
lawless
Date:
Mon Jul 09 22:59:06 2012 +0000
Commit message:

Changed in this revision

main.cpp 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
diff -r 000000000000 -r a6f66204f651 main.cpp
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Mon Jul 09 22:59:06 2012 +0000
@@ -0,0 +1,318 @@
+/*
+ 
+ Derived from http://mbed.org/users/JohnSchooling/programs/pwm_trinary_count_01/m9rhax
+ 
+ 
+ * mbed demo:
+ * Software PWM on the mbed LEDs.  Counting in trinary using off, half bright and full on LEDs.
+ * Smooth scrolling a graphic on a 16x2 LCD display (using ST7066U controller).
+ * 
+ * 2012-05-09 John Schooling
+ *
+ 
+ In order to try and understand what's going on and to customise it later
+ I changed the code into an ST7066U class
+ 
+ 
+ 
+ */
+
+#include "mbed.h"
+
+
+class ST7066U  {
+
+    private :
+        DigitalOut *rs, *rw, *e, *db0, *db1, *db2, *db3, *db4, *db5, *db6, *db7;
+        uint8_t lines_bit, font_bit;
+
+    public :
+    ST7066U () {
+        rs = new DigitalOut(p5);
+        rw = new DigitalOut(p6);
+        e = new DigitalOut(p7);
+        db0 = new DigitalOut(p8);
+        db1 = new DigitalOut(p9);
+        db2 = new DigitalOut(p10);
+        db3 = new DigitalOut(p11);
+        db4 = new DigitalOut(p12);
+        db5 = new DigitalOut(p13);
+        db6 = new DigitalOut(p14);
+        db7 = new DigitalOut(p15); 
+        
+        font_bit = 0;
+        lines_bit = 0;
+        
+        wait(0.040);          // LCD initialisation takes 40ms.
+    }
+    
+    void rows(int l) {
+        if(l == 1)
+            lines_bit = 0;
+        else if (l == 2)
+            lines_bit = 8;
+        
+        instruction(32 | 16 | lines_bit | font_bit);
+    }
+    
+    void font(int f) {
+        if(f == 0)
+            font_bit = 0;
+        else if (f == 1)
+            font_bit = 4;
+         
+        instruction(32 | 16 | lines_bit | font_bit);
+    }
+       
+    
+    void write(int c, int nrs) {
+        int old_rs = rs->read();
+        // Should check Busy Flag here.
+        rs->write(nrs);
+        e->write(1);  // E must be on for min 480ns then drop to zero.  Trigger is on falling signal.
+        db0->write(c & 1);
+        db1->write(c>>1 & 1);
+        db2->write(c>>2 & 1);
+        db3->write(c>>3 & 1);
+        db4->write(c>>4 & 1);
+        db5->write(c>>5 & 1);
+        db6->write(c>>6 & 1);
+        db7->write(c>>7 & 1);
+        
+        // added extra wait state
+        wait(0.000001);  // Needed the equivalent of this on the Raspberry Pi.
+        
+        // Tdsw Data Setup Width time at least 80ns.  No need for delay on slow processor.
+        e->write(0); //   = 0; // Strobe.
+        // Th   Data Hold time at least 10ns.  No need for delay on slow processor.
+        wait(0.000037);  // Most instructions take 37us.  May not need this delay if Busy Flag checked at top.
+        rs->write(old_rs);
+    }
+    
+    void data(uint8_t c) {
+        write(c, 1); 
+    }
+    void instruction(uint8_t c) {
+        write(c, 0);
+    }
+    
+    void clear(void) {
+        instruction(1);
+        wait(0.00152); // clear takes 1.52 ms.
+    }
+    void home(void) {
+        instruction(2); 
+        wait(0.00152); // home takes 1.52 ms.
+    }
+    
+    void str_at(const char *str, uint8_t x = 0, uint8_t y = 0) {
+        uint8_t *c = (uint8_t *) str;
+        ddram(y * 0x40 + x);
+        for (uint8_t i = 0; i < 80 && (*c); i++) { // Will never write more than 80 chars.
+            data(*c);
+            c++;
+        }
+    }
+    
+    void row0(const char *str, uint8_t x = 0) {
+        str_at(str, x, 0);
+    }
+    
+    void row1(const char *str, uint8_t x = 0) {
+        str_at(str, x, 1);
+    }
+    
+    void str(const char *str) {
+        str_at(str);
+    }
+    
+    void on() {
+        instruction(0x0C); // 0000 1DCB Display=1 Cursor=0 Blink=0
+    
+    }
+    
+    void off() {
+        instruction(0x08); // 0000 1DCB Display=0 Cursor=0 Blink=0
+    }
+    
+    void cgram(uint8_t a) {
+        instruction(0x40 | a);
+    }
+    
+    void ddram(uint8_t a) {
+        instruction(0x80 | a);
+    }
+
+};
+/*
+   Crystalfontz CFAH1602BTMIJT 16x2 LCD display.
+   http://www.coolcomponents.co.uk/catalog/blue-16x2-display-p-151.html (also part of mbed starter kit).
+
+   Sitronix ST7066U functions (compatible with Hitachi HD44780).
+   CFAH1602BTMIJT_v1.0.pdf
+   http://www.crystalfontz.com/controllers/ST7066U.pdf
+   
+   LCD initialisation takes 40ms.
+
+   Instruction              RS RW  7 6 5 4 3 2 1 0  Time (270kHz)
+   Clear Display             0  0  0 0 0 0 0 0 0 1  1.52 ms Clear, Home, Entry Mode = Increment.
+   Return Home               0  0  0 0 0 0 0 0 1 x  1.52 ms.
+   Entry Mode Set            0  0  0 0 0 0 0 1 I S   .037ms Increment cursor, Shift display (shift cursor).
+   Display On/Off            0  0  0 0 0 0 1 D C P   .037ms Display on, Cursor on, Position on.
+   Cursor or Display Shift   0  0  0 0 0 1 D R x x   .037ms Display shift (cursor shift), Right (left).
+   Function Set              0  0  0 0 1 D N F x x   .037ms Data interface 8 (4) bits, Number of lines 2 (1), Font 5x11 if 1 line (5x8).
+   Set CGRAM address         0  0  0 1 A A A A A A   .037ms Set 6 bit CGRAM address in address counter.
+   Set DDRAM address         0  0  1 A A A A A A A   .037ms Set 7 bit DDRAM address in address counter.
+   Read Busy Flag and addr   0  1  F A A A A A A A   .000ms Read Busy Flag and address counter.
+   Write data to RAM         1  0  A A A A A A A A   .037ms Write data to RAM (DDRAM or CGRAM).  Must do Set address first.
+   Read data from RAM        1  1  A A A A A A A A   .037ms Read data from internal RAM (DDRAM or CGRAM).  Must do Set address first.
+*/
+
+int face1[8][8] = {
+      {0x01, 0x02, 0x04, 0x08, 0x13, 0x14, 0x14, 0x13} // Top left.
+    , {0x1F, 0x00, 0x00, 0x00, 0x00, 0x11, 0x11, 0x04}
+    , {0x10, 0x08, 0x04, 0x02, 0x19, 0x05, 0x05, 0x19}
+    , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Top right.
+
+    , {0x10, 0x10, 0x12, 0x11, 0x09, 0x04, 0x02, 0x01} // Bottom left.
+    , {0x04, 0x00, 0x00, 0x00, 0x1F, 0x1F, 0x00, 0x1F}
+    , {0x01, 0x01, 0x09, 0x11, 0x12, 0x04, 0x08, 0x10}
+    , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Bottom right.
+};
+int face2[8][8] = {
+      {0x01, 0x06, 0x0C, 0x18, 0x30, 0x33, 0x36, 0x36} // Top left.
+    , {0x3F, 0x00, 0x00, 0x00, 0x00, 0x21, 0x33, 0x33}
+    , {0x20, 0x18, 0x0C, 0x06, 0x03, 0x33, 0x1B, 0x1B}
+    , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Top right.
+
+    , {0x33, 0x30, 0x33, 0x1B, 0x19, 0x0C, 0x06, 0x01} // Bottom left.
+    , {0x21, 0x00, 0x00, 0x00, 0x21, 0x3F, 0x00, 0x3F}
+    , {0x33, 0x03, 0x33, 0x36, 0x26, 0x0C, 0x18, 0x20}
+    , {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00} // Bottom right.
+};
+
+
+
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);
+
+void scroll_face(ST7066U *lcd) {
+    int pict[8][8];
+    memcpy(pict, face2, sizeof(pict));
+    lcd->cgram(0);
+    for (int i = 0; i < 64; i++) {
+        lcd->data((uint8_t)pict[i/8][i%8]);
+    }
+    // Display the graphic characters.
+    lcd->ddram(0);
+    lcd->data(3);    // Top right of graphic.                                              
+    lcd->ddram(64); 
+    lcd->data(7);    // Bottom right of graphic.
+
+    for (int n = 0; n < 19; n++) {
+        for (int k = 0; k < 6; k++) { // 6 bit Smooth scrolling avoiding jump between characters on display.
+            lcd->cgram(0); 
+            for (int i = 63; i >= 0; i--) {
+                if (i/8 == 0 || i/8 == 4) {
+                    pict[i/8][i%8] |= ((pict[i/8 +3][i%8] &1) << 6); // Put right hand low bit into bit 6.
+                } else {
+                    pict[i/8][i%8] |= ((pict[i/8 -1][i%8] &1) << 6); // Put previous low bit into bit 6.
+                }
+            }
+            for (int i = 0; i < 64; i++) {
+                pict[i/8][i%8] >>= 1;                                // Scroll the character.
+                lcd->data((uint8_t)pict[i/8][i%8]);             // Write to LCD.
+            }
+            wait(0.1);
+        }
+        if(n >= 3) {
+            // Graphic has moved on a whole character.  Replace left characters with a space.
+            lcd->ddram(n - 3); 
+            lcd->data(' ');
+            lcd->ddram(64 + n - 3);
+            lcd->data(' ');
+        }
+        // Set right side of graphic to correct characters.
+        lcd->ddram(1 + n); 
+        lcd->data(n%4);
+        lcd->ddram(64 + 1 + n);
+        lcd->data(n%4 + 4);
+    }
+}
+
+void scroll_bar(ST7066U *lcd) {
+
+    // Scrolling vertical bar to clear the screen.
+    // Bar is two lines (smoother scrolling and more visible than a single line).
+    // There are six combinations for each of the available five bits.  Avoids jump between characters on display.
+    // Character number 7 is used for the graphic (0-5 are used by the face).  Earlier version left face on screen.
+    for (int i = 0; i < 6 * 17; i++) { // 6 positions for each of 17 characters.
+        lcd->cgram(7 * 8); 
+        for (int j = 0; j < 8; j++) {
+            lcd->data((3 << (5 - i%6)) >> 1); // Fill 8 bytes for vertical bar character in Character Generator RAM.
+        }
+        lcd->ddram(i / 6 - (i >= 6)); 
+        if (i >= 6) lcd->data(0x20);
+        lcd->data(7); // Top row.
+        lcd->ddram(64 + i / 6 - (i >= 6));
+        if (i >= 6) lcd->data(0x20);
+        lcd->data(7); // Bottom row.
+        wait(0.075);
+    }
+}
+
+int main() {
+
+    uint32_t a = 0;       // Main PWM loop counter.
+    uint16_t b;
+    int16_t i;
+    uint16_t e4[] = {0, 20, 256}; // LED brightness.
+    char str[17];              // String for writing to the LCD display.
+
+    ST7066U *lcd = new ST7066U();
+    
+    lcd->clear();
+    lcd->rows(2);
+    lcd->on(); 
+
+    lcd->row0("Bedtime", 4);    
+    lcd->row1("Counter", 4);
+
+    // Flash display off/on a couple of times.
+    for (int i = 0; i < 2; i++) {
+        wait(0.5);
+        lcd->off(); // 0000 1DCB Display=0 Cursor=0 Blink=0
+        wait(0.5);
+        lcd->on(); // 0000 1DCB Display=1 Cursor=0 Blink=0
+    }
+
+    wait(1);
+    scroll_face(lcd);
+    //scroll_bar();
+
+    // Trinary counting.
+    // Use the mbed LEDs to display trinary values (using software PWM) to count from zero to 80 (trinary 2222).
+    // LED brightness: off = 0, half bright = 1, full on = 2.
+    i = 80; // Force next display value to be zero: (80 + 1) % 81.
+    while (1) {
+        if (a == 0) {
+            // Counter expired: display the next value.
+            i = (i + 1) % 81;
+            // Write decimal and trinary.
+            sprintf(str, "dec %2d  tri %d%d%d%d", i, (i / 27) % 3, (i / 9) % 3, (i / 3) % 3, i % 3);
+            lcd->row0(str);
+            // Write hex and binary.
+            sprintf(str, "0x%2.2X  0b0%d%d%d%d%d%d%d", i, i>>6&1, i>>5&1, i>>4&1, i>>3&1, i>>2&1, i>>1&1, i&1);
+            lcd->row1(str);
+        }
+        b = a & 0xFF;
+        // PWM for mbed LEDs.  e4 contains the brightness for trit values 0, 1 and 2.
+        myled4 = b < e4[       i % 3] ? 1 : 0;
+        myled3 = b < e4[(i /  3) % 3] ? 1 : 0;
+        myled2 = b < e4[(i /  9) % 3] ? 1 : 0;
+        myled1 = b < e4[(i / 27) % 3] ? 1 : 0;
+        a = (a + 1) & 0x7FFFF; // Loop counter.
+    }
+}
diff -r 000000000000 -r a6f66204f651 mbed.bld
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mbed.bld	Mon Jul 09 22:59:06 2012 +0000
@@ -0,0 +1,1 @@
+http://mbed.org/users/mbed_official/code/mbed/builds/737756e0b479