* 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 The code is not in a library but gives you what you need in one file to add the required code to your own library.

Dependencies:   mbed

Revision:
0:514531f6b9db
Child:
1:f0561ba3d266
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/main.cpp	Wed May 09 14:29:05 2012 +0000
@@ -0,0 +1,244 @@
+/*
+ * 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
+ *
+ */
+
+#include "mbed.h"
+
+#define    LCD_RS_DATA   1
+#define    LCD_RS_INST   0
+
+/*
+   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 lcd_rs(p5);
+DigitalOut lcd_rw(p6);
+DigitalOut lcd_e(p7);
+DigitalOut lcd_db0(p8);
+DigitalOut lcd_db1(p9);
+DigitalOut lcd_db2(p10);
+DigitalOut lcd_db3(p11);
+DigitalOut lcd_db4(p12);
+DigitalOut lcd_db5(p13);
+DigitalOut lcd_db6(p14);
+DigitalOut lcd_db7(p15);
+
+
+DigitalOut myled1(LED1);
+DigitalOut myled2(LED2);
+DigitalOut myled3(LED3);
+DigitalOut myled4(LED4);
+
+
+void lcd_write(int c, int rs) {
+    int old_lcd_rs = lcd_rs;
+    // Should check Busy Flag here.
+    lcd_rs  = rs;
+    lcd_e   = 1; // E must be on for min 480ns then drop to zero.  Trigger is on falling signal.
+    lcd_db0 = c    & 1;
+    lcd_db1 = c>>1 & 1;
+    lcd_db2 = c>>2 & 1;
+    lcd_db3 = c>>3 & 1;
+    lcd_db4 = c>>4 & 1;
+    lcd_db5 = c>>5 & 1;
+    lcd_db6 = c>>6 & 1;
+    lcd_db7 = c>>7 & 1;
+    // Tdsw Data Setup Width time at least 80ns.  No need for delay on slow processor.
+    lcd_e   = 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.
+    lcd_rs  = old_lcd_rs;
+}
+
+void lcd_write_data(uint8_t c) {
+    lcd_write(c, LCD_RS_DATA);    // Data
+}
+void lcd_write_inst(uint8_t c) {
+    lcd_write(c, LCD_RS_INST);    // Instruction
+}
+
+void lcd_clear(void) {
+    lcd_write_inst(1); //
+    wait(0.00152); // clear takes 1.52 ms.
+}
+void lcd_home(void) {
+    lcd_write_inst(2); //
+    wait(0.00152); // home takes 1.52 ms.
+}
+
+void lcd_write_str(uint8_t *str, uint8_t x = 0, uint8_t y = 0) {
+    uint8_t *c = str;
+    lcd_write_inst(0x80 + y * 0x40 + x); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+    for (uint8_t i = 0; i < 80 && (*c); i++) { // Will never write more than 80 chars.
+        lcd_write_data(*c);
+        c++;
+    }
+}
+
+void scroll_face(void) {
+int pict[8][8];
+    memcpy(pict, face2, sizeof(pict));
+    // Write the graphic characters to CGRAM.
+    lcd_write_inst(0x40); // 0 1 A A A A A A  Set 6 bit CGRAM address in address counter
+    for (int i = 0; i < 64; i++) {
+        lcd_write_data((uint8_t)pict[i/8][i%8]);
+    }
+    // Display the graphic characters.
+    lcd_write_inst(0x80); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+    lcd_write_data(3);    // Top right of graphic.
+    lcd_write_inst(0xC0); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+    lcd_write_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.
+            // Write the graphic characters to CGRAM.
+            lcd_write_inst(0x40); // 0 1 A A A A A A  Set 6 bit CGRAM address in address counter
+            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 previous low bit into bit 6.
+                } else {
+                    pict[i/8][i%8] |= ((pict[i/8 -1][i%8] &1) << 6); // Put right hand end bit into bit 6.
+                }
+            }
+            for (int i = 0; i < 64; i++) {
+                pict[i/8][i%8] >>= 1;                                // Scroll the character.
+                lcd_write_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_write_inst(0x80 + n - 3); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+            lcd_write_data(32);
+            lcd_write_inst(0xC0 + n - 3); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+            lcd_write_data(32);
+        }
+        // Set right side of graphic to correct characters.
+        lcd_write_inst(0x81 + n); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+        lcd_write_data(n%4);
+        lcd_write_inst(0xC1 + n); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+        lcd_write_data(n%4 + 4);
+    }
+}
+
+void scroll_bar(void) {
+
+    // 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_write_inst(0x40 + 7 * 8); // 0 1 A A A A A A  Set 6 bit CGRAM address in address counter
+        for (int j = 0; j < 8; j++) {
+            lcd_write_data((3 << (5 - i%6)) >> 1); // Fill 8 bytes for vertical bar character in Character Generator RAM.
+        }
+        lcd_write_inst(0x80 + i / 6 - (i >= 6)); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+        if (i >= 6) lcd_write_data(0x20);
+        lcd_write_data(7); // Top row.
+        lcd_write_inst(0xC0 + i / 6 - (i >= 6)); // 1 A A A A A A A  Set 7 bit DDRAM address in address counter
+        if (i >= 6) lcd_write_data(0x20);
+        lcd_write_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.
+    uint8_t str[17];              // String for writing to the LCD display.
+
+    wait(0.040);          // LCD initialisation takes 40ms.
+    lcd_clear();
+    lcd_write_inst(0x0C); // 0000 1DCB Display=1 Cursor=0 Blink=0
+    lcd_write_inst(0x38); // 001D NFxx Data interface 8 (4) bits, Number of lines 2 (1), Font 5x11 if 1 line (5x8)
+
+    lcd_write_str((uint8_t *)"Trinary", 4, 0);
+    lcd_write_str((uint8_t *)"Counter", 4, 1);
+
+    // Flash display off/on a couple of times.
+    for (int i = 0; i < 2; i++) {
+        wait(0.5);
+        lcd_write_inst(0x08); // 0000 1DCB Display=0 Cursor=0 Blink=0
+        wait(0.5);
+        lcd_write_inst(0x0C); // 0000 1DCB Display=1 Cursor=0 Blink=0
+    }
+
+    wait(1);
+    scroll_face();
+    //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((char *)str, "dec %2d  tri %d%d%d%d", i, (i / 27) % 3, (i / 9) % 3, (i / 3) % 3, i % 3);
+            lcd_write_str(str);
+            // Write hex and binary.
+            sprintf((char *)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_write_str(str, 0, 1);
+        }
+        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.
+    }
+}