Y-con P020 Electric Paper Display
This is a library for Y-con P020 Electric Paper Display.
sample program is here.
詳しくはこちら(sorry only in Japanese)をご覧ください。
Diff: YconP020.cpp
- 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; }