GR KURUMI + フルカラーLEDマトリクス
以前、単色のLEDマトリクスをGR KURUMIから操作してみましたが、今回はフルカラーです。
Arduinoでよく使われるTLC5940というLED用PWMドライバを使ったのですが、GR KURUMIの方の処理速度の問題で、ちらつきを完全になくすことができませんでした。なので、表示処理で素早く点灯色を切り替えて、ちらつきか意図的なものかわかりづらくしてます。笑
それにしても、駅の電光掲示板とか、どんな制御してるんでしょうねえ。びしっと表示されててスクロールまでするので本当にすごいと思います。笑
表示内容はまたもやライフゲームです。
以下、ソースです。
/*GR-KURUMI Sketch Template Version: V1.00*/ #include <RLduino78.h> #define NUM_5940 2 #define GSCLK_PIN 3 #define COM0_PIN 4 #define COM1_PIN 5 #define COM2_PIN 6 #define VPRG_PIN 7 #define BLANK_PIN 8 #define XLAT_PIN 9 #define SIN_PIN 11 #define SCLK_PIN 13 //void myisr( void ); void set_dc( void ); void set_gs( void ); void proc_gs( void ); void proc_update(unsigned long u32ms); void disp_update( void ); void set_gsval( void ); void set_row( void ); void get_temp( unsigned long u32ms ); void lifegame( void ); void proc_color( void ); int gsupdate = 0; int dispindex = 0; byte dcval[NUM_5940][16] = { {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, {0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30, 0x30}, }; word gsval[NUM_5940][16]; typedef unsigned long RGB; #define GetRED(x) (byte)(((x)>>16)&0xff) #define GetGREEN(x) (byte)(((x)>>8)&0xff) #define GetBLUE(x) (byte)((x)&0xff) #define SetRGB(r,g,b) (((r)<<16)|((g)<<8)|(b)) RGB dots[8][8] = { { 0x000000, 0x000000, 0x000000, 0xFF8811, 0xFF8811, 0x000000, 0x000000, 0x000000 }, { 0x000000, 0x000000, 0xFF8811, 0x000000, 0x000000, 0xFF8811, 0x000000, 0x000000 }, { 0x000000, 0xFF8811, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF8811, 0x000000 }, { 0xFF8811, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF8811 }, { 0xFF8811, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF8811 }, { 0x000000, 0xFF8811, 0x000000, 0x000000, 0x000000, 0x000000, 0xFF8811, 0x000000 }, { 0x000000, 0x000000, 0xFF8811, 0x000000, 0x000000, 0xFF8811, 0x000000, 0x000000 }, { 0x000000, 0x000000, 0x000000, 0xFF8811, 0xFF8811, 0x000000, 0x000000, 0x000000 } }; typedef struct { byte red; byte green; byte blue; } s_dir_colors; s_dir_colors dir_colors; int row_index = 0; int current_temp = 0; // the setup routine runs once when you press reset: void setup() { int i, j; row_index = 0; gsupdate = 0; dispindex = 0; dir_colors.red = 1; dir_colors.green = 0; dir_colors.blue = 0; for( i = 0; i < NUM_5940; i ++ ){ for( j = 0; j < 16; j ++ ){ gsval[i][j] = 0; } } pinMode(COM0_PIN, OUTPUT); pinMode(COM1_PIN, OUTPUT); pinMode(COM2_PIN, OUTPUT); pinMode(VPRG_PIN, OUTPUT); pinMode(BLANK_PIN, OUTPUT); pinMode(XLAT_PIN, OUTPUT); // SS(STCP) pinMode(SIN_PIN, OUTPUT); pinMode(SCLK_PIN, OUTPUT); pinMode(GSCLK_PIN, OUTPUT); digitalWrite(COM0_PIN, LOW); digitalWrite(COM1_PIN, LOW); digitalWrite(COM2_PIN, LOW); digitalWrite(VPRG_PIN, HIGH); digitalWrite(BLANK_PIN, HIGH); digitalWrite(XLAT_PIN, LOW); digitalWrite(GSCLK_PIN, LOW); // start work set_dc(); gsupdate = 1; attachCyclicHandler(0, get_temp, 3005); attachCyclicHandler(1, proc_update, 1000); } // the loop routine runs over and over again forever: void loop() { // check update disp_update(); // update // set row set_row(); // set grayscale data set_gs(); proc_gs(); // increment row row_index = ( row_index + 1 ) & 0x7; } void get_temp( unsigned long u32ms ) { current_temp = getTemperature( TEMP_MODE_CELSIUS ); } void set_dc( void ) { int i = 0; int j = 0; byte k = 0; // Dot Correction noInterrupts(); P0.BIT.bit0 = 1; // VPRG P1.BIT.bit3 = 0; // XLAT P7.BIT.bit0 = 0; // SCLK for( i = 0; i < NUM_5940; i ++ ){ for( j = 0; j < 16; j ++ ){ for( k = 0x20; k != 0x00; k >>= 1 ){ P7.BIT.bit2 = ( ( dcval[i][j] & k ) == 0 ) ? 0 : 1; // SIN P7.BIT.bit0 = 1; // SCLK P7.BIT.bit0 = 0; // SCLK } } } P1.BIT.bit3 = 1; // XLAT P1.BIT.bit3 = 0; // XLAT interrupts(); } void set_gs( void ) { int i = 0; int j = 0; word k = 0; // Gray Scale set_gsval(); noInterrupts(); P0.BIT.bit0 = 0; // VPRG P1.BIT.bit3 = 0; // XLAT P0.BIT.bit1 = 1; // BLANK P7.BIT.bit0 = 0; // SCLK for( i = 1; i >= 0; i -- ){ for( j = 0; j < 16; j ++ ){ for( k = 0x0800; k != 0x0000; k >>= 1 ){ P7.BIT.bit2 = ( ( gsval[i][j] & k ) == 0 ) ? 0 : 1; // SIN P7.BIT.bit0 = 1; // SCLK P7.BIT.bit0 = 0; // SCLK } } } P1.BIT.bit3 = 1; // XLAT P1.BIT.bit3 = 0; // XLAT P7.BIT.bit0 = 1; // SCLK P7.BIT.bit0 = 0; // SCLK interrupts(); } void proc_gs( void ) { int i = 0; noInterrupts(); P0.BIT.bit1 = 0; // BLANK P1.BIT.bit6 = 0; // GSCLK for( i = 0; i < 4096; i ++ ){ P1.BIT.bit6 = 1; // GSCLK P1.BIT.bit6 = 0; // GSCLK } P0.BIT.bit1 = 1; // BLANK P0.BIT.bit1 = 0; // BLANK interrupts(); } void set_row( void ) { // set ROW noInterrupts(); switch( row_index ){ case 0: P3.BIT.bit1 = 0; // COM0 P1.BIT.bit5 = 0; // COM1 P1.BIT.bit0 = 0; // COM2 break; case 1: P3.BIT.bit1 = 1; // COM0 P1.BIT.bit5 = 0; // COM1 P1.BIT.bit0 = 0; // COM2 break; case 2: P3.BIT.bit1 = 0; // COM0 P1.BIT.bit5 = 1; // COM1 P1.BIT.bit0 = 0; // COM2 break; case 3: P3.BIT.bit1 = 1; // COM0 P1.BIT.bit5 = 1; // COM1 P1.BIT.bit0 = 0; // COM2 break; case 4: P3.BIT.bit1 = 0; // COM0 P1.BIT.bit5 = 0; // COM1 P1.BIT.bit0 = 1; // COM2 break; case 5: P3.BIT.bit1 = 1; // COM0 P1.BIT.bit5 = 0; // COM1 P1.BIT.bit0 = 1; // COM2 break; case 6: P3.BIT.bit1 = 0; // COM0 P1.BIT.bit5 = 1; // COM1 P1.BIT.bit0 = 1; // COM2 break; case 7: P3.BIT.bit1 = 1; // COM0 P1.BIT.bit5 = 1; // COM1 P1.BIT.bit0 = 1; // COM2 break; default: break; } interrupts(); } void proc_update( unsigned long u32ms ) { gsupdate = 1; } void set_gsval( void ) { /* set gsval */ gsval[0][0] = GetRED(dots[row_index][5]) * 16; gsval[0][1] = GetBLUE(dots[row_index][4]) * 16; gsval[0][2] = GetGREEN(dots[row_index][4]) * 16; gsval[0][3] = GetRED(dots[row_index][4]) * 16; gsval[0][4] = GetBLUE(dots[row_index][3]) * 16; gsval[0][5] = GetGREEN(dots[row_index][3]) * 16; gsval[0][6] = GetRED(dots[row_index][3]) * 16; gsval[0][7] = GetBLUE(dots[row_index][2]) * 16; gsval[0][8] = GetGREEN(dots[row_index][2]) * 16; gsval[0][9] = GetRED(dots[row_index][2]) * 16; gsval[0][10] = GetBLUE(dots[row_index][1]) * 16; gsval[0][11] = GetGREEN(dots[row_index][1]) * 16; gsval[0][12] = GetRED(dots[row_index][1]) * 16; gsval[0][13] = GetBLUE(dots[row_index][0]) * 16; gsval[0][14] = GetGREEN(dots[row_index][0]) * 16; gsval[0][15] = GetRED(dots[row_index][0]) * 16; gsval[1][0] = 0; gsval[1][1] = 0; gsval[1][2] = 0; gsval[1][3] = 0; gsval[1][4] = 0; gsval[1][5] = 0; gsval[1][6] = 0; gsval[1][7] = 0; gsval[1][8] = GetBLUE(dots[row_index][7]) * 16; gsval[1][9] = GetGREEN(dots[row_index][7]) * 16; gsval[1][10] = GetRED(dots[row_index][7]) * 16; gsval[1][11] = GetBLUE(dots[row_index][6]) * 16; gsval[1][12] = GetGREEN(dots[row_index][6]) * 16; gsval[1][13] = GetRED(dots[row_index][6]) * 16; gsval[1][14] = GetBLUE(dots[row_index][5]) * 16; gsval[1][15] = GetGREEN(dots[row_index][5]) * 16; } void disp_update( void ) { if( gsupdate == 1 ){ lifegame(); gsupdate = 0; } else{ proc_color(); } } void lifegame( void ) { int y, x; int num = 0; RGB work[8][8]; for(y=0; y<8; y++){ for(x=0; x<8; x++){ work[y][x] = dots[y][x]; } } for(y=0; y<8; y++){ for(x=0; x<8; x++){ num = 0; /* count around */ if( x != 0 ){ if( dots[y][x-1] != 0 ){ num ++; } } if( x != 7 ){ if( dots[y][x+1] != 0 ){ num ++; } } if( y != 0 ){ if( dots[y-1][x] != 0 ){ num ++; } if( x != 0 ){ if( dots[y-1][x-1] != 0 ){ num ++; } } if( x != 7 ){ if( dots[y-1][x+1] != 0 ){ num ++; } } } if( y != 7 ){ if( dots[y+1][x] != 0 ){ num ++; } if( x != 0 ){ if( dots[y+1][x-1] != 0 ){ num ++; } } if( x != 7 ){ if( dots[y+1][x+1] != 0 ){ num ++; } } } /* decide */ if( dots[y][x] == 0 ){ if( num == 3 ){ work[y][x] = 0xFF8811; } } else{ if( ( num != 2 ) && ( num != 3 ) ){ work[y][x] = 0; } } } } for( y=0; y<8; y++ ){ for( x=0; x<8; x++ ){ dots[y][x] = work[y][x]; } } } void proc_color( void ) { int y, x; byte tmpred; byte tmpgreen; byte tmpblue; for( y=0; y<8; y++ ){ for( x=0; x<8; x++ ){ if( dots[y][x] != 0 ){ tmpred = GetRED( dots[y][x] ); tmpgreen = GetGREEN( dots[y][x] ); tmpblue = GetBLUE( dots[y][x] ); if( dir_colors.red == 0 ){ tmpred = ( tmpred + 0x11 ) & 0xff; if( tmpred == 0xff ){ dir_colors.red = 1; } } else{ tmpred = ( tmpred - 0x11 ) & 0xff; if( tmpred == 0x11 ){ dir_colors.red = 0; } } if( dir_colors.green == 0 ){ tmpgreen = ( tmpgreen + 0x11 ) & 0xff; if( tmpgreen== 0xff ){ dir_colors.green = 1; } } else{ tmpgreen = ( tmpgreen - 0x11 ) & 0xff; if( tmpgreen == 0x11 ){ dir_colors.green = 0; } } if( dir_colors.blue == 0 ){ tmpblue= ( tmpblue + 0x11 ) & 0xff; if( tmpblue == 0xff ){ dir_colors.green = 1; } } else{ tmpblue = ( tmpblue - 0x11 ) & 0xff; if( tmpblue == 0x11 ){ dir_colors.blue= 0; } } dots[y][x] = SetRGB( (RGB)tmpred, (RGB)tmpgreen, (RGB)tmpblue ); } } } }
digitalWriteが遅いので、ポート直接叩くように後から書き換えました。お見苦しいかもしれませんが、ご容赦ください。