This is a sample program to drive a 128x128 LCD with t6963 controller through SPI by means of an MCP23S17 16-Bit I/O Expander with Serial Interface

Dependencies:   mbed

Revision:
3:fc101c00b5be
Parent:
2:9071445a6895
Child:
4:fd7c6559a56d
--- a/main.cpp	Mon Dec 06 20:45:00 2010 +0000
+++ b/main.cpp	Tue Jun 28 17:02:24 2011 +0000
@@ -1,218 +1,409 @@
-#include "mbed.h"
-#include "mcp_lcd.h"
-
-// for 21 characters on a row (6x8 font)
-// #define LCDFONTSEL  0xFF
-// for 16 characters on a row (8x8 font)
-#define LCDFONTSEL 0xDF
-
-// lcd dimensions in pixels
-#define LCD_XWIDTH     128
-#define LCD_YHEIGHT    128
-
-#if LCDFONTSEL == 0xFF
-// lcd dimensions in characters
-#define LCD_WIDTH   22
-#define LCD_HEIGHT  16
-#else
-#define LCD_WIDTH   16
-#define LCD_HEIGHT  16
-#endif
-
-#define TEXT_STARTADDRESS       0x0000
-#define GRAPHIC_STARTADDRESS    0x1000
-
-DigitalOut myled(LED1);
-SPI spi(p5, p6, p7); // mosi, miso, sclk
-DigitalOut cs(p20);
-
-Serial pc(USBTX, USBRX); // tx, rx
-
-
-// write 8 bits lcd data
-void lcd_data(unsigned char d)
-{
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOB);  // select GPIOB
-    spi.write(d);      // set data byte
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL-LCD_CE-LCD_CD);   
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL - LCD_WR - LCD_CE - LCD_CD);   
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL - LCD_CD);   
-    cs=1;
-    
-}
-
-// write 8 bits lcd command
-void lcd_command(unsigned char c)
-{
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOB);  // select GPIOB
-    spi.write(c);      // set data byte
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL-LCD_CE);   
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL - LCD_WR - LCD_CE);   
-    cs=1;
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA
-    spi.write(LCDFONTSEL);   
-    cs=1;
-}
-
-void lcd_init()
-{
-    cs=0;
-    spi.write(0x40);
-    spi.write(IODIRA);  // select IODIRA at start
-    spi.write(0x00);    // IODIRA all outputs
-    spi.write(0x00);    // IODIRB all outputs
-    cs=1;
-    wait(0.1);
-    
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA at start
-    spi.write(LCDFONTSEL-LCD_RST);    // activate reset
-    spi.write(0x00);    // all B outputs 0
-    cs=1;
-    wait(0.1);
-
-    cs=0;
-    spi.write(0x40);
-    spi.write(GPIOA);  // select GPIOA at start
-    spi.write(LCDFONTSEL);    // deactivate reset
-    cs=1;
-    wait(0.1);
-
-    // set text home address at 0x0000
-    lcd_data(TEXT_STARTADDRESS%0x100);
-    lcd_data(TEXT_STARTADDRESS/0x100);
-    lcd_command(TXHOME);
-    
-    // set graphic home address at 0x1000
-    lcd_data(GRAPHIC_STARTADDRESS%0x100);
-    lcd_data(GRAPHIC_STARTADDRESS/0x100);
-    lcd_command(GRHOME);
-    
-    // set text area 
-    lcd_data(LCD_WIDTH);
-    lcd_data(0x00);
-    lcd_command(TXAREA);
-
-    // set graphic area
-    lcd_data(LCD_WIDTH);
-    lcd_data(0x00);
-    lcd_command(GRAREA);
-    
-    // mode set (internal character generation mode)
-    lcd_command(0x80);
-    
-    // set offset register
-    lcd_data(0x02);
-    lcd_data(0x00);
-    lcd_command(OFFSET);
-    
-    // display mode (text on graphics on cursor off)
-    lcd_command(0x90+0x08+0x04);
-        
-}
-
-// put a text string at position x,y (character row,column)
-void lcd_string(char x,char y,char *s)
-{
-    int adr;
-    adr=TEXT_STARTADDRESS+x+y*LCD_WIDTH;
-    lcd_data(adr%0x100);
-    lcd_data(adr/0x100);
-    lcd_command(ADPSET);
-    lcd_command(AWRON);
-    
-    while (s[0])
-    {
-        // convert from ascii to t6963
-        lcd_data(s[0]-32);
-        s++;
-    }
-    lcd_command(AWROFF);
-}
-
-// clear lcd display memory (8k)        
-void lcd_cls()
-{
-    int a;
-    lcd_data(0x00);
-    lcd_data(0x00);
-    lcd_command(ADPSET);
-    lcd_command(AWRON);
-    for (a=0; a<8192; a++) lcd_data(0);
-    lcd_command(AWROFF);
-}
-
-// set or reset a pixel on the display on position x,y with color 0 or 1
-void lcd_plot(char x,char y,char color)
-{
-    int adr;                         
-    adr = GRAPHIC_STARTADDRESS + ((LCD_WIDTH) * y) + (x/8);   // calculate offset
-    lcd_data(adr%0x100);       // set low byte
-    lcd_data(adr/0x100);       // set high byte
-    lcd_command(ADPSET);           // set address pointer
-    if (color) lcd_command(BS + (7-(x%8)));   // use bit set mode
-        else  lcd_command(BR + (7-(x%8)));  // use bit reset mode
-}
-
-int main() {
-
-    int a;
-    pc.printf("SPI test\n");
-    
-    // set SPI to full speed (10 MHz mode)
-    spi.format(8,0);
-    spi.frequency(10000000);
-//    spi.frequency(10000);
-    wait(0.1);
-
-    pc.printf("MCP init\n");
-    lcd_init();
-    lcd_cls();
-
-    // write some text    
-    lcd_string(0,0,"Hello World!");
-    lcd_string(0,2,"0123456789");
-    lcd_string(0,15,"abcdefghijklmnopqrstuvwxyz");
-   
-    for (a=0; a<128; a++) lcd_plot(a,a/2+48,1);
-    
-    while(1) {
-        myled = 1;
-        wait(0.2);
-        myled = 0;
-        wait(0.2);
-    }
-}
+#include "mbed.h"
+#include "mcp_lcd.h"
+
+// for 21 characters on a row (6x8 font)
+#define LCDFONTSEL  0xFF
+// for 16 characters on a row (8x8 font)
+// #define LCDFONTSEL 0xDF
+
+// lcd dimensions in pixels
+#define LCD_XWIDTH     128
+#define LCD_YHEIGHT    128
+
+#if LCDFONTSEL == 0xFF
+// lcd dimensions in characters
+#define LCD_WIDTH   22
+#define LCD_HEIGHT  16
+#define PIXELWIDTH  6
+#else
+#define LCD_WIDTH   16
+#define LCD_HEIGHT  16
+#define PIXELWIDTH  8
+#endif
+
+#define TEXT_STARTADDRESS       0x0000
+#define GRAPHIC_STARTADDRESS    0x1000
+
+   
+#define CENTERX 64
+#define CENTERY 64
+#define INNER_RADIUS    45
+#define OUTER_RADIUS    50
+#define CENTER_CIRCLE   5
+
+DigitalOut myled(LED1);
+SPI spi(p5, p6, p7); // mosi, miso, sclk
+DigitalOut cs(p20);
+
+Serial pc(USBTX, USBRX); // tx, rx
+
+
+// write 8 bits lcd data
+void lcd_data(unsigned char d)
+{
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOB);  // select GPIOB
+    spi.write(d);      // set data byte
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL-LCD_CE-LCD_CD);   
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL - LCD_WR - LCD_CE - LCD_CD);   
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL - LCD_CD);   
+    cs=1;
+    
+}
+
+// write 8 bits lcd command
+void lcd_command(unsigned char c)
+{
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOB);  // select GPIOB
+    spi.write(c);      // set data byte
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL-LCD_CE);   
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL - LCD_WR - LCD_CE);   
+    cs=1;
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA
+    spi.write(LCDFONTSEL);   
+    cs=1;
+}
+
+void lcd_init()
+{
+    cs=0;
+    spi.write(0x40);
+    spi.write(IODIRA);  // select IODIRA at start
+    spi.write(0x00);    // IODIRA all outputs
+    spi.write(0x00);    // IODIRB all outputs
+    cs=1;
+    wait(0.1);
+    
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA at start
+    spi.write(LCDFONTSEL-LCD_RST);    // activate reset
+    spi.write(0x00);    // all B outputs 0
+    cs=1;
+    wait(0.1);
+
+    cs=0;
+    spi.write(0x40);
+    spi.write(GPIOA);  // select GPIOA at start
+    spi.write(LCDFONTSEL);    // deactivate reset
+    cs=1;
+    wait(0.1);
+
+    // set text home address at 0x0000
+    lcd_data(TEXT_STARTADDRESS%0x100);
+    lcd_data(TEXT_STARTADDRESS/0x100);
+    lcd_command(TXHOME);
+    
+    // set graphic home address at 0x1000
+    lcd_data(GRAPHIC_STARTADDRESS%0x100);
+    lcd_data(GRAPHIC_STARTADDRESS/0x100);
+    lcd_command(GRHOME);
+    
+    // set text area 
+    lcd_data(LCD_WIDTH);
+    lcd_data(0x00);
+    lcd_command(TXAREA);
+
+    // set graphic area
+    lcd_data(LCD_WIDTH);
+    lcd_data(0x00);
+    lcd_command(GRAREA);
+    
+    // mode set (internal character generation mode)
+    lcd_command(0x80);
+    
+    // set offset register
+    lcd_data(0x02);
+    lcd_data(0x00);
+    lcd_command(OFFSET);
+    
+    // display mode (text on graphics on cursor off)
+    lcd_command(0x90+0x08+0x04);
+        
+}
+
+// put a text string at position x,y (character row,column)
+void lcd_string(char x,char y,char *s)
+{
+    int adr;
+    adr=TEXT_STARTADDRESS+x+y*LCD_WIDTH;
+    lcd_data(adr%0x100);
+    lcd_data(adr/0x100);
+    lcd_command(ADPSET);
+    lcd_command(AWRON);
+    
+    while (s[0])
+    {
+        // convert from ascii to t6963
+        lcd_data(s[0]-32);
+        s++;
+    }
+    lcd_command(AWROFF);
+}
+
+// clear lcd display memory (8k)        
+void lcd_cls()
+{
+    int a;
+    lcd_data(0x00);
+    lcd_data(0x00);
+    lcd_command(ADPSET);
+    lcd_command(AWRON);
+    for (a=0; a<8192; a++) lcd_data(0);
+    lcd_command(AWROFF);
+}
+
+// set or reset a pixel on the display on position x,y with color 0 or 1
+void lcd_plot(char x,char y,char color)
+{
+    int adr;                         
+    adr = GRAPHIC_STARTADDRESS + ((LCD_WIDTH) * y) + (x/PIXELWIDTH);   // calculate offset
+    lcd_data(adr%0x100);       // set low byte
+    lcd_data(adr/0x100);       // set high byte
+    lcd_command(ADPSET);           // set address pointer
+    if (color) lcd_command(BS + ((PIXELWIDTH-1)-(x%PIXELWIDTH)));   // use bit set mode
+        else  lcd_command(BR + ((PIXELWIDTH-1)-(x%PIXELWIDTH)));  // use bit reset mode
+}
+
+// Bresenham line routine
+void lcd_line(int x0, int y0, int x1, int y1,char color)
+{
+    char steep=1;
+    int i,dx,dy,e;
+    signed char sx,sy;
+    
+    dx = abs(x1-x0);
+    sx = ((x1 - x0) >0) ? 1 : -1;
+    dy=abs(y1-y0);
+    sy = ((y1 - y0) >0) ? 1 : -1;
+    
+    if (dy > dx)
+    {
+        steep=0;
+        // swap X0 and Y0
+        x0=x0 ^ y0;
+        y0=x0 ^ y0;
+        x0=x0 ^ y0;
+
+        // swap DX and DY
+        dx=dx ^ dy;
+        dy=dx ^ dy;
+        dx=dx ^ dy;
+
+        // swap SX and SY
+        sx=sx ^ sy;
+        sy=sx ^ sy;
+        sx=sx ^ sy;
+    }
+
+    e = (dy << 1) - dx;
+
+    for (i=0; i<=dx; i++)
+    {
+        if (steep)
+        {
+            lcd_plot(x0,y0,color);
+        }
+        else
+        {
+            lcd_plot(y0,x0,color);
+        }
+        while (e >= 0)
+        {
+            y0 += sy;
+            e -= (dx << 1);
+        }
+        x0 += sx;
+        e += (dy << 1);
+    }
+ }
+
+// Bresenham circle routine
+void lcd_circle(int x0,int y0, int radius, char color)
+{
+
+    int f = 1 - radius;
+    int dx = 1;
+    int dy = -2 * radius;
+    int x = 0;
+    int y = radius;
+ 
+    lcd_plot(x0, y0 + radius,color);
+    lcd_plot(x0, y0 - radius,color);
+    lcd_plot(x0 + radius, y0,color);
+    lcd_plot(x0 - radius, y0,color);
+ 
+    while(x < y)
+    {
+        if(f >= 0) 
+        {
+            y--;
+            dy += 2;
+            f += dy;
+        }
+        x++;
+        dx += 2;
+        f += dx;    
+        lcd_plot(x0 + x, y0 + y,color);
+        lcd_plot(x0 - x, y0 + y,color);
+        lcd_plot(x0 + x, y0 - y,color);
+        lcd_plot(x0 - x, y0 - y,color);
+        lcd_plot(x0 + y, y0 + x,color);
+        lcd_plot(x0 - y, y0 + x,color);
+        lcd_plot(x0 + y, y0 - x,color);
+        lcd_plot(x0 - y, y0 - x,color);
+    }
+}
+
+int main() {
+
+    
+    float a,b,f;
+    float pi=3.14159265;
+    float h_pi=pi/6;
+    float m_pi=pi/30;
+    
+        char buf[40];
+    time_t seconds;
+    int sec,min,hour;
+    int s_sx,s_sy,s_ex,s_ey;
+    int m_sx,m_sy,m_ex,m_ey;
+    int h_sx,h_sy,h_ex,h_ey;
+    
+    // setup time structure
+    struct tm t;
+    t.tm_sec = 00;    // 0-59
+    t.tm_min = 30;    // 0-59
+    t.tm_hour = 21;   // 0-23
+    t.tm_mday = 14;   // 1-31
+    t.tm_mon = 11;     // 0-11
+    t.tm_year = 110;  // year since 1900
+    seconds = mktime(&t);
+    // set_time(seconds);
+
+
+    pc.printf("SPI test\n");
+    
+    // set SPI to full speed (10 MHz mode)
+    spi.format(8,0);
+    spi.frequency(10000000);
+//    spi.frequency(10000);
+    wait(0.1);
+
+    pc.printf("MCP init\n");
+    lcd_init();
+    lcd_cls();
+
+    // write some text 345678901234567890   
+    lcd_string(0,0,"* Hello mbed World! *");
+    // lcd_string(0,15,"abcdefghijklmnopqrstuvwxyz");
+   
+    
+    // draw outer circle of analog clock
+    lcd_circle(CENTERX,CENTERY,OUTER_RADIUS+1,1);    
+   
+   // draw hour markings  
+    for (min=0; min<59; min+=5)
+    {
+        b=min*m_pi;
+        m_sx=sin(b)*INNER_RADIUS+CENTERX;
+        m_sy=-cos(b)*INNER_RADIUS+CENTERY;
+        m_ex=sin(b)*OUTER_RADIUS+CENTERX;
+        m_ey=-cos(b)*OUTER_RADIUS+CENTERY;
+        lcd_line(m_sx,m_sy,m_ex,m_ey,1);
+    }
+        
+
+    for(;;)
+    {
+        seconds = time(NULL);
+        
+        //                13:24:00   dd/mm/yyyy
+        strftime(buf,40, "%H:%M:%S   %d/%m/%Y", localtime(&seconds));
+        lcd_string(0,15,buf);
+
+        strftime(buf,40, "%I %M %S", localtime(&seconds));
+        sscanf(buf,"%d %d %d",&hour,&min,&sec);
+        
+        b=sec*m_pi;
+        s_sx=CENTERX;
+        s_sy=CENTERY;
+        s_ex=sin(b)*(INNER_RADIUS-3)+CENTERX;
+        s_ey=-cos(b)*(INNER_RADIUS-3)+CENTERY;
+
+        
+        b=min*m_pi;
+        m_sx=sin(b)*(CENTER_CIRCLE)+CENTERX;
+        m_sy=-cos(b)*(CENTER_CIRCLE)+CENTERY;
+        m_ex=sin(b)*(INNER_RADIUS-10)+CENTERX;
+        m_ey=-cos(b)*(INNER_RADIUS-10)+CENTERY;
+
+        // advancing hour hand
+        if (hour<12)
+        {
+            // draw hour hand with an offset
+            // calculated by dividing minutes by 12 
+            b=(hour*5+min/12)*m_pi;
+        }
+        else
+        {
+            // hour would be 0 offset at 12 o'clock
+            // so we can leave it out of the equation...
+            b=(min/12)*m_pi;
+        }
+        h_sx=sin(b)*(CENTER_CIRCLE)+CENTERX;
+        h_sy=-cos(b)*(CENTER_CIRCLE)+CENTERY;
+        h_ex=sin(b)*(INNER_RADIUS-20)+CENTERX;
+        h_ey=-cos(b)*(INNER_RADIUS-20)+CENTERY;
+
+        // draw 'new' hands
+        lcd_line(s_sx,s_sy,s_ex,s_ey,1);
+        lcd_line(m_sx,m_sy,m_ex,m_ey,1);
+        lcd_line(h_sx,h_sy,h_ex,h_ey,1);
+
+        lcd_circle(CENTERX,CENTERY,CENTER_CIRCLE,1);        
+        lcd_circle(CENTERX,CENTERY,1,1);        
+ 
+        myled = !myled;
+        
+        // now wait until the seconds change
+        while (seconds==time(NULL)) wait(0.1);
+        
+        // erase 'old' hands
+        lcd_line(s_sx,s_sy,s_ex,s_ey,0);
+        lcd_line(m_sx,m_sy,m_ex,m_ey,0);
+        lcd_line(h_sx,h_sy,h_ex,h_ey,0);
+        
+    }
+}