Y-con P020 Electric Paper Display

Dependents:   YconP020_USBIFEx

This is a library for Y-con P020 Electric Paper Display.

sample program is here.

詳しくはこちら(sorry only in Japanese)をご覧ください。

Revision:
1:a7e6ebc4cb72
Parent:
0:4dbc7e226777
--- a/YconP020.cpp	Fri Jul 01 13:22:18 2016 +0000
+++ b/YconP020.cpp	Sun Jul 03 10:38:58 2016 +0000
@@ -1,10 +1,84 @@
 #include "mbed.h"
 #include "YconP020.h"
-#ifdef TARGET_LPC11U35_501
-#include "DirHandle.h" //トラ技ARMライタでは何故かこれが必要
+#if DEVICE_LOCALFILESYSTEM == 0
+#include "DirHandle.h" 
 #endif
 #include <cctype>
+#include <functional>
 
+int toint(const string::const_iterator& begin, const string::const_iterator& end)
+{
+    if(begin==end) return 0;
+    int val=0;
+    bool minus=false;
+    string::const_iterator p=begin;
+    if(*p=='-') {
+        minus=true;
+        p++;
+    }
+    while( p!=end) {
+        if((*p)<'0' || '9'<(*p)) break;
+        val = val*10+(*p)-'0';
+        p++;
+    }
+    if(minus) val = 0-val;
+    return val;
+}
+int toint(const string& s) {return toint(s.begin(),s.end());}
+string tostring(int i)
+{
+    string s;
+    bool minus=false;
+    if(i<0) {
+        minus=true;
+        i=0-i;
+    }
+    do {
+        s += (i%10)+'0';
+        i/=10;
+    } while(i!=0);
+    if(minus) s += '-';
+    reverse(s.begin(),s.end());
+    return s;
+}
+template<class T>
+T skipspace(T begin, T end)
+{
+    return find_if(begin,end, bind1st(not2(equal_to<char>()), ' '));
+}
+
+// class YconP020GBuf
+void YconP020GBuf::pixel(int x, int y, int b)
+{
+    if(x<0 || x>=MAX_X/pixelsizex || y<0 || y>=MAX_Y/pixelsizey) return;
+    for(int i=0; i<pixelsizex; i++) {
+        for(int j=0; j<pixelsizey; j++) {
+            pixel1x1(x*pixelsizex+i, y*pixelsizey+j, b);
+        }
+    }
+}
+void YconP020GBuf::setfontscale(uint8_t x, uint8_t y)
+{
+    if(x==0 || y==0) return;
+    locate((_column*pixelsizex+x-1)/x, (_row*pixelsizey+y-1)/y);
+    pixelsizex=x;
+    pixelsizey=y;
+}
+void YconP020GBuf::cls()
+{
+    setfontscale();
+    GraphicsDisplay::cls();
+    locate(0,0);
+}
+
+void YconP020GBuf::pixel1x1(int x, int y, int b)
+{
+    if(x<0 || x>=MAX_X || y<0 || y>=MAX_Y) return;
+    if(!b) buffer[MAX_Y-1-y][x/8] |= 1<<(7-(x%8));
+    else buffer[MAX_Y-1-y][x/8] &= ~(1<<(7-(x%8)));
+}
+
+// class YconP020
 YconP020::YconP020(PinName tx, PinName rx) : uart(tx,rx), use_recinbuf(false)
 {
     uart.baud(115200);
@@ -49,7 +123,7 @@
 const vector<string>& YconP020::getfilelist(const vector<string>& dirs)
 {
     filelist.clear();
-    for(vector<string>::const_iterator p=dirs.begin(); p<dirs.end(); p++) {
+    for(vector<string>::const_iterator p=dirs.begin(); p!=dirs.end(); p++) {
         string dn;
         if((*p)[0]!='/') dn='/';
         dn += *p;
@@ -63,22 +137,17 @@
         while((file=readdir(dir))!=NULL) {
             filename=file->d_name;
             if(filename.size()<4) continue;
-            string extstr(4,' ');
-            transform(filename.end()-4, filename.end(), extstr.begin(), toupper);
+            string extstr;
+            transform(filename.end()-4, filename.end(), back_inserter(extstr), toupper);
             if(extstr==".BMP") {
                 filelist.push_back('/'+ *p +'/'+filename);
             }
         }
         closedir(dir);
     }
+    sort(filelist.begin(),filelist.end());
     return filelist;
 }
-const vector<string>& YconP020::getfilelist(const string& dir)
-{
-    vector<string> fslist;
-    fslist.push_back(dir);
-    return getfilelist(fslist);
-}
 const vector<string>& YconP020::getfilelistall()
 {
     vector<string> fslist;
@@ -110,15 +179,7 @@
     recinbuf.clear();
     return r;
 }
-void YconP020::dispstoredpict(int picnum)
-{
-    use_recinbuf=true;
-    command_mode();
-    uart.printf("D %d\r", picnum);
-    wait_command_ready();
-    use_recinbuf=false;
-    recinbuf.clear();
-}
+
 YconP020::error_t YconP020::storepictfile(const string& filename, const int picnum)
 {
     if(picnum>6 || picnum<0) return REGINDEXERR;
@@ -134,7 +195,7 @@
 }
 
 const size_t BMPHEADERSIZE = 62;
-const int8_t BMPHEADER[BMPHEADERSIZE]
+const uint8_t BMPHEADER[BMPHEADERSIZE]
     = {0x42, 0x4d, 0xbd, 0x0a, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x3e, 0x00, 0x00, 0x00, 0x28, 0x00,
        0x00, 0x00, 0xc8, 0x00, 0x00, 0x00, 0x60, 0x00,
@@ -150,11 +211,11 @@
     uart.puts("exit\r");
     while(lastchar!='>') wait_ms(1);
     lastchar='\0';
-    for(size_t i=0; i<BMPHEADERSIZE; i++) {
+    for(int i=0; i<BMPHEADERSIZE; i++) {
         uart.putc(BMPHEADER[i]);
     }
-    for(size_t y=0; y<internalbuf.height(); y++) {
-        for(size_t x=0; x<internalbuf.width()/8; x++) uart.putc(internalbuf.get8(x,y));
+    for(int y=0; y<YconP020GBuf::MAX_Y; y++) {
+        for(int x=0; x<YconP020GBuf::MAX_X/8; x++) uart.putc(internalbuf.getbyte(x,y));
         uart.putc(0x00);
         uart.putc(0x00);
         uart.putc(0x00);
@@ -189,17 +250,114 @@
         mem_fun<void,YconP020,char>(&YconP020::push_recbuf), this));
 }
     
-YconP020::error_t YconP020::sendfile(const string& filename) {
-        FILE *fp=fopen(filename.c_str(),"r");
-        if(fp==NULL) return FILEOPENERR;
-        int c;
-        while((c=fgetc(fp)) != EOF) {
-            uart.putc(c);
+YconP020::error_t YconP020::sendfile(const string& filename)
+{
+    FILE *fp=fopen(filename.c_str(),"r");
+    if(fp==NULL) return FILEOPENERR;
+    int c;
+    while((c=fgetc(fp)) != EOF) {
+        uart.putc(c);
+    }
+    fclose(fp);
+    return NOERROR;
+}
+
+// 出力を横取りして拡張コマンドを処理するための関数群
+bool commandline_D(YconP020& epd, const string& comline, string& retstr)
+{
+    string::const_iterator cp=skipspace(comline.begin()+1,comline.end());
+    if(cp==comline.end()) return false;
+    switch(toupper(*cp)) {
+    case 'F':
+        if(++cp==comline.end()) return false;
+        if(*cp==' ') {
+            // "D F filename"
+            cp=skipspace(cp,comline.end());
+            if(cp!=comline.end()) {
+                string fn(cp,comline.end());
+                if(epd.dispfile(fn)!=YconP020::NOERROR) retstr += "\r\n"+fn+" not found\r\n!";
+            } else retstr += "Filename is required\r\n";
+        } else {
+            // "D Fnumber"
+            int i=toint(cp,comline.end());
+            if(0<=i && i<epd.getfilelist().size()) epd.dispfile(epd.getfilelist()[i]);
+            else retstr += "\r\nfile No."+string(cp,comline.end())+" not found\r\n!";
         }
-        fclose(fp);
-        return NOERROR;
+        return true;
+    case 'I':
+        // "D I"
+        epd.display_internalbuf();
+        return true;
+    default:
+        return false;
+    }
+}
+bool commandline_L(YconP020& epd, const string &comline, string& retstr)
+{
+    string::const_iterator cp=comline.begin()+1;
+    if(cp==comline.end()) return false;
+    if(toupper(*cp)!='S') return false;
+    if(++cp==comline.end()) {
+        // "LS"
+    } else {
+        if(*cp!=' ') return false;
+        cp=skipspace(cp,comline.end());
+        if(cp==comline.end()) {
+            // "LS "
+        } else if(*cp=='*') {
+            // "LS *"
+            epd.getfilelistall();
+        } else {
+            // "LS pathname"
+            epd.getfilelist(string(cp,comline.end()));
+        }
+    }
+    for(int i=0; i<epd.getfilelist().size(); i++) {
+        retstr += tostring(i)+": "+epd.getfilelist()[i]+"\r\n";
     }
-
+    return true;
+}
+void T_esc_num(YconP020& epd, string::const_iterator& p, const string::const_iterator& e)
+{
+    char c=*p++;
+    const string::const_iterator semicolon=find(p,e,';');
+    if(semicolon==e) return;
+    const string::const_iterator comma=find(p,semicolon,',');
+    int x,y;
+    if(comma==semicolon) {
+        x=0;
+        y=0;
+    } else {
+        x=toint(p, comma);
+        y=toint(comma+1,semicolon);
+    }
+    p=semicolon;
+    if(c=='l') epd.text()->locate(x,y);
+    if(x==0) x=1;
+    if(y==0) y=1;
+    if(c=='s') epd.setfontscale(x,y);
+}
+bool commandline_T(YconP020& epd, const string &comline)
+{
+    if(comline.size()>2 && comline[1]==' ') {
+        for(string::const_iterator p=comline.begin()+2; p<comline.end(); p++) {
+            if(*p=='\\') {
+                if(++p==comline.end()) break;
+                switch(*p) {
+                    case 'c': epd.text()->cls();         break;
+                    case 'f': epd.display_internalbuf(); break;
+                    case 'n': epd.text()->putc('\n');    break;
+                    case 'l': case 's':
+                       T_esc_num(epd,p,comline.end());   break;
+                    case '\\': epd.text()->putc('\\');   break;
+                    default: epd.text()->putc(*p);
+                }
+            } else  epd.text()->putc(*p);
+        }
+        return true;
+    }
+    return false;
+}
 int YconP020::putc_intercept(int c)
 {
     if(localcomline.size()) {
@@ -210,56 +368,35 @@
             return c;
         }
         push_recbuf('\n');
+        bool command_done=false;
+        string retstr;
         switch(toupper(localcomline[0])) {
             case 'D':
-                if(commandline_D(localcomline)) {
-                    localcomline.clear();
-                    push_recbuf('!');
-                    lastchar='!';
-                    return c;
-                }
+                command_done=commandline_D(*this, localcomline, retstr);
                 break;
             case 'L':
-                if(commandline_L(localcomline)) {
-                    localcomline.clear();
-                    push_recbuf('!');
-                    lastchar='!';
-                    return c;
-                }
+                command_done=commandline_L(*this, localcomline, retstr);
                 break;
             case 'T':
-                if(localcomline.size()>2 && localcomline[1]==' ') {
-                    for(string::const_iterator p=localcomline.begin()+2; p<localcomline.end(); p++) {
-                        switch(*p) {
-                        case '\\':
-                            if(++p==localcomline.end()) break;
-                            if(*p=='n') {
-                                text()->putc('\n');
-                            } else if(*p=='\\') {
-                                text()->putc('\\');
-                            }
-                            break;    
-                        default:
-                            text()->putc(*p);
-                        }
-                    }
-                    localcomline.clear();
-                    push_recbuf('!');
-                    lastchar='!';
-                    return c;
-                }
+                command_done=commandline_T(*this, localcomline);
                 break;
             case 'W':
                 if(localcomline.size()>=2 && toupper(localcomline[1])=='I') {
                     clear_internalbuf();
                     text()->locate(0,0);
-                    localcomline.clear();
-                    push_recbuf('!');
-                    lastchar='!';
-                    return c;
+                    command_done=true;
                 }
                 break;
         }
+        if(!retstr.empty()) push_recbuf(retstr);
+        if(command_done) {
+            //拡張コマンドとして処理した
+            localcomline.clear();
+            push_recbuf('!');
+            lastchar='!';
+            return c;
+        }
+        //拡張コマンドではなかったので Y-con P020に送る
         uart.puts(localcomline.c_str());
         uart.putc('\r');
         localcomline.clear();
@@ -274,70 +411,9 @@
     }
     return c;
 }
-bool skipspace(string::const_iterator &p, string::const_iterator end)
-{
-    while(*++p==' ') {
-        if(p==end) return false;
-    }
-    return true;
-}
-bool YconP020::commandline_D(const string &comline)
-{
-    string::const_iterator cp=comline.begin();
-    if(!skipspace(cp, comline.end())) return false;
-    switch(toupper(*cp)) {
-    case 'F':
-        if(*++cp==' ') {
-            while(*++cp==' ') {
-                if(cp==comline.end()) break;
-            }
-            if(cp<comline.end()) {
-                const string fn=comline.substr(cp-comline.begin());
-                if(dispfile(fn)!=NOERROR) push_recbuf("\r\n"+fn+" not found\r\n!");
-            }
-        } else {
-            const string fns=comline.substr(cp-comline.begin());
-            int fn=atoi(fns.c_str());
-            if(filelist.size()<fn || fn<0) push_recbuf("\r\nfile No."+fns+" not found\r\n!");
-            else dispfile(filelist[fn]);
-        }
-        return true;
-    case 'I':
-        display_internalbuf();
-        return true;
-    default:
-        return false;
-    }
-}
-bool YconP020::commandline_L(const string &comline)
-{
-    string::const_iterator cp=comline.begin();
-    if(toupper(*++cp)=='S') {
-        skipspace(cp,comline.end());
-        if(cp==comline.end()) {
-            //getfilelist();
-        } else if(*cp=='*') {
-            getfilelistall();
-        } else {
-            getfilelist(comline.substr(cp-comline.begin()));
-        }
-        for(vector<string>::const_iterator p=filelist.begin(); p<filelist.end(); p++) {
-            /* ostringstream を使うとメモリ(RAM)使用量が跳ね上がっちゃう
-            ostringstream s;
-            s << p-filelist.begin() <<": " << *p << "\r\n";
-            outputstr(s.str());
-            */
-            char buf[4];
-            sprintf(buf,"%3d",p-filelist.begin());
-            push_recbuf(string(buf)+": "+(*p)+"\r\n");
-        }
-        return true;
-    }
-    return false;
-}
 
-//sub-functions for execute commands
-void YconP020::void_command(const string& command, bool waitready)
+// Y-conP 020 のコマンドを関数化するためのヘルパー関数群
+void YconP020::send_command(const string& command, bool waitready)
 {
     use_recinbuf=true;
     command_mode();
@@ -346,70 +422,44 @@
     uart.putc('\r');
     if(waitready) wait_command_ready();
     use_recinbuf=false;
-    recinbuf.clear();
-    push_recbuf('!');
-}
-void YconP020::set_intparam(const string& command, int param)
+}    
+void YconP020::void_command(const string& command, bool waitready)
 {
-    use_recinbuf=true;
-    command_mode();
-    lastchar=' ';
-    uart.printf("%s %4d\r", command.c_str(), param);
-    wait_command_ready();
-    use_recinbuf=false;
+    send_command(command, waitready);
     recinbuf.clear();
-    push_recbuf('!');
+}
+void YconP020::set_param(const string& command, int param)
+{
+    send_command(command+' '+tostring(param));
+    recinbuf.clear();
 }
 int YconP020::get_intparam(const string& command, const string& retstr)
 {
+    send_command(command);
     int retval;
-    use_recinbuf=true;
-    command_mode();
-    lastchar=' ';
-    uart.puts(command.c_str());
-    uart.putc('\r');
-    wait_ms(100);
-    size_t i=recinbuf.find(retstr);
-    retval = atoi(recinbuf.substr(i+retstr.size()+1).c_str());
-    wait_command_ready();
-    use_recinbuf=false;
+    string::iterator p=search(recinbuf.begin(),recinbuf.end(),
+                                retstr.begin(),  retstr.end());
+    if(p!=recinbuf.end()) p+=retstr.size()+1;
+    retval=toint(p,recinbuf.end());
     recinbuf.clear();
-    push_recbuf('!');
     return retval;
 }
 bool YconP020::get_boolparam(const string& command)
 {
+    send_command(command);
     bool retval=false;
-    use_recinbuf=true;
-    command_mode();
-    lastchar=' ';
-    uart.puts(command.c_str());
-    uart.putc('\r');
-    wait_ms(100);
     if(recinbuf.find("Enable")!=string::npos) retval=true;
-    wait_command_ready();
-    use_recinbuf=false;
     recinbuf.clear();
-    push_recbuf('!');
     return retval;
 }
 string YconP020::get_stringparam(const string& command)
 {
-    use_recinbuf=true;
-    command_mode();
-    lastchar=' ';
-    uart.puts(command.c_str());
-    uart.putc('\r');
-    wait_command_ready();
-    use_recinbuf=false;
-    string retval;
-    string::const_iterator p=recinbuf.begin()+recinbuf.find(command)+command.size();
-    while(p<recinbuf.end()) {
-        if(*p=='!') break;
-        retval += *p++;
-    }
+    send_command(command);
+    string::iterator p=search(recinbuf.begin(),recinbuf.end(),
+                               command.begin(), command.end());
+    if(p!=recinbuf.end()) p+=command.size();
+    string retval(p,find(p,recinbuf.end(),'!'));
     recinbuf.clear();
-    push_recbuf('!');
     return retval;
 }