SSブログ

CH552でシリアル入力 [Arduino]

先日のスケッチをいじって、CH552のシリアル入力を使ってみました。
シリアル出力は、ちょっと癖があるらしいのですが、入力はそれほどむつかしいことはありませんでした。



ふつうのArduinoとCh55xduinoでちょっと違うところ。
・配列の宣言に __xdata
・関数の宣言と定義が必要 (CとC++の違いらしい)
・PROGMEMのデータの読み取りは "pgm_read_~"なし
・shiftOutがなかった (MSBFIRST、16ビット専用のコードを作ってみた)
・USBSerialは通信速度とか関係なし? (300bpsでも2000000bpsでも送信できた)

以下、拙いソース
// Flowing text string from serial input <<CH552 version>>
// Quadruple Matrix LED Driven by MAX7219 
uint8_t CLK = 15;       // to MAX7219 CLOCK
uint8_t CS  = 16;       // to MAX7219 LOAD(~CS)
uint8_t DAT = 17;       // to MAX7219 DIN
uint8_t BUF[32] = {0};  // matrix LED image [ring buffer]
uint8_t pBUF  = 0;      // display start position in BUF
uint8_t pTEXT = 0;      // start position in TEXT string
uint8_t pCHAR = 4;      // start position in character (left:3or4, right:0)
uint8_t fPROP = 1;      // blanks on the left side of characters (0:no, 1:yes) (for proportional font)
__xdata char  TEXT[256]  = "Hello world!";

static const uint32_t FONT4x8[] PROGMEM = {
  0x00000000, 0x000000BF, 0x00030003, 0xF42FF42F, 0x44EA4B32, 0x2313C8C4, 0xE6996690, 0x00000403, //  !"#$%&'
  0x003C4281, 0x0081423C, 0x00140814, 0x00103810, 0x00008060, 0x00101010, 0x00000080, 0xC0300C03, // ()*+,-./
  0x7E91897E, 0x0082FF80, 0xE291918E, 0x42898976, 0x3826FF20, 0x4F898971, 0x7E898972, 0x01E11907, // 01234567
  0x76898976, 0x4E91917E, 0x00006666, 0x0080E666, 0x18244281, 0x28282828, 0x81422418, 0x0201B10E, // 89:;<=>?
  0x7E81995E, 0xFE1111FE, 0xFF898976, 0x7E818166, 0xFF81817E, 0xFF898989, 0xFF090901, 0x7E8191F2, // @ABCDEFG
  0xFF0808FF, 0x0081FF81, 0x80817F01, 0xFF0814E3, 0xFF808080, 0x061806ff, 0xFF0618FF, 0x7E81817E, // HIJKLMNO
  0xFF11110E, 0x3E4171BE, 0xFF11718E, 0x46899162, 0x01FF0101, 0x7F80807F, 0x3FC0601F, 0xe018e01f, // PQRSTUVW
  0xF70808F7, 0x07F80807, 0xC1B18D83, 0x00FF8181, 0x030C30C0, 0x008181FF, 0x00060106, 0x80808080, // XYZ[\]^_
  0x00010204, 0x609494F8, 0xFE909060, 0x78848448, 0x609090FE, 0x78949458, 0x08FC0A0A, 0x18A4A47E, // `abcdefg
  0xFE0808F0, 0x000000FA, 0x0080807A, 0xFE205088, 0x00007E80, 0x04f804f8, 0xFc0404F8, 0x78848478, // hijklmno
  0xFC242418, 0x182424FC, 0xFC100808, 0x4894A448, 0x087E8888, 0x7C80807C, 0x7C80403C, 0xc020c03c, // pqrstuvw
  0xEC1010EC, 0x0C90907C, 0xC4A4948C, 0x00187E81, 0x000000FF, 0x00817E18, 0x10081008 };           // xyz{|}~

void ledOut( uint16_t, uint16_t, uint16_t, uint16_t );
void refreshLED();

