RL78/G15 FPB と USBシリアル変換モジュール [Arduino]
自作 RL78/G15 Fast Prototyping Board のUSBインターフェイスに、これまで一番差し障りのないFTDI FT232 シリーズでやっていましたが、他のものはどうでしょう?
DTR#が出ていればよさそうなので、CH340Cが載ったやつで試してみました。
結果はOKでした。
USB type-Cで気持ちいい。
さらに、書き込みに30秒かかっていたのが、5秒もかからなくなりました。
本家より優秀になっている。
<追加報告>
CP2102のUSBシリアル変換モジュールが出てきたので試してみたら、こちらはダメでした。
DTR#が出ていればよさそうなので、CH340Cが載ったやつで試してみました。
結果はOKでした。
USB type-Cで気持ちいい。
さらに、書き込みに30秒かかっていたのが、5秒もかからなくなりました。
本家より優秀になっている。
<追加報告>
CP2102のUSBシリアル変換モジュールが出てきたので試してみたら、こちらはダメでした。
RL78/G15 FPB の tone()関数で和音 [Arduino]
RL78/G15 のレジスタを直接いじるの大変そう。PWM作るのにもe2stdioとかいうのを使ってやるみたい。
そこでtone()関数をみてみると、、
RL78G15 20ピン Fast Prototyping Board ピンリスト · renesas_Arduino Wiki · GitHub
https://github.com/renesas/Arduino/wiki/RL78G15-20%E3%83%94%E3%83%B3-Fast-Prototyping-Board-%E3%83%94%E3%83%B3%E3%83%AA%E3%82%B9%E3%83%88
2-7. Tone のところで、Tone output pinに指定できるのは、Arduino 0番, 3番, 13番の3つ。
3つ同時に使えるかと思ったら、3番, 13番を同時に使うのはダメで2和音まででした。
第5オクターブで曲データを作っています。
これより低い音はうまく出せないみたい。
楽譜データの音符などは、notes2.h で。
Digisparkで音楽演奏【楽譜編】
https://hello-world.blog.ss-blog.jp/2022-07-04
そこでtone()関数をみてみると、、
RL78G15 20ピン Fast Prototyping Board ピンリスト · renesas_Arduino Wiki · GitHub
https://github.com/renesas/Arduino/wiki/RL78G15-20%E3%83%94%E3%83%B3-Fast-Prototyping-Board-%E3%83%94%E3%83%B3%E3%83%AA%E3%82%B9%E3%83%88
2-7. Tone のところで、Tone output pinに指定できるのは、Arduino 0番, 3番, 13番の3つ。
3つ同時に使えるかと思ったら、3番, 13番を同時に使うのはダメで2和音まででした。
// RL78/G15 FPB tone function test
#include "notes2.h" // Definition data of notes ( pitch (scale & octave), and note value (length))
#define MAX_TRACK 2 // Maximum number of tracks
const uint8_t ToneOutputPin[] = { 0, 13 }; // two of 0,3,13 pins (No combination of 3 and 13)
const uint16_t F_SCALE[] = { 33488, 35479, 37589, 39824, 42192, 44701, 47359, 50175, 53159, 56320, 59669, 63217 };
// basic frequency of 12-note scale (from C11 to B11)(Hz)
const uint16_t Frogs[] = { // melody data
120 , 0 ,
c5q , d5q , e5q , f5q , e5q , d5q , c5q , RSq , e5q , f5q , g5q , a5q , g5q , f5q , e5q , RSq ,
c5q , RSq , c5q , RSq , c5q , RSq , c5q , RSq , c5e , c5e , d5e , d5e , e5e , e5e , f5e , f5e ,
e5q , d5q , c5q , RSq , RSd , RSd , 0 ,
RSd ,
c5q , d5q , e5q , f5q , e5q , d5q , c5q , RSq , e5q , f5q , g5q , a5q , g5q , f5q , e5q , RSq ,
c5q , RSq , c5q , RSq , c5q , RSq , c5q , RSq , c5e , c5e , d5e , d5e , e5e , e5e , f5e , f5e ,
e5q , d5q , c5q , RSq , RSd , 0 , 0 };
void setup(){
}
void loop(){
const uint16_t *d = Frogs; // Pointer of melody data
const uint16_t *p[MAX_TRACK]; // Pointer for each track of the score
uint8_t Tracks, t; // Number of tracks and counter
uint16_t note; // Note (pitch + note value) information
uint8_t len[MAX_TRACK] = {}; // Length of note (how many 96th notes) (subtraction counter)
uint32_t usInt, usExp; // sound division interval, sound expire time(usec)
usInt = 1000000*60*4 / MIN_NOTE / *d++; // Calculate standard 96th note length(usec) from tempo
for( Tracks=0; Tracks<MAX_TRACK; ) { // Get the number of tracks and the start position of each track from the song data
if( *d++ != 0 ) continue; // Skip until the break comes
if( *d == 0 ) break; // If two zeros follow, end of data
p[ Tracks++ ] = d; // Get location in memory, Count up the number of tracks
}
usExp = micros();
do { // Processing of score for each reference note(96th note) length
for( t=0; t<Tracks; t++) {
if( !len[t]-- ) { // Subtract the length of the note, and when it reaches 0, go to the next note
if( !(note = *p[t]++) ) return; // end if note = 0
len[t] = (note & 0x00ff) - 1; // The lower 8 bits are the length of the note (how many times the length of a 96th note)
if(note & 0xff00) // note(16bit) : Upper 4 bits are octave, next 4 bits are pitch class (0-11)
tone( ToneOutputPin[t], F_SCALE[(note>>8)&0x0f] >> (11-(note>>12)), 0 );
else noTone( ToneOutputPin[t] ); // 0 for rests
}
}
usExp += usInt;
while( micros() < usExp ); // wait until expiration
} while( note );
for( t=0; t<Tracks; t++) noTone( ToneOutputPin[t] ); // stop all sounds
delay(1000);
}
第5オクターブで曲データを作っています。
これより低い音はうまく出せないみたい。
楽譜データの音符などは、notes2.h で。
Digisparkで音楽演奏【楽譜編】
https://hello-world.blog.ss-blog.jp/2022-07-04
タグ:RL78/G15
RL78/G15 FPB 自作してみた。 [Arduino]
こんな感じで、RL78/G15をDIP化およびシリアル書き込み周辺の抵抗などを載せ、Arduino Pro Miniなどで使うUSBシリアル変換アダプタを使用してスケッチを書き込むことができました。
(秋月電子通商のAE-UM232Rでも行けました。)
シリアルポートを使用した RL78 デバッグ機能
https://www.renesas.com/jp/ja/document/apn/rl78-debugging-functions-using-serial-port-application-note
できるだけジャンプワイヤーを使用しなくていいように、DIP化基板に抵抗などを載せました。
RL78/G15(R5F12068MSP)の5番(RESET#)のラインを切断し、チップ抵抗 1kΩを挟む。
裏面は、電源部にキャパシタ。他、1kΩ、2kΩ(がなかったので2.2kΩ)を接続しました。
PDFには、DTRがない場合はRTSも使えるけど「RTSを使う場合は必ずプロパティの設定変更を行ってください。」とのこと。
他、Arduino IDEのシリアルモニタ等を使う場合は、「74LVC1G126」というパーツが必要らしい。RL78/G15 FPBにも載っている。
Arduino上でのピン番号とのIC上のピンとの対応
Lチカ サンプル
タグ:RL78/G15
RL78/G15 Fast Prototyping Board 買ってみた。 [Arduino]
Renesas RL78/G15 を使った Arduinoっぽいボードを発見したので購入しました。
マルツで売ってました。
<参考URL>
RTK5RLG150C00000BJ - RL78/G15 Fast Prototyping Board | Renesas
https://www.renesas.com/jp/ja/products/microcontrollers-microprocessors/rl78-low-power-8-16-bit-mcus/rtk5rlg150c00000bj-rl78g15-fast-prototyping-board
RL78/G15 FAST PROTOTYPING BOARD RTK5RLG150C00000BJ ルネサスエレクトロニクス(Intersil・IDT)製|電子部品・半導体通販のマルツ
https://www.marutsu.co.jp/pc/i/43306583/
ホーム · renesas/Arduino Wiki · GitHub
https://github.com/renesas/Arduino/wiki/%E3%83%9B%E3%83%BC%E3%83%A0
ボードマネージャファイル
・RL78/G15-20p Fast Prototyping Board
https://raw.githubusercontent.com/renesas/Arduino/master/hardware/package_index_rl78g15_fpb_p20_bundled.json
<とりあえずサンプル>
スケッチ例あるBlinkはそのままではうごきませんでした。
#define LED_BUILTIN 24
となっているようです。
ボード上に2つLEDがついていて、LED1がArduino上のデジタル7番(IC 2番ピン, P20)で、LED2がArduino上のデジタル4番(IC 1番ピン, P21)となっていました。
#define LED1_BUILTIN 7
#define LED2_BUILTIN 4
void setup() {
pinMode(LED1_BUILTIN, OUTPUT);
pinMode(LED2_BUILTIN, OUTPUT);
}
void loop() {
digitalWrite(LED1_BUILTIN, HIGH);
digitalWrite(LED2_BUILTIN, LOW);
delay(500);
digitalWrite(LED1_BUILTIN, LOW);
digitalWrite(LED2_BUILTIN, HIGH);
delay(500);
}
このスケッチ書き込みに30秒くらいかかる。なんでだろう。
タグ:RL78/G15
CH552でシリアル入力 [Arduino]
先日のスケッチをいじって、CH552のシリアル入力を使ってみました。
シリアル出力は、ちょっと癖があるらしいのですが、入力はそれほどむつかしいことはありませんでした。
ふつうのArduinoとCh55xduinoでちょっと違うところ。
・配列の宣言に __xdata
・関数の宣言と定義が必要 (CとC++の違いらしい)
・PROGMEMのデータの読み取りは "pgm_read_~"なし
・shiftOutがなかった (MSBFIRST、16ビット専用のコードを作ってみた)
・USBSerialは通信速度とか関係なし? (300bpsでも2000000bpsでも送信できた)
以下、拙いソース
今のところCh55xduinoは、とりあえずArduino用にスケッチ作ってそれを移植するという感じです。
シリアル出力は、ちょっと癖があるらしいのですが、入力はそれほどむつかしいことはありませんでした。
ふつうの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用にスケッチ作ってそれを移植するという感じです。
4連マトリックスLEDで文字列を流す [Arduino]
4連マトリックスLEDで文字列を流してみたいと思います。
とりあえず半角英数・記号のみ。
漢字を扱うことの問題は、フォントの著作権と文字コードです。
ということで英数・記号フォントを自作しました。
・基本4×8ドットをいっぱいに使う
・見栄えとスペースの節約のためにプロポーショナルフォント
・4ドット幅だと表現が厳しい"M","W","m","w"は1ドット追加
としました。
とりあえず半角英数・記号のみ。
漢字を扱うことの問題は、フォントの著作権と文字コードです。
ということで英数・記号フォントを自作しました。
・基本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
CH552Eduinoをつくってみた。 [Arduino]
ちいさいものが好きなので、CH552EのテストボードをKiCadで設計してみました。
・メインのCH552Eは裏面に
・リセットボタン・ブートローダボタンはほぼ使う機会がなかったので省略
・USBとの接続ピン(UDP, UDM)(UDPはブートローダにも)はブレットボードには使わない位置へ
・USBとの接続ピン以外はICピン配列順にしたかったけど、リセットピンだけ引き回せず別位置へ
・リセッタブルヒューズなど安全性の配慮はなし
・外部電源非対応(USB type-C only)
・そのかわりに、ちゃんとCC1, CC2に5.1kΩの抵抗はつける
2バージョン作成。
3Dイメージ
これらの基板を発注してしばらく待ちます。
先日、基板が届いたので、チップ抵抗、チップキャパシタ、USB-Cレセプタクルを載せてみました。
できあがりサイズは、USB type-C DIP変換基板とか、USB-TTL変換基板くらいのサイズです。
チップ部品のはんだ付けは、まだまだ難儀しています。
先日の演奏スケッチで動作確認できました。
・メインのCH552Eは裏面に
・リセットボタン・ブートローダボタンはほぼ使う機会がなかったので省略
・USBとの接続ピン(UDP, UDM)(UDPはブートローダにも)はブレットボードには使わない位置へ
・USBとの接続ピン以外はICピン配列順にしたかったけど、リセットピンだけ引き回せず別位置へ
・リセッタブルヒューズなど安全性の配慮はなし
・外部電源非対応(USB type-C only)
・そのかわりに、ちゃんとCC1, CC2に5.1kΩの抵抗はつける
2バージョン作成。
3Dイメージ
これらの基板を発注してしばらく待ちます。
先日、基板が届いたので、チップ抵抗、チップキャパシタ、USB-Cレセプタクルを載せてみました。
できあがりサイズは、USB type-C DIP変換基板とか、USB-TTL変換基板くらいのサイズです。
チップ部品のはんだ付けは、まだまだ難儀しています。
先日の演奏スケッチで動作確認できました。
楽譜再生スケッチをCH552に移植してみた。 [Arduino]
以前につくった楽譜再生スケッチをCH552用に移植してみました。
音楽は、パッヘルベルのカノンのリンナイお風呂バージョンを3和音アレンジにしてみました。
CH552での感想
・プログラムサイズが大きくなると各所で書いてあったが、かなり大きくなり驚いた。
・いままで256クロックで4和音行けていたのが、2和音しか行けなくなった。
どうやら、プログラムサイズ的にも速度的にも、コンパイラの効率がわるいみたい。
拙いスケッチです。
"note2.h" は以下参照
Digisparkで音楽演奏【楽譜編】
https://hello-world.blog.ss-blog.jp/2022-07-04
(参考にさせていただいたところ)
ch55xduinoでタイマ割り込み|akita11|note
https://note.com/akita11/n/ne4f2a2fb7c70
音楽は、パッヘルベルのカノンのリンナイお風呂バージョンを3和音アレンジにしてみました。
CH552での感想
・プログラムサイズが大きくなると各所で書いてあったが、かなり大きくなり驚いた。
・いままで256クロックで4和音行けていたのが、2和音しか行けなくなった。
どうやら、プログラムサイズ的にも速度的にも、コンパイラの効率がわるいみたい。
拙いスケッチです。
// CH552 version Score Replay Sketch
// boards manager URL : https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
// Board : CH55x Boards > CH552 Board
// Clock : 24/16/12 MHz
#if !defined(CH552) && !defined(CH551)
#error "Only compatible with CH552 and CH551"
#endif
#include "notes2.h" // Definition data of notes ( pitch (scale & octave), and note value (length))
#define MAX_TRACK 4 // Maximum number of tracks
// Number of cycles that are the wavelength of the basic 12-note scale (from C0 to B0) (with an interrupt every 512 clocks)
#if F_CPU == 24000000L
static const uint16_t CYC_SCALE[] = { 2867, 2706, 2554, 2411, 2275, 2148, 2027, 1913, 1806, 1705, 1609, 1519 };
#elif F_CPU == 16000000L
static const uint16_t CYC_SCALE[] = { 1911, 1804, 1703, 1607, 1517, 1432, 1351, 1276, 1204, 1136, 1073, 1012 };
#elif F_CPU == 12000000L
static const uint16_t CYC_SCALE[] = { 1433, 1353, 1277, 1205, 1138, 1074, 1014, 957, 903, 852, 804, 759 };
#endif
static const uint16_t Rinnai[] PROGMEM = { // "Canon in D" by Johann Pachelbel
110 , 0 ,
a5e , F5s , g5s , a5e , F5s , g5s, a5s , a4s , b4s , C5s , d5s , e5s , F5s , g5s ,
F5e , d5s , e5s , F5e , F4s , g4s , a4s , b4s , a4s , g4s , a4s , d5s , C5s , d5s ,
g4e , b4s , a4s , g4e , F4s , e4s , F4s , e4s , d4s , e4s , F4s , g4s , a4s , b4s ,
g4e , b4s , a4s , b4e , C5s , d5s , C5s , d5s , e5s , F5s , g5s , a5s , b5s , C6s ,
F5s , a5s , d6qt| LNh , 0 ,
F4q , d5q , C5h , RSq , b4q , d5h , d4hd, d4q , d4q , g4q , e4q , C5q , d5w , 0 ,
d4q , F4q , e4q , a2q , b2q , d4q , F4q , F2q , b3q , g2q , a3q , d3q , RSq , g2q , C4q , a2q , d4w , 0 , 0 };
void play552PWM(const uint16_t*);
void setup(){
// *** PWM pin setteings (P1.5, PWM) *** = pinMode( 15, OUTPUT ); but you can save about 500 bytes
PIN_FUNC &= ~(bPWM1_PIN_X); // Pin Function Select Register: 0(PWM1 use P1.5)
P1_MOD_OC &= ~(1<<5); // P1 output mode register: 0(pull output)
P1_DIR_PU |= 1<<5 ; // P1 direction control and pull-up enable register: 1(output)
// *** Register Settings (PWM1 for DAC) ***
PWM_CK_SE = 1; // PWM_CK_SE(PWM clock divided Frequency setting register)
PWM_CTRL |= bPWM1_OUT_EN; // PWM_CTRL: PWM1 Output Enable
// *** Register Settings (TIMER1 for Data) *** Data processing interval 31.25kHz(768clk@24MHz)
TR2 = 0; // T2CON: Timer2 start/stop bit: stop (for initial setting)
C_T2 = 0; // T2CON: Timer2 clock source select bit: using the internal clock
T2MOD |= bTMR_CLK | bT2_CLK; // T2MOD: Set Fsys(24/16/12MHz) to Timer2 clock
RCAP2H = 0xfe; RCAP2L = 0x00; // RCAP2(reload count/capture data register 2): Reload value on overflow(65536-512=65024=0xfe00, 24MHz/512=46,875Hz (Interrupt frequency))
TH2 = RCAP2H; TL2 = RCAP2L; // T2COUNT: Timer2 counter, Initialize Timer2 count value with reload value (RCAP2)
TF2 = 0; // T2CON: Timer2 overflow interrupt flag
TR2 = 1; // T2CON: Timer2 start/stop bit: start
}
void loop(){
play552PWM( Rinnai ); // Playback
delay(5000);
}
void play552PWM(const uint16_t *d){ // CH552 PWM version (24/16/12 MHz support)
uint8_t Tracks; // Number of tracks
const uint16_t *NoteP[MAX_TRACK]; // Pointer for each track of the score
uint16_t NoteCycle, n; // Number of interrupt cycles required for the length of the reference note (96th note) and its counter (n)
uint16_t note = 0; // Note (pitch + note value) information read from PROGMEM
uint8_t len[MAX_TRACK]; // Length of note (how many 96th notes) (subtraction counter)
uint16_t cyc[MAX_TRACK], c[MAX_TRACK];// Number of interrupt cycles (cyc) required for one sound wavelength cycle and its counter (c)
uint16_t env[MAX_TRACK]; // Sound amplitude (envelope)
uint16_t out[MAX_TRACK]; // Output value
uint8_t lap = 20; // Sound transitional cycles(laptime) (for Attenuation calculator)
// *** Preparing Scores ***
NoteCycle = F_CPU /512 *4 *60 / *d++ /MIN_NOTE; // Number of cycles required for reference note
for( Tracks = 0; Tracks < MAX_TRACK; ) { // Get the number of tracks and the start position of each track from the song data
if( *d++ != 0 ) continue; // Skip until the break comes
if( *d == 0 ) break; // If two zeros follow, end of data
len[ Tracks ] = 1; // Initialize the note length subtraction counter to the remaining 1
NoteP[ Tracks++ ] = d; // Get location in memory, Count up the number of tracks
}
n = Tracks; // Initialize the score processing so that it can be performed immediately after the start of the do loop
// *** Playback ***
do {
// * Processing Scores *
if( --n < Tracks ) { // Processing of score for each reference note length
if( !--len[n] ) {
note = *NoteP[n]++;
len[n] = (uint8_t) note; // The lower 8 bits are the length of the note (how many times the length of a 96th note)
cyc[n] = (note>>8) ? CYC_SCALE[ (note>>8) & 0xf ] >> (note>>12) : 0; // Upper 4 bits are octave, next 4 bits are pitch class (0-11), 0 for rests
c[n] = 0; // Initialize the counter for the number of cycles to create one square wave cycle
env[n] = 0xffff; // Initially, the maximum amplitude
}
if( !n ) n = NoteCycle;
}
// * Waveform Processing / Output *
switch( Tracks ) { // Create output data, Square wave with duty ratio of 1:1
case 4: out[3] = ( ( c[3] = (++c[3]==cyc[3]) ? 0 : c[3] ) < (cyc[3]>>1) ) ? env[3] : 0; // [[fallthrough]]; // C++
case 3: out[2] = ( ( c[2] = (++c[2]==cyc[2]) ? 0 : c[2] ) < (cyc[2]>>1) ) ? env[2] : 0; // [[fallthrough]]; // C++
case 2: out[1] = ( ( c[1] = (++c[1]==cyc[1]) ? 0 : c[1] ) < (cyc[1]>>1) ) ? env[1] : 0; // [[fallthrough]]; // C++
case 1: out[0] = ( ( c[0] = (++c[0]==cyc[0]) ? 0 : c[0] ) < (cyc[0]>>1) ) ? env[0] : 0;
}
switch( Tracks ) { // Change output by number of tracks
case 1: PWM_DATA1 = out[0] >>8; break;
case 2: PWM_DATA1 = ((out[0]>>1) + (out[1]>>1)) >>8; break;
case 3: PWM_DATA1 = ((out[0]>>1) + (out[1]>>2) + (out[2]>>2)) >>8; break;
case 4: PWM_DATA1 = ((out[0]>>2) + (out[1]>>2) + (out[2]>>2) + (out[3]>>2)) >>8;
}
switch( --lap ) { // Amplitude attenuation (Distribute processing per loop)
case 4: env[3] -= (env[3]>>9); break;
case 3: env[2] -= (env[2]>>9); break;
case 2: env[1] -= (env[1]>>9); break;
case 1: env[0] -= (env[0]>>9); break;
case 0: lap = 30; // every 640usec(21.3usec*30) @24MHz (Adjustable)
}
while( !TF2 ); // Waiting for Timer1 overflow (every 21.3usec(=512clk/24MHz))
TF2 = 0; // Clear Timer1 Overflow Flag
} while( note ); // Exit if note data is 0
PWM_DATA1 = 0; // Set output to 0
}
"note2.h" は以下参照
Digisparkで音楽演奏【楽譜編】
https://hello-world.blog.ss-blog.jp/2022-07-04
(参考にさせていただいたところ)
ch55xduinoでタイマ割り込み|akita11|note
https://note.com/akita11/n/ne4f2a2fb7c70
CH552 Core Board と Ch55xduino [Arduino]
CH552Eと遊んでいたら、なにかの拍子にUSBから認識されなくなってしまいました。
しかし、こんなこともあろうかと CH552 Core Board というものを購入しておいたのでした。
このボードとCH552のデータシートとCh55xduinoの内容を確認しながら、Ch55xduino でのタイマー、カウンタ、PWMなどについて調べてみました。
Ch55xduinoのcoreのある場所 (windows)
%localappdata%\Arduino15\packages\CH55xDuino\hardware\mcs51\0.0.16\cores\ch55xduino
Ch55xduinoでは、、
・Timer0 : mills(), micros()などの時間関係に使用されている
・Timer1 : UART0 のところで、"use Timer1 for baudrate generator" って書いてあった
・AVRと異なり、タイマー・カウンタとPWMとは別々っぽい
・内部クロック(または外部オシレータ)24MHz(Fosc)で、そこから4倍の96MHz(Fpll)として、Fpllを2分周した48MHzをUSBへ、Fpllを分周設定したものをシステムクロック(Fsys)としている(187.5kHz~24MHz)
・PWMはFsysからの分周数を設定できる(0~255)
・タイマーの分周は、Fsysからの1/4/12分周の三択っぽい
他、気になったところ
・CH552/551のプログラム(ROM)は200回しか書き換えできない (Data Flash は約 10,000 回)。
・CH559のROMは10万回消せるっぽい。
しかし、こんなこともあろうかと CH552 Core Board というものを購入しておいたのでした。
このボードとCH552のデータシートとCh55xduinoの内容を確認しながら、Ch55xduino でのタイマー、カウンタ、PWMなどについて調べてみました。
Ch55xduinoのcoreのある場所 (windows)
%localappdata%\Arduino15\packages\CH55xDuino\hardware\mcs51\0.0.16\cores\ch55xduino
Ch55xduinoでは、、
・Timer0 : mills(), micros()などの時間関係に使用されている
・Timer1 : UART0 のところで、"use Timer1 for baudrate generator" って書いてあった
・AVRと異なり、タイマー・カウンタとPWMとは別々っぽい
・内部クロック(または外部オシレータ)24MHz(Fosc)で、そこから4倍の96MHz(Fpll)として、Fpllを2分周した48MHzをUSBへ、Fpllを分周設定したものをシステムクロック(Fsys)としている(187.5kHz~24MHz)
・PWMはFsysからの分周数を設定できる(0~255)
・タイマーの分周は、Fsysからの1/4/12分周の三択っぽい
他、気になったところ
・CH552/551のプログラム(ROM)は200回しか書き換えできない (Data Flash は約 10,000 回)。
・CH559のROMは10万回消せるっぽい。
タグ:CH552 Ch55xduino
CH552Eで遊ぶ [Arduino]
ぼくがdigisparkやATtiny85で遊んでいたころ、世間はATtiny202という安価なマイコンで沸いていたらしい。
触ってみたかったけど、半導体不足のせいか秋月電子では売り切れ。
ちょっと割高なところで購入してみた。
digispark, ATtiny85と比較して、、
・とにかく安い
・しかし、売ってない
・UPDIでの書き込みが便利(USB-TTLにダイオードちょい足しするだけ)
・自由なピンが5つ
・フラッシュメモリ、RAMはATtiny85ほどはない
・USBに直接はつながらない
・レジスタがいままでのとちょっと違う
UPDIで書き込みするとして、電源だけUSBからもらう基板を考えてみた。
なら、ついでに安いUSB-TTL変換IC(CH340Eとか)も載せちゃったほうが便利じゃん、、と調べていたら、CH552とかいうICを見つけちゃいました。
USBに対応していて、キャパシタ2つつけるだけでよくて、フラッシュメモリも16kB, RAM 1280byteと十分。
いろいろなパッケージがあるのですが、そんなに足はいらないので一番小さいCH552Eを選択。
ということでAliExpressでお取り寄せ。
DIP変換基板に載せます。
かなり細かいのではんだ付け大変。
フラックスでひたひたにしている動画を参考に、フラックスまみれにしてはんだ付けしました。
これをUSB-Cレセプタクル基板(CCの5.1kΩ抵抗なし)と合体させてテストボードを作りました。
ボードマネージャに以下のURLを追加
https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
ドライバのインストールはよくわからなかかった。
解説のページとは異なり、unknown device #1 (だったと思う)というものが出てきた。
よくわからなかったけど、Zadigで、"libusb-win32"をインストールしてみた。
スケッチ書き込めた。(C++ではなくC言語らしいので、ちょっと修正が必要だった)
(参考)
★ATtiny202など
AVRマイコン ATTINY202-SSNR: マイコン関連 秋月電子通商-電子部品・ネット通販
https://akizukidenshi.com/catalog/g/gI-15731/
GitHub - SpenceKonde/megaTinyCore: Arduino core for the tinyAVR 0/1/2-series -
https://github.com/SpenceKonde/megaTinyCore
ここ↑から、Installation.md へいくと、追加のボードマネージャのURLがある。
http://drazzy.com/package_drazzy.com_index.json
USB Serial AdapterとUPDIの接続は、
AVR-Guidance/jtag2updi.md at master · SpenceKonde/AVR-Guidance · GitHub
https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md
★CH55xduino
GitHub - DeqingSun/ch55xduino: An Arduino-like programming API for the CH55X
https://github.com/DeqingSun/ch55xduino
追加のボードマネージャのURL
https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
CH55xをArduinoIDEで使う - Qiita
https://qiita.com/akita11/items/d7baed4ca3c06e292637
触ってみたかったけど、半導体不足のせいか秋月電子では売り切れ。
ちょっと割高なところで購入してみた。
digispark, ATtiny85と比較して、、
・とにかく安い
・しかし、売ってない
・UPDIでの書き込みが便利(USB-TTLにダイオードちょい足しするだけ)
・自由なピンが5つ
・フラッシュメモリ、RAMはATtiny85ほどはない
・USBに直接はつながらない
・レジスタがいままでのとちょっと違う
UPDIで書き込みするとして、電源だけUSBからもらう基板を考えてみた。
なら、ついでに安いUSB-TTL変換IC(CH340Eとか)も載せちゃったほうが便利じゃん、、と調べていたら、CH552とかいうICを見つけちゃいました。
USBに対応していて、キャパシタ2つつけるだけでよくて、フラッシュメモリも16kB, RAM 1280byteと十分。
いろいろなパッケージがあるのですが、そんなに足はいらないので一番小さいCH552Eを選択。
ということでAliExpressでお取り寄せ。
DIP変換基板に載せます。
かなり細かいのではんだ付け大変。
フラックスでひたひたにしている動画を参考に、フラックスまみれにしてはんだ付けしました。
これをUSB-Cレセプタクル基板(CCの5.1kΩ抵抗なし)と合体させてテストボードを作りました。
ボードマネージャに以下のURLを追加
https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
ドライバのインストールはよくわからなかかった。
解説のページとは異なり、unknown device #1 (だったと思う)というものが出てきた。
よくわからなかったけど、Zadigで、"libusb-win32"をインストールしてみた。
スケッチ書き込めた。(C++ではなくC言語らしいので、ちょっと修正が必要だった)
(参考)
★ATtiny202など
AVRマイコン ATTINY202-SSNR: マイコン関連 秋月電子通商-電子部品・ネット通販
https://akizukidenshi.com/catalog/g/gI-15731/
GitHub - SpenceKonde/megaTinyCore: Arduino core for the tinyAVR 0/1/2-series -
https://github.com/SpenceKonde/megaTinyCore
ここ↑から、Installation.md へいくと、追加のボードマネージャのURLがある。
http://drazzy.com/package_drazzy.com_index.json
USB Serial AdapterとUPDIの接続は、
AVR-Guidance/jtag2updi.md at master · SpenceKonde/AVR-Guidance · GitHub
https://github.com/SpenceKonde/AVR-Guidance/blob/master/UPDI/jtag2updi.md
★CH55xduino
GitHub - DeqingSun/ch55xduino: An Arduino-like programming API for the CH55X
https://github.com/DeqingSun/ch55xduino
追加のボードマネージャのURL
https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
CH55xをArduinoIDEで使う - Qiita
https://qiita.com/akita11/items/d7baed4ca3c06e292637
タグ:CH552 Ch55xduino