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) 

この広告は前回の更新から一定期間経過したブログに表示されています。更新すると自動で解除されます。