void setup() {
  pinMode( CLK, OUTPUT );
  pinMode( CS , OUTPUT );
  pinMode( DAT, OUTPUT );
  ledOut( 0x0F00, 0x0F00, 0x0F00, 0x0F00 );     // Display Test(0xXF): Normal Operation (0)
  ledOut( 0x0B07, 0x0B07, 0x0B07, 0x0B07 );     // Scan Limit  (0xXB): Display all digits (7)
  ledOut( 0x0A01, 0x0A01, 0x0A01, 0x0A01 );     // Intensity   (0xXA): Luminance (0-F)
  ledOut( 0x0900, 0x0900, 0x0900, 0x0900 );     // Decode Mode (0xX9): No decode (00)
  ledOut( 0x0C01, 0x0C01, 0x0C01, 0x0C01 );     // Shutdown    (0xXC): Normal Operation (0)
}

void loop() {
      /*** Get string from serial ***/ 
  char rx, pRx = 0;                             // Receive data length
  while( USBSerial_available() ) {
    rx = USBSerial_read();
    if( rx == '\n' || rx == '\r' ) break;       // Exit if end of string
    TEXT[pRx++] = rx;                           // Add character
    if( pRx == sizeof(TEXT) - 1 ) break;        // Exit if buffer is full
  }
  if( pRx ) {                                   // if the data is not empty..
    TEXT[pRx] = '\0';                           // terminate a string
    pCHAR = (pTEXT) ? 36 : pCHAR;               // insert spaces to the next string
    pTEXT = 0;                                  // reset display start position
    while( USBSerial_available() ) USBSerial_read();    // discard the rest of the data
  }
      /*** Scroll the text ***/
  char c = TEXT[ pTEXT ];                       // character to display
  refreshLED();
  delay(200);
  if( pCHAR >  4 ) BUF[pBUF] = 0;               // display blank
  if( pCHAR == 4 ) switch( c ) {                // for blank or 5-dot width
      case ' ':  fPROP = 0; pCHAR = 1;         break;
      case 'M':  fPROP = 0; BUF[pBUF] = 0xFF;  break;
      case 'm':  fPROP = 0; BUF[pBUF] = 0xFC;  break;
      case 'W':  fPROP = 0; BUF[pBUF] = 0x1F;  break;
      case 'w':  fPROP = 0; BUF[pBUF] = 0x3c;  break;
      default :  pCHAR--;                       // Move character display start position
  }
  if( pCHAR <  4 ) {
    BUF[pBUF] = FONT4x8[ c-' ' ] >> ( pCHAR * 8 );
    while( !BUF[pBUF] && fPROP ) BUF[pBUF] = FONT4x8[ c-' ' ] >> ( --pCHAR * 8 );   // remove blanks
    fPROP = 0;
  }
  if( !pCHAR-- ) {                              // When finished displaying a character
    fPROP = 1;                                  // revert flag
    if( TEXT[++pTEXT] ) pCHAR = 5;              // If there is a following character
    else { pTEXT = 0;   pCHAR = 36; }           // Reset display start position
  }
  pBUF = ++pBUF %32;                            // Move display start position of ring buffer
}

void ledOut( uint16_t d0, uint16_t d1, uint16_t d2, uint16_t d3 ) {
  uint16_t d[]={ d0, d1, d2, d3 };
  digitalWrite( CS, LOW );
  for(uint8_t n=0; n<4; n++) {
    for (uint8_t i=15; i<16; i--)  {      // shiftOut MSBFIRST 16bit
      digitalWrite( DAT, ( d[n]>>i ) & 1 );
      digitalWrite( CLK, HIGH );
      digitalWrite( CLK, LOW  );
    }
  }
  digitalWrite( CS, HIGH );
}

void refreshLED() {
  uint8_t d[4];
  for(uint8_t m=0; m<8; m++) {            // matrix LED data line
    for(uint8_t b=0; b<8; b++) {          // bit
      for(uint8_t n=0; n<4; n++) {        // Number of LEDs
        d[n] = d[n]<<1 | ((BUF[(b+n*8+pBUF)%32]>>m) & 1);
      }
    }
    ledOut(((m+1)<<8)+d[0], ((m+1)<<8)+d[1], ((m+1)<<8)+d[2], ((m+1)<<8)+d[3] );
  }
}

今のところCh55xduinoは、とりあえずArduino用にスケッチ作ってそれを移植するという感じです。

nice!(0)  コメント(0) 

4連マトリックスLEDで文字列を流す [Arduino]

4連マトリックスLEDで文字列を流してみたいと思います。
とりあえず半角英数・記号のみ。
漢字を扱うことの問題は、フォントの著作権と文字コードです。
ということで英数・記号フォントを自作しました。
diyfontexcel.jpg
・基本4×8ドットをいっぱいに使う
・見栄えとスペースの節約のためにプロポーショナルフォント
・4ドット幅だと表現が厳しい"M","W","m","w"は1ドット追加
としました。



// Quadruple Matrix LED Driven by MAX7219
//  *** flowing text string ***
uint8_t CLK = 13;       // to MAX7219 CLOCK
uint8_t CS  = 10;       // to MAX7219 LOAD(~CS)
uint8_t DAT = 11;       // to MAX7219 DIN
uint8_t BUF[32] = {0};  // matrix LED image [ring buffer]
uint8_t pBUF  = 0;      // display start position in BUF
uint8_t pTEXT = 0;      // start position in TEXT string
uint8_t pCHAR = 4;      // start position in character (left:3or4, right:0)
uint8_t fPROP = 1;      // blanks on the left side of characters (0:no, 1:yes) (for proportional font)
char    TEXT[128]  = "Hello world !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~";

static const uint32_t FONT4x8[] PROGMEM = {
  0x00000000, 0x000000BF, 0x00030003, 0xF42FF42F, 0x44EA4B32, 0x2313C8C4, 0xE6996690, 0x00000403, //  !"#$%&'
  0x003C4281, 0x0081423C, 0x00140814, 0x00103810, 0x00008060, 0x00101010, 0x00000080, 0xC0300C03, // ()*+,-./
  0x7E91897E, 0x0082FF80, 0xE291918E, 0x42898976, 0x3826FF20, 0x4F898971, 0x7E898972, 0x01E11907, // 01234567
  0x76898976, 0x4E91917E, 0x00006666, 0x0080E666, 0x18244281, 0x28282828, 0x81422418, 0x0201B10E, // 89:;<=>?
  0x7E81995E, 0xFE1111FE, 0xFF898976, 0x7E818166, 0xFF81817E, 0xFF898989, 0xFF090901, 0x7E8191F2, // @ABCDEFG
  0xFF0808FF, 0x0081FF81, 0x80817F01, 0xFF0814E3, 0xFF808080, 0x061806ff, 0xFF0618FF, 0x7E81817E, // HIJKLMNO
  0xFF11110E, 0x3E4171BE, 0xFF11718E, 0x46899162, 0x01FF0101, 0x7F80807F, 0x3FC0601F, 0xe018e01f, // PQRSTUVW
  0xF70808F7, 0x07F80807, 0xC1B18D83, 0x00FF8181, 0x030C30C0, 0x008181FF, 0x00060106, 0x80808080, // XYZ[\]^_
  0x00010204, 0x609494F8, 0xFE909060, 0x78848448, 0x609090FE, 0x78949458, 0x08FC0A0A, 0x18A4A47E, // `abcdefg
  0xFE0808F0, 0x000000FA, 0x0080807A, 0xFE205088, 0x00007E80, 0x04f804f8, 0xFc0404F8, 0x78848478, // hijklmno
  0xFC242418, 0x182424FC, 0xFC100808, 0x4894A448, 0x087E8888, 0x7C80807C, 0x7C80403C, 0xc020c03c, // pqrstuvw
  0xEC1010EC, 0x0C90907C, 0xC4A4948C, 0x00187E81, 0x000000FF, 0x00817E18, 0x10081008 };           // xyz{|}~

void setup() {
  pinMode( CLK, OUTPUT );
  pinMode( CS , OUTPUT );
  pinMode( DAT, OUTPUT );
  ledOut( 0x0F00, 0x0F00, 0x0F00, 0x0F00 );     // Display Test(0xXF): Normal Operation (0)
  ledOut( 0x0B07, 0x0B07, 0x0B07, 0x0B07 );     // Scan Limit  (0xXB): Display all digits (7)
  ledOut( 0x0A01, 0x0A01, 0x0A01, 0x0A01 );     // Intensity   (0xXA): Luminance (0-F)
  ledOut( 0x0900, 0x0900, 0x0900, 0x0900 );     // Decode Mode (0xX9): No decode (00)
  ledOut( 0x0C01, 0x0C01, 0x0C01, 0x0C01 );     // Shutdown    (0xXC): Normal Operation (0)
}

void loop() {
  char c = TEXT[ pTEXT ];                       // character to display
  refreshLED();
  delay(200);
  if( pCHAR >  4 ) BUF[pBUF] = 0;               // display blank
  if( pCHAR == 4 ) switch( c ) {                // for blank or 5-dot width
      case ' ':  fPROP = 0; pCHAR = 1;         break;
      case 'M':  fPROP = 0; BUF[pBUF] = 0xFF;  break;
      case 'm':  fPROP = 0; BUF[pBUF] = 0xFC;  break;
      case 'W':  fPROP = 0; BUF[pBUF] = 0x1F;  break;
      case 'w':  fPROP = 0; BUF[pBUF] = 0x3c;  break;
      default:   pCHAR--;                       // Move character display start position
  }
  if( pCHAR <  4 ) {
    BUF[pBUF] = pgm_read_dword(FONT4x8 + c-' ') >> ( pCHAR * 8 );       // if you don't use PROGMEM -> FONT4x8[ c-' ' ] 
    while( !BUF[pBUF] && fPROP ) BUF[pBUF] = pgm_read_dword(FONT4x8 + c-' ') >> ( --pCHAR * 8 );   // remove blanks
    fPROP = 0;
  }
  if( !pCHAR-- ) {                              // When finished displaying a character
    fPROP = 1;                                  // revert flag
    if( TEXT[++pTEXT] ) pCHAR = 5;              // If there is a following character
    else { pTEXT = 0;   pCHAR = 36; }           // Reset display start position
  }
  ++pBUF %= 32;                                 // Move display start position of ring buffer
}

void ledOut( uint16_t d0, uint16_t d1, uint16_t d2, uint16_t d3 ) {
  uint16_t d[]={ d0, d1, d2, d3 };
  digitalWrite( CS, LOW );
  for(uint8_t n=0; n<4; n++) {
    shiftOut( DAT, CLK, MSBFIRST, d[n]>>8 );
    shiftOut( DAT, CLK, MSBFIRST, d[n]    );
  }
  digitalWrite( CS, HIGH );
}

void refreshLED() {
  uint8_t d[4];
  for(uint8_t m=0; m<8; m++) {            // matrix LED data line
    for(uint8_t b=0; b<8; b++) {          // bit
      for(uint8_t n=0; n<4; n++) {        // Number of LEDs
        d[n] = d[n]<<1 | ((BUF[(b+n*8+pBUF)%32]>>m) & 1);
      }
    }
    ledOut(((m+1)<<8)+d[0], ((m+1)<<8)+d[1], ((m+1)<<8)+d[2], ((m+1)<<8)+d[3] );
  }
}


タグ:Matrix LED
nice!(0)  コメント(0) 

CH552Eduinoをつくってみた。 [Arduino]

ちいさいものが好きなので、CH552EのテストボードをKiCadで設計してみました。

・メインのCH552Eは裏面に
・リセットボタン・ブートローダボタンはほぼ使う機会がなかったので省略
・USBとの接続ピン(UDP, UDM)(UDPはブートローダにも)はブレットボードには使わない位置へ
・USBとの接続ピン以外はICピン配列順にしたかったけど、リセットピンだけ引き回せず別位置へ
・リセッタブルヒューズなど安全性の配慮はなし
・外部電源非対応(USB type-C only)
・そのかわりに、ちゃんとCC1, CC2に5.1kΩの抵抗はつける

2バージョン作成。
ch552eduino_m_pcb.jpg
ch552eduino_w_pcb.jpg
3Dイメージ
ch552eduino_m_3d.jpg
ch552eduino_w_3d.jpg
これらの基板を発注してしばらく待ちます。

先日、基板が届いたので、チップ抵抗、チップキャパシタ、USB-Cレセプタクルを載せてみました。
できあがりサイズは、USB type-C DIP変換基板とか、USB-TTL変換基板くらいのサイズです。

ch552ge_f.jpg
ch552ge_b.jpg
チップ部品のはんだ付けは、まだまだ難儀しています。
先日の演奏スケッチで動作確認できました。
nice!(0)  コメント(0)