/* Pi Picoを使ったチャーリープレクシングによる72LEDクリスマスツリーイルミネーション Earle Philhowerバージョンで実行。 以前作った物から点灯タイマーや明るさ調整機能を省略。 by radiopench http://radiopench.blog96.fc2.com/ 20220428_Pico72LedXmassTree.ino */ volatile uint16_t Ly[8]; // 表示パターンメモリー uint16_t Ly_a[8], Ly_b[8], Ly_c[8]; // 表示パターン操作メモリー int L7[16]; // 流れ星末端の点灯回数メモリ void ledOff() { // すべて入力ピンにアサインして消灯 // gpio_set_dir_in_masked(0b11111111100); // これだとダメ(TX,RX以外全て入力にアサイン) // gpio_init_mask(0b11111111100); // GP2-10を初期化(入力にアサイン)消灯時も僅かに点灯 pinMode( 2, INPUT); // これで初期化すると完全に消灯(本当はgpio命令でやりたかった) pinMode( 3, INPUT); pinMode( 4, INPUT); pinMode( 5, INPUT); pinMode( 6, INPUT); pinMode( 7, INPUT); pinMode( 8, INPUT); pinMode( 9, INPUT); pinMode(10, INPUT); } // チャーリープレクシングで該当するLEDを点灯(ここは割り込みルーチンから起動される) void d2High() { // D2からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00000000100; // D2を無条件に指定 if ( Ly[6] & 0b0010000000000000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000100000000000 ) bp |= 0b00100000000; // D8 if ( Ly[6] & 0b0000001000000000 ) bp |= 0b00010000000; // D7 if ( Ly[6] & 0b0000000010000000 ) bp |= 0b00001000000; // D6 if ( Ly[6] & 0b0000000000100000 ) bp |= 0b00000100000; // D5 if ( Ly[6] & 0b0000000000001000 ) bp |= 0b00000010000; // D4 if ( Ly[6] & 0b0000000000000010 ) bp |= 0b00000001000; // D3 if ( Ly[7] & 0b0000000000000010 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(2, HIGH); // D2をHigh。これでLED点灯(光量最小化のため最後にやる) } void d3High() { // D3からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00000001000; if ( Ly[4] & 0b0000100000000000 ) bp |= 0b00100000000; // D8 if ( Ly[4] & 0b0000001000000000 ) bp |= 0b00010000000; // D7 if ( Ly[4] & 0b0000000010000000 ) bp |= 0b00001000000; // D6 if ( Ly[4] & 0b0000000000100000 ) bp |= 0b00000100000; // D5 if ( Ly[4] & 0b0000000000001000 ) bp |= 0b00000010000; // D4 if ( Ly[5] & 0b0000000000001000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000000000000100 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0000000000001000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(3, HIGH); // D3をHigh。これでLED点灯(光量最小化のため最後にやる) } void d4High() { // D4からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00000010000; if ( Ly[2] & 0b0000001000000000 ) bp |= 0b00010000000; // D7 if ( Ly[2] & 0b0000000010000000 ) bp |= 0b00001000000; // D6 if ( Ly[2] & 0b0000000000100000 ) bp |= 0b00000100000; // D5 if ( Ly[3] & 0b0000000000100000 ) bp |= 0b00100000000; // D8 if ( Ly[4] & 0b0000000000010000 ) bp |= 0b00000001000; // D3 if ( Ly[5] & 0b0000000000100000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000000000010000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0000000000100000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(4, HIGH); // D4をHigh。これでLED点灯(光量最小化のため最後にやる) } void d5High() { // D5からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00000100000; if ( Ly[0] & 0b0000000010000000 ) bp |= 0b00001000000; // D6 if ( Ly[1] & 0b0000000010000000 ) bp |= 0b00010000000; // D7 if ( Ly[2] & 0b0000000001000000 ) bp |= 0b00000010000; // D4 if ( Ly[3] & 0b0000000010000000 ) bp |= 0b00100000000; // D8 if ( Ly[4] & 0b0000000001000000 ) bp |= 0b00000001000; // D3 if ( Ly[5] & 0b0000000010000000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000000001000000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0000000010000000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(5, HIGH); // D5をHigh。これでLED点灯(光量最小化のため最後にやる) } void d6High() { // D6からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00001000000; if ( Ly[0] & 0b0000000100000000 ) bp |= 0b00000100000; // D5 if ( Ly[1] & 0b0000001000000000 ) bp |= 0b00010000000; // D7 if ( Ly[2] & 0b0000000100000000 ) bp |= 0b00000010000; // D4 if ( Ly[3] & 0b0000001000000000 ) bp |= 0b00100000000; // D8 if ( Ly[4] & 0b0000000100000000 ) bp |= 0b00000001000; // D3 if ( Ly[5] & 0b0000001000000000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000000100000000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0000001000000000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(6, HIGH); // D6をHigh。これでLED点灯(光量最小化のため最後にやる) } void d7High() { // D7からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00010000000; if ( Ly[1] & 0b0000000100000000 ) bp |= 0b00001000000; // D6 if ( Ly[1] & 0b0000000001000000 ) bp |= 0b00000100000; // D5 if ( Ly[2] & 0b0000010000000000 ) bp |= 0b00000010000; // D4 if ( Ly[3] & 0b0000100000000000 ) bp |= 0b00100000000; // D8 if ( Ly[4] & 0b0000010000000000 ) bp |= 0b00000001000; // D3 if ( Ly[5] & 0b0000100000000000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0000010000000000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0000100000000000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(7, HIGH); // D7をHigh。これでLED点灯(光量最小化のため最後にやる) } void d8High() { // D8からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b00100000000; if ( Ly[3] & 0b0000010000000000 ) bp |= 0b00010000000; // D7 if ( Ly[3] & 0b0000000100000000 ) bp |= 0b00001000000; // D6 if ( Ly[3] & 0b0000000001000000 ) bp |= 0b00000100000; // D5 if ( Ly[3] & 0b0000000000010000 ) bp |= 0b00000010000; // D4 if ( Ly[4] & 0b0001000000000000 ) bp |= 0b00000001000; // D3 if ( Ly[5] & 0b0010000000000000 ) bp |= 0b01000000000; // D9 if ( Ly[6] & 0b0001000000000000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b0010000000000000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(8, HIGH); // D8をHigh。これでLED点灯(光量最小化のため最後にやる) } void d9High() { // D9からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b01000000000; if ( Ly[5] & 0b0001000000000000 ) bp |= 0b00100000000; // D8を出力にアサイン if ( Ly[5] & 0b0000010000000000 ) bp |= 0b00010000000; // D7 if ( Ly[5] & 0b0000000100000000 ) bp |= 0b00001000000; // D6 if ( Ly[5] & 0b0000000001000000 ) bp |= 0b00000100000; // D5 if ( Ly[5] & 0b0000000000010000 ) bp |= 0b00000010000; // D4 if ( Ly[5] & 0b0000000000000100 ) bp |= 0b00000001000; // D3 if ( Ly[6] & 0b0100000000000000 ) bp |= 0b00000000100; // D2 if ( Ly[7] & 0b1000000000000000 ) bp |= 0b10000000000; // D10 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(9, HIGH); // D9をHigh。これでLED点灯(光量最小化のため最後にやる) } void d10High() { // D10からHighを出力し、指定のLEDを点灯 uint32_t bp = 0b10000000000; if ( Ly[7] & 0b0100000000000000 ) bp |= 0b01000000000; // D9を出力にアサイン if ( Ly[7] & 0b0001000000000000 ) bp |= 0b00100000000; // D8 if ( Ly[7] & 0b0000010000000000 ) bp |= 0b00010000000; // D7 if ( Ly[7] & 0b0000000100000000 ) bp |= 0b00001000000; // D6 if ( Ly[7] & 0b0000000001000000 ) bp |= 0b00000100000; // D5 if ( Ly[7] & 0b0000000000010000 ) bp |= 0b00000010000; // D4 if ( Ly[7] & 0b0000000000000100 ) bp |= 0b00000001000; // D3 if ( Ly[7] & 0b0000000000000001 ) bp |= 0b00000000100; // D2 gpio_set_dir_out_masked(bp); // ビットが立っていたポートを出力に設定(LOWが出力される) gpio_put(10, HIGH); // D10をHigh。これでLED点灯(光量最小化のため最後にやる) } /***** 1ms割り込み処理 *****/ struct repeating_timer st_tm1ms; bool tm1ms(struct repeating_timer *t) { static int scanN = 0; // リフレッシュ位置カウンタ gpio_put(16, HIGH); // GP16 High 割込み処理中表示 // f_x15 ^= 1; // gpio_put(15, f_x15); // GP15 トグル ledOff(); // 全LED消灯(舞台裏を見せないために消灯) switch (scanN) { // スキャン番号に対応したLEDを点灯(時分割で点灯される) case 0: d2High(); break; case 1: d3High(); break; case 2: d4High(); break; case 3: d5High(); break; case 4: d6High(); break; case 5: d7High(); break; case 6: d8High(); break; case 7: d9High(); break; case 8: d10High(); break; default: break; } scanN ++; // スキャン番号を更新 if (scanN > 8) { // 上限超えたらゼロに戻す scanN = 0; } gpio_put(16, LOW); // GP14 Low return true; } void clearArray() { // パターンメモリー消去 for (int i = 0; i < 8; i++) { Ly[i] = 0; Ly_a[i] = 0; Ly_b[i] = 0; } } void allOn() { // パターンメモリーの全LEDをONにする) Ly[0] = 0x0180; Ly[1] = 0x03C0; Ly[2] = 0x07E0; Ly[3] = 0x0FF0; Ly[4] = 0x1FF8; Ly[5] = 0x3FFC; Ly[6] = 0x7FFE; Ly[7] = 0xFFFF; } void show(unsigned int t) { // 見せるために指定時間待機。 delay(t); } void onOff(int n) { // 全LED点灯/消灯 for (int i = 0; i < n; i++) { allOn(); show(2000); clearArray(); show(1000); } } void spiralUp() { // スパイラル上昇 Ly[0] &= 0x0180; // 表示領域外をクリア Ly[1] &= 0x03C0; Ly[2] &= 0x07E0; Ly[3] &= 0x0FF0; Ly[4] &= 0x1FF8; Ly[5] &= 0x3FFC; Ly[6] &= 0x7FFE; Ly[0] = Ly[0] << 1; if (Ly[1] & 0x0200) Ly[0] |= 0x0080; // Ly[1]の左端が1だったら、Ly[0]の右端を1にする Ly[1] = Ly[1] << 1; if (Ly[2] & 0x0400) Ly[1] |= 0x0040; // Ly[2]の左端が1だったら、Ly[1]の右端を1にする Ly[2] = Ly[2] << 1; if (Ly[3] & 0x0800) Ly[2] |= 0x0020; // Ly[3]の左端が1だったら、Ly[2]の右端を1にする Ly[3] = Ly[3] << 1; if (Ly[4] & 0x1000) Ly[3] |= 0x0010; // Ly[4]の左端が1だったら、Ly[3]の右端を1にする Ly[4] = Ly[4] << 1; if (Ly[5] & 0x2000) Ly[4] |= 0x0008; // Ly[5]の左端が1だったら、Ly[4]の右端を1にする Ly[5] = Ly[5] << 1; if (Ly[6] & 0x4000) Ly[5] |= 0x0004; // Ly[6]の左端が1だったら、Ly[5]の右端を1にする Ly[6] = Ly[6] << 1; if (Ly[7] & 0x8000) Ly[6] |= 0x0002; // Ly[7]の左端が1だったら、Ly[6]の右端を1にする Ly[7] = Ly[7] << 1; } void ledTest1() { // LED点灯テスト1(全点灯して左から消去) for (;;) { unsigned int p; p = 0xFFFF; // 初期点灯パターン for (int i = 0; i <= 16; i++) { for (int j = 0; j <= 7; j++) { // 点灯パターンをメモリーへコピー Ly[j] = p; } show(200); p = p >> 1; // 点灯パターンを右に1ビットシフト } } } void ledTest2() { // LED点灯テスト2(下から順にLEDを一つづつ点灯) for (;;) { // 無限ループで、(中身はstarSpiralUpと同じ) Ly[7] = 0x0001; // 種を仕込んで show(300); // 点灯 for (int j = 0; j <= 72; j++) { // 一番上まで spiralUp(); // スパイラル上昇 show(300); // 点灯 } clearArray(); delay(200); } } void propeller(int n) { // プロペラ表示 int a; for (int i = 0; i < n; i++) { // 引数で指定された回数繰り返す for (a = 0; a < 1680 * 2; a += 10) { // 正回転(1680は16,14,12,10 の最小公倍数) invertV(a); // 指定角度で逆V字表示 show(5); } for (a = 1680 * 2; a > 0; a -= 10) { // 逆回転 invertV(a); show(5); } } } void invertV(int k) { // 指定角度で逆V字型に点灯(引数840で半回転) Ly[0] = 0b0000000110000000; // 頂上の2個は常時点灯 Ly[1] = 0b0000001010000000 >> ((k / 420) % 2); // V字パターンを指定角度に移動 Ly[2] = 0b0000010010000000 >> ((k / 280) % 3); // なお840は8,7,6,5,4,3,2の最小公倍数 Ly[3] = 0b0000100010000000 >> ((k / 210) % 4); Ly[4] = 0b0001000010000000 >> ((k / 168) % 5); Ly[5] = 0b0010000010000000 >> ((k / 140) % 6); Ly[6] = 0b0100000010000000 >> ((k / 120) % 7); Ly[7] = 0b1000000010000000 >> ((k / 105) % 8); } void starSpiralUp(int n) { // 回転しながら下から上に向かってLEDを一つづ点灯 for (int i = 0; i < n; i++) { // 指定回数 Ly[7] = 0x0001; // 種を仕込んで show(20); // for (int j = 0; j <= 72; j++) { // 一番上まで spiralUp(); // スパイラル上昇 show(20); // 点灯 } clearArray(); delay(200); } } void fallingRing(int c) { // リングを上から落とす for (int n = 0; n < c; n++) { // 指定回数 clearArray(); Ly[0] = 0xFFFF; // 先頭にネタを仕込んで show(100); // 見せるためにちょっと待機 for (int i = 0; i < 7; i++) { Ly[i + 1] = Ly[i]; // 一つ後ろ(下)にずらす Ly[i] = 0; show(70); // 待機 } } clearArray(); // 最後に消灯 delay(200); } void stackUpDown(int n) { // 積み上げで点灯、積み下げで消灯 for (int i = 0; i < n; i++) { for (int z = 7; z >= 0; z--) { // 下から上に順に積み上げ点灯 Ly[z] = 0xFFFF; show(30); } show(200); // 全点灯でちょっと待つ for (int z = 7; z >= 0; z--) { // 下から上へ消灯 Ly[z] = 0x0000; show(30); } show(200); // 全消灯でちょっと待つ for (int z = 0; z <= 7; z++) { // 上から下へ逆積みで点灯 Ly[z] = 0xFFFF; show(30); } show(200); // 全点灯でちょっと待つ for (int z = 0; z <= 7; z++) { // 上から下へ消灯 Ly[z] = 0x0000; show(30); } show(300); // 全消灯でちょっと待つ } // n回繰り返し } void swing(int n) { // 斜め線を右移動 for (int i = 0; i < n; i++) { // 指定回数 for (int j = 0; j < 2; j++) { // 左回転で2回 Ly[0] = 0x0100; // 左側に斜め線を仕込む Ly[1] = 0x0200; Ly[2] = 0x0400; Ly[3] = 0x0800; Ly[4] = 0x1000; Ly[5] = 0x2000; Ly[6] = 0x4000; Ly[7] = 0x8000; for (int k = 0; k < 16; k++) { // 16回 for (int m = 0; m < 8; m++) { // 各層の Ly[m] = Ly[m] >> 1; // 像を右シフト } show(50); // 表示のために待機 } } show(200); for (int j = 0; j < 2; j++) { // 右回転で2回 Ly[0] = 0x0080; // 右側に斜め線を仕込む Ly[1] = 0x0040; Ly[2] = 0x0020; Ly[3] = 0x0010; Ly[4] = 0x0008; Ly[5] = 0x0004; Ly[6] = 0x0002; Ly[7] = 0x0001; for (int k = 0; k < 16; k++) { // 16回 for (int m = 0; m < 8; m++) { Ly[m] = Ly[m] << 1; // 像を右シフト } show(50); // 表示のために待機 } } show(200); for (int j = 0; j < 2; j++) { // 交差スイングで2回 Ly_a[0] = 0x0100; Ly_b[0] = 0x0080; // 両側に斜め線を仕込む Ly_a[1] = 0x0200; Ly_b[1] = 0x0040; Ly_a[2] = 0x0400; Ly_b[2] = 0x0020; Ly_a[3] = 0x0800; Ly_b[3] = 0x0010; Ly_a[4] = 0x1000; Ly_b[4] = 0x0008; Ly_a[5] = 0x2000; Ly_b[5] = 0x0004; Ly_a[6] = 0x4000; Ly_b[6] = 0x0002; Ly_a[7] = 0x8000; Ly_b[7] = 0x0001; for (int k = 0; k < 16; k++) { // 16回 for (int m = 0; m < 8; m++) { Ly_a[m] = Ly_a[m] >> 1; // aバッファの像を右シフト } for (int m = 0; m < 8; m++) { Ly_b[m] = Ly_b[m] << 1; // bバッファの像を左シフト } for (int m = 0; m <= 7; m++) { Ly[m] = Ly_a[m] | Ly_b[m]; // 表示メモリに合成 } show(50); // 表示のために待機 } } show(500); } } void verticalCut(int n) { // 縦切りで横に点灯、消灯 clearArray(); for (int i = 0; i < n; i++) { // 指定回数 // 左から右に点灯 Ly[6] |= 0b0000100000000000; Ly[7] |= 0b0001100000000000; // 1 ビットを立てて点灯 show(50); Ly[4] |= 0b0000010000000000; Ly[5] |= 0b0000110000000000; Ly[6] |= 0b0001010000000000; Ly[7] |= 0b0010010000000000; // 2 show(50); Ly[2] |= 0b0000001000000000; Ly[3] |= 0b0000011000000000; Ly[4] |= 0b0000101000000000; Ly[5] |= 0b0001001000000000; Ly[6] |= 0b0010001000000000; Ly[7] |= 0b0100001000000000; // 3 show(50); Ly[0] |= 0b0000000100000000; Ly[1] |= 0b0000001100000000; Ly[2] |= 0b0000010100000000; Ly[3] |= 0b0000100100000000; Ly[4] |= 0b0001000100000000; Ly[5] |= 0b0010000100000000; Ly[6] |= 0b0100000100000000; Ly[7] |= 0b1000000100000000; // 4 show(50); Ly[0] |= 0b0000000010000000; Ly[1] |= 0b0000000011000000; Ly[2] |= 0b0000000010100000; Ly[3] |= 0b0000000010010000; Ly[4] |= 0b0000000010001000; Ly[5] |= 0b0000000010000100; Ly[6] |= 0b0000000010000010; Ly[7] |= 0b0000000010000001; // 5 show(50); Ly[2] |= 0b0000000001000000; Ly[3] |= 0b0000000001100000; Ly[4] |= 0b0000000001010000; Ly[5] |= 0b0000000001001000; Ly[6] |= 0b0000000001000100; Ly[7] |= 0b0000000001000010; // 6 show(50); Ly[4] |= 0b0000000000100000; Ly[5] |= 0b0000000000110000; Ly[6] |= 0b0000000000101000; Ly[7] |= 0b0000000000100100; // 7 show(50); Ly[6] |= 0b0000000000010000; Ly[7] |= 0b0000000000011000; // 8 show(300); // 左から右に消灯 Ly[6] &= ~0b0000100000000000; Ly[7] &= ~0b0001100000000000; // 1 ビットを消して消灯 show(50); // Ly[4] &= ~0b0000010000000000; Ly[5] &= ~0b0000110000000000; Ly[6] &= ~0b0001010000000000; Ly[7] &= ~0b0010010000000000; // 2 show(50); Ly[2] &= ~0b0000001000000000; Ly[3] &= ~0b0000011000000000; Ly[4] &= ~0b0000101000000000; Ly[5] &= ~0b0001001000000000; Ly[6] &= ~0b0010001000000000; Ly[7] &= ~0b0100001000000000; // 3 show(50); Ly[0] &= ~0b0000000100000000; Ly[1] &= ~0b0000001100000000; Ly[2] &= ~0b0000010100000000; Ly[3] &= ~0b0000100100000000; Ly[4] &= ~0b0001000100000000; Ly[5] &= ~0b0010000100000000; Ly[6] &= ~0b0100000100000000; Ly[7] &= ~0b1000000100000000; // 4 show(50); Ly[0] &= ~0b0000000010000000; Ly[1] &= ~0b0000000011000000; Ly[2] &= ~0b0000000010100000; Ly[3] &= ~0b0000000010010000; Ly[4] &= ~0b0000000010001000; Ly[5] &= ~0b0000000010000100; Ly[6] &= ~0b0000000010000010; Ly[7] &= ~0b0000000010000001; // 5 show(50); Ly[2] &= ~0b0000000001000000; Ly[3] &= ~0b0000000001100000; Ly[4] &= ~0b0000000001010000; Ly[5] &= ~0b0000000001001000; Ly[6] &= ~0b0000000001000100; Ly[7] &= ~0b0000000001000010; // 6 show(50); Ly[4] &= ~0b0000000000100000; Ly[5] &= ~0b0000000000110000; Ly[6] &= ~0b0000000000101000; Ly[7] &= ~0b0000000000100100; // 7 show(50); Ly[6] &= ~0b0000000000010000; Ly[7] &= ~0b0000000000011000; // 8 右端まで消灯完了 show(300); // 右から左に点灯 Ly[6] |= 0b0000000000010000; // Ly[7] |= 0b0000000000011000; // 8 右端から ビットを立てて点灯 show(50); Ly[4] |= 0b0000000000100000; Ly[5] |= 0b0000000000110000; Ly[6] |= 0b0000000000101000; Ly[7] |= 0b0000000000100100; // 7 show(50); Ly[2] |= 0b0000000001000000; Ly[3] |= 0b0000000001100000; Ly[4] |= 0b0000000001010000; Ly[5] |= 0b0000000001001000; Ly[6] |= 0b0000000001000100; Ly[7] |= 0b0000000001000010; // 6 show(50); Ly[0] |= 0b0000000010000000; Ly[1] |= 0b0000000011000000; Ly[2] |= 0b0000000010100000; Ly[3] |= 0b0000000010010000; Ly[4] |= 0b0000000010001000; Ly[5] |= 0b0000000010000100; Ly[6] |= 0b0000000010000010; Ly[7] |= 0b0000000010000001; // 5 show(50); Ly[0] |= 0b0000000100000000; Ly[1] |= 0b0000001100000000; Ly[2] |= 0b0000010100000000; Ly[3] |= 0b0000100100000000; Ly[4] |= 0b0001000100000000; Ly[5] |= 0b0010000100000000; Ly[6] |= 0b0100000100000000; Ly[7] |= 0b1000000100000000; // 4 show(50); Ly[2] |= 0b0000001000000000; Ly[3] |= 0b0000011000000000; Ly[4] |= 0b0000101000000000; Ly[5] |= 0b0001001000000000; Ly[6] |= 0b0010001000000000; Ly[7] |= 0b0100001000000000; // 3 show(50); Ly[4] |= 0b0000010000000000; Ly[5] |= 0b0000110000000000; Ly[6] |= 0b0001010000000000; Ly[7] |= 0b0010010000000000; // 2 show(50); Ly[6] |= 0b0000100000000000; Ly[7] |= 0b0001100000000000; // 1 show(300); // 右から左に消灯 Ly[6] &= ~0b0000000000010000; Ly[7] &= ~0b0000000000011000; // 8 ビットを消して消灯 show(50); Ly[4] &= ~0b0000000000100000; Ly[5] &= ~0b0000000000110000; Ly[6] &= ~0b0000000000101000; Ly[7] &= ~0b0000000000100100; // 7 show(50); Ly[2] &= ~0b0000000001000000; Ly[3] &= ~0b0000000001100000; Ly[4] &= ~0b0000000001010000; Ly[5] &= ~0b0000000001001000; Ly[6] &= ~0b0000000001000100; Ly[7] &= ~0b0000000001000010; // 6 show(50); Ly[0] &= ~0b0000000010000000; Ly[1] &= ~0b0000000011000000; Ly[2] &= ~0b0000000010100000; Ly[3] &= ~0b0000000010010000; Ly[4] &= ~0b0000000010001000; Ly[5] &= ~0b0000000010000100; Ly[6] &= ~0b0000000010000010; Ly[7] &= ~0b0000000010000001; // 5 show(50); Ly[0] &= ~0b0000000100000000; Ly[1] &= ~0b0000001100000000; Ly[2] &= ~0b0000010100000000; Ly[3] &= ~0b0000100100000000; Ly[4] &= ~0b0001000100000000; Ly[5] &= ~0b0010000100000000; Ly[6] &= ~0b0100000100000000; Ly[7] &= ~0b1000000100000000; // 4 show(50); Ly[2] &= ~0b0000001000000000; Ly[3] &= ~0b0000011000000000; Ly[4] &= ~0b0000101000000000; Ly[5] &= ~0b0001001000000000; Ly[6] &= ~0b0010001000000000; Ly[7] &= ~0b0100001000000000; // 3 show(50); Ly[4] &= ~0b0000010000000000; Ly[5] &= ~0b0000110000000000; Ly[6] &= ~0b0001010000000000; Ly[7] &= ~0b0010010000000000; // 2 show(50); Ly[6] &= ~0b0000100000000000; Ly[7] &= ~0b0001100000000000; // 1 show(500); } } void rotateAndClimb(int n) { // 回転しながら登る clearArray(); for (int i = 0; i < n; i++) { // 指定回数 for (int j = 0; j < 80; j++) { if ( (j % 18) > 8) { // 8回置きに、 Ly[7] |= 0x0001; // 一番下に星を埋め込む } else { Ly[7] &= ~0x0001; // 星を消す } show(40); spiralUp(); } for (int j = 0; j < 55; j++) { Ly[7] &= ~0x0001; show(40); spiralUp(); } } clearArray(); delay(500); } void randomStar(int n) { // ランダムに点灯 for (int i = 0; i < n; i++) { // 引数で指定された回数 for (int j = 0; j < 40; j++) { // 6秒間(0.15秒x40回) Ly[0] |= 0x0180; // 先端の2個は常時点灯 Ly[1] = random(0, 0xFFFF) & random(0, 0xFFFF); // 確率1/4で点灯 Ly[2] = random(0, 0xFFFF) & random(0, 0xFFFF); Ly[3] = random(0, 0xFFFF) & random(0, 0xFFFF); Ly[4] = random(0, 0xFFFF) & random(0, 0xFFFF); Ly[5] = random(0, 0xFFFF) & random(0, 0xFFFF); Ly[6] = random(0, 0xFFFF) & random(0, 0xFFFF); Ly[7] = random(0, 0xFFFF) & random(0, 0xFFFF); show(150); } } // loop n clearArray(); show(1000); } void fallingSnow(int m) { // 雪が降る mは表示時間倍率 int p = 8; // 雪の出現確率(確率= 1/p) for (int k = 0; k < 8; k++) { // 積雪量をクリア Ly_c[k] = 0; } for (int k = 0; k < (220 * m); k++) { if (random(0, p) == 0) Ly_a[3] = 0x0800; // A1ラインの種 if (random(0, p) == 0) Ly_a[2] = 0x0400; // A2ラインの種 if (random(0, p) == 0) Ly_a[1] = 0x0200; // A3ラインの種 if (random(0, p) == 0) Ly_a[1] = 0x0100; // A4ラインの種 if (random(0, p) == 0) Ly_a[1] = 0x0080; // A5ラインの種 if (random(0, p) == 0) Ly_a[1] = 0x0040; // A6ラインの種 if (random(0, p) == 0) Ly_a[2] = 0x0020; // A7ラインの種 if (random(0, p) == 0) Ly_a[3] = 0x0010; // A8ラインの種 if (random(0, p) == 0) Ly_b[3] = 0x0100; // B1ラインの種 if (random(0, p) == 0) Ly_b[2] = 0x0100; // B2ラインの種 if (random(0, p) == 0) Ly_b[1] = 0x0100; // B3ラインの種 if (random(0, p) == 0) Ly_b[1] = 0x0200; // B4ラインの種 if (random(0, p) == 0) Ly_b[1] = 0x0040; // B5ラインの種 if (random(0, p) == 0) Ly_b[1] = 0x0080; // B6ラインの種 if (random(0, p) == 0) Ly_b[2] = 0x0080; // B7ラインの種 if (random(0, p) == 0) Ly_b[3] = 0x0080; // B8ラインの種 if (k > (100 * m)) Ly_c[7] = 0xFFFF; // 徐々に積もっていく if (k > (120 * m)) Ly_c[6] = 0xFFFF; if (k > (140 * m)) Ly_c[5] = 0xFFFF; if (k > (160 * m)) Ly_c[4] = 0xFFFF; if (k > (170 * m)) Ly_c[3] = 0xFFFF; if (k > (185 * m)) Ly_c[2] = 0xFFFF; if (k > (200 * m)) Ly_c[1] = 0xFFFF; for (int j = 0; j < 8; j++) { Ly[j] = Ly_a[j] | Ly_b[j] | Ly_c[j]; // 表示メモリに転送 } Ly[0] |= 0x0180; //先端の星を点灯 show(80); stepDown(); // 星を一つ下に流す } // next k clearArray(); show(1000); } void stepDown() { // 星を所定のルートで下に落とす if (Ly_a[6] & 0x0800) L7[11] = 4; else L7[11]--; // A1 最下段は4回光ったままにする if (L7[11] < 0) L7[11] = 0; if (L7[11] > 0 ) Ly_a[7] |= 0x0800; else Ly_a[7] &= ~0x0800; if (Ly_a[5] & 0x0800) Ly_a[6] |= 0x0800; else Ly_a[6] &= ~0x0800; if (Ly_a[4] & 0x0800) Ly_a[5] |= 0x0800; else Ly_a[5] &= ~0x0800; if (Ly_a[3] & 0x0800) Ly_a[4] |= 0x0800; else Ly_a[4] &= ~0x0800; Ly_a[3] &= ~0x0800; if (Ly_a[6] & 0x0400) L7[10] = 4; else L7[10]--; // A2 最下段は4回光ったままにする if (L7[10] < 0) L7[10] = 0; if (L7[10] > 0 ) Ly_a[7] |= 0x0400; else Ly_a[7] &= ~0x0400; if (Ly_a[5] & 0x0400) Ly_a[6] |= 0x0400; else Ly_a[6] &= ~0x0400; if (Ly_a[4] & 0x0400) Ly_a[5] |= 0x0400; else Ly_a[5] &= ~0x0400; if (Ly_a[3] & 0x0400) Ly_a[4] |= 0x0400; else Ly_a[4] &= ~0x0400; if (Ly_a[2] & 0x0400) Ly_a[3] |= 0x0400; else Ly_a[3] &= ~0x0400; Ly_a[2] &= ~0x0400; if (Ly_a[6] & 0x0200) L7[9] = 4; else L7[9]--; // A3 最下段は4回光ったままにする if (L7[9] < 0) L7[9] = 0; if (L7[9] > 0 ) Ly_a[7] |= 0x0200; else Ly_a[7] &= ~0x0200; if (Ly_a[5] & 0x0200) Ly_a[6] |= 0x0200; else Ly_a[6] &= ~0x0200; if (Ly_a[4] & 0x0200) Ly_a[5] |= 0x0200; else Ly_a[5] &= ~0x0200; if (Ly_a[3] & 0x0200) Ly_a[4] |= 0x0200; else Ly_a[4] &= ~0x0200; if (Ly_a[2] & 0x0200) Ly_a[3] |= 0x0200; else Ly_a[3] &= ~0x0200; if (Ly_a[1] & 0x0200) Ly_a[2] |= 0x0200; else Ly_a[2] &= ~0x0200; Ly_a[1] &= ~0x0200; if (Ly_a[6] & 0x0100) L7[8] = 4; else L7[8]--; // A4 最下段は4回光ったままにする if (L7[8] < 0) L7[8] = 0; if (L7[8] > 0 ) Ly_a[7] |= 0x0100; else Ly_a[7] &= ~0x0100; if (Ly_a[5] & 0x0100) Ly_a[6] |= 0x0100; else Ly_a[6] &= ~0x0100; if (Ly_a[4] & 0x0100) Ly_a[5] |= 0x0100; else Ly_a[5] &= ~0x0100; if (Ly_a[3] & 0x0100) Ly_a[4] |= 0x0100; else Ly_a[4] &= ~0x0100; if (Ly_a[2] & 0x0100) Ly_a[3] |= 0x0100; else Ly_a[3] &= ~0x0100; if (Ly_a[1] & 0x0100) Ly_a[2] |= 0x0100; else Ly_a[2] &= ~0x0100; Ly_a[1] &= ~0x0100; if (Ly_a[6] & 0x0080) L7[7] = 4; else L7[7]--; // A5 最下段は4回光ったままにする if (L7[7] < 0) L7[7] = 0; if (L7[7] > 0 ) Ly_a[7] |= 0x0080; else Ly_a[7] &= ~0x0080; if (Ly_a[5] & 0x0080) Ly_a[6] |= 0x0080; else Ly_a[6] &= ~0x0080; if (Ly_a[4] & 0x0080) Ly_a[5] |= 0x0080; else Ly_a[5] &= ~0x0080; if (Ly_a[3] & 0x0080) Ly_a[4] |= 0x0080; else Ly_a[4] &= ~0x0080; if (Ly_a[2] & 0x0080) Ly_a[3] |= 0x0080; else Ly_a[3] &= ~0x0080; if (Ly_a[1] & 0x0080) Ly_a[2] |= 0x0080; else Ly_a[2] &= ~0x0080; Ly_a[1] &= ~0x0080; if (Ly_a[6] & 0x0040) L7[6] = 4; else L7[6]--; // A6 最下段は4回光ったままにする if (L7[6] < 0) L7[6] = 0; if (L7[6] > 0 ) Ly_a[7] |= 0x0040; else Ly_a[7] &= ~0x0040; if (Ly_a[5] & 0x0040) Ly_a[6] |= 0x0040; else Ly_a[6] &= ~0x0040; if (Ly_a[4] & 0x0040) Ly_a[5] |= 0x0040; else Ly_a[5] &= ~0x0040; if (Ly_a[3] & 0x0040) Ly_a[4] |= 0x0040; else Ly_a[4] &= ~0x0040; if (Ly_a[2] & 0x0040) Ly_a[3] |= 0x0040; else Ly_a[3] &= ~0x0040; if (Ly_a[1] & 0x0040) Ly_a[2] |= 0x0040; else Ly_a[2] &= ~0x0040; Ly_a[1] &= ~0x0040; if (Ly_a[6] & 0x0020) L7[5] = 4; else L7[5]--; // A7 最下段は4回光ったままにする if (L7[5] < 0) L7[5] = 0; if (L7[5] > 0 ) Ly_a[7] |= 0x0020; else Ly_a[7] &= ~0x0020; if (Ly_a[5] & 0x0020) Ly_a[6] |= 0x0020; else Ly_a[6] &= ~0x0020; if (Ly_a[4] & 0x0020) Ly_a[5] |= 0x0020; else Ly_a[5] &= ~0x0020; if (Ly_a[3] & 0x0020) Ly_a[4] |= 0x0020; else Ly_a[4] &= ~0x0020; if (Ly_a[2] & 0x0020) Ly_a[3] |= 0x0020; else Ly_a[3] &= ~0x0020; Ly_a[2] &= ~0x0020; if (Ly_a[6] & 0x0010) L7[4] = 4; else L7[4]--; // A8 最下段は4回光ったままにする if (L7[4] < 0) L7[4] = 0; if (L7[4] > 0 ) Ly_a[7] |= 0x0010; else Ly_a[7] &= ~0x0010; if (Ly_a[5] & 0x0010) Ly_a[6] |= 0x0010; else Ly_a[6] &= ~0x0010; if (Ly_a[4] & 0x0010) Ly_a[5] |= 0x0010; else Ly_a[5] &= ~0x0010; if (Ly_a[3] & 0x0010) Ly_a[4] |= 0x0010; else Ly_a[4] &= ~0x0010; Ly_a[3] &= ~0x0010; // B1-B8ラインの星を流す if (Ly_b[6] & 0x0800) L7[12] = 4; else L7[12]--; // B1 最下段は4回光ったままにする if (L7[12] < 0) L7[12] = 0; if (L7[12] > 0 ) Ly_b[7] |= 0x1000; else Ly_b[7] &= ~0x1000; if (Ly_b[5] & 0x0400) Ly_b[6] |= 0x0800; else Ly_b[6] &= ~0x0800; if (Ly_b[4] & 0x0200) Ly_b[5] |= 0x0400; else Ly_b[5] &= ~0x0400; if (Ly_b[3] & 0x0100) Ly_b[4] |= 0x0200; else Ly_b[4] &= ~0x0200; Ly_b[3] &= ~0x0100; if (Ly_b[6] & 0x1000) L7[13] = 4; else L7[13]--; // B2 最下段は4回光ったままにする if (L7[13] < 0) L7[13] = 0; if (L7[13] > 0 ) Ly_b[7] |= 0x2000; else Ly_b[7] &= ~0x2000; if (Ly_b[5] & 0x0800) Ly_b[6] |= 0x1000; else Ly_b[6] &= ~0x1000; if (Ly_b[4] & 0x0400) Ly_b[5] |= 0x0800; else Ly_b[5] &= ~0x0800; if (Ly_b[3] & 0x0200) Ly_b[4] |= 0x0400; else Ly_b[4] &= ~0x0400; if (Ly_b[2] & 0x0100) Ly_b[3] |= 0x0200; else Ly_b[3] &= ~0x0200; Ly_b[2] &= ~0x0100; if (Ly_b[6] & 0x2000) L7[14] = 4; else L7[14]--; // B3 最下段は4回光ったままにする if (L7[14] < 0) L7[14] = 0; if (L7[14] > 0 ) Ly_b[7] |= 0x4000; else Ly_b[7] &= ~0x4000; if (Ly_b[5] & 0x1000) Ly_b[6] |= 0x2000; else Ly_b[6] &= ~0x2000; if (Ly_b[4] & 0x0800) Ly_b[5] |= 0x1000; else Ly_b[5] &= ~0x1000; if (Ly_b[3] & 0x0400) Ly_b[4] |= 0x0800; else Ly_b[4] &= ~0x0800; if (Ly_b[2] & 0x0200) Ly_b[3] |= 0x0400; else Ly_b[3] &= ~0x0400; if (Ly_b[1] & 0x0100) Ly_b[2] |= 0x0200; else Ly_b[2] &= ~0x0200; Ly_b[1] &= ~0x0100; if (Ly_b[6] & 0x4000) L7[15] = 4; else L7[15]--; // B4 最下段は4回光ったままにする if (L7[15] < 0) L7[15] = 0; if (L7[15] > 0 ) Ly_b[7] |= 0x8000; else Ly_b[7] &= ~0x8000; if (Ly_b[5] & 0x2000) Ly_b[6] |= 0x4000; else Ly_b[6] &= ~0x4000; if (Ly_b[4] & 0x1000) Ly_b[5] |= 0x2000; else Ly_b[5] &= ~0x2000; if (Ly_b[3] & 0x0800) Ly_b[4] |= 0x1000; else Ly_b[4] &= ~0x1000; if (Ly_b[2] & 0x0400) Ly_b[3] |= 0x0800; else Ly_b[3] &= ~0x0800; if (Ly_b[1] & 0x0200) Ly_b[2] |= 0x0400; else Ly_b[2] &= ~0x0400; Ly_b[1] &= ~0x0200; if (Ly_b[6] & 0x0002) L7[0] = 4; else L7[0]--; // B5 最下段は4回光ったままにする if (L7[0] < 0) L7[0] = 0; if (L7[0] > 0 ) Ly_b[7] |= 0x0001; else Ly_b[7] &= ~0x0001; if (Ly_b[5] & 0x0004) Ly_b[6] |= 0x0002; else Ly_b[6] &= ~0x0002; if (Ly_b[4] & 0x0008) Ly_b[5] |= 0x0004; else Ly_b[5] &= ~0x0004; if (Ly_b[3] & 0x0010) Ly_b[4] |= 0x0008; else Ly_b[4] &= ~0x0008; if (Ly_b[2] & 0x0020) Ly_b[3] |= 0x0010; else Ly_b[3] &= ~0x0010; if (Ly_b[1] & 0x0040) Ly_b[2] |= 0x0020; else Ly_b[2] &= ~0x0020; Ly_b[1] &= ~0x0040; if (Ly_b[6] & 0x0004) L7[1] = 4; else L7[1]--; // B6 最下段は4回光ったままにする if (L7[1] < 0) L7[1] = 0; if (L7[1] > 0 ) Ly_b[7] |= 0x0002; else Ly_b[7] &= ~0x0002; if (Ly_b[5] & 0x0008) Ly_b[6] |= 0x0004; else Ly_b[6] &= ~0x0004; if (Ly_b[4] & 0x0010) Ly_b[5] |= 0x0008; else Ly_b[5] &= ~0x0008; if (Ly_b[3] & 0x0020) Ly_b[4] |= 0x0010; else Ly_b[4] &= ~0x0010; if (Ly_b[2] & 0x0040) Ly_b[3] |= 0x0020; else Ly_b[3] &= ~0x0020; if (Ly_b[1] & 0x0080) Ly_b[2] |= 0x0040; else Ly_b[2] &= ~0x0040; Ly_b[1] &= ~0x0080; if (Ly_b[6] & 0x0008) L7[2] = 4; else L7[2]--; // B7 最下段は4回光ったままにする if (L7[2] < 0) L7[2] = 0; if (L7[2] > 0 ) Ly_b[7] |= 0x0004; else Ly_b[7] &= ~0x0004; if (Ly_b[5] & 0x0010) Ly_b[6] |= 0x0008; else Ly_b[6] &= ~0x0008; if (Ly_b[4] & 0x0020) Ly_b[5] |= 0x0010; else Ly_b[5] &= ~0x0010; if (Ly_b[3] & 0x0040) Ly_b[4] |= 0x0020; else Ly_b[4] &= ~0x0020; if (Ly_b[2] & 0x0080) Ly_b[3] |= 0x0040; else Ly_b[3] &= ~0x0040; Ly_b[2] &= ~0x0080; if (Ly_b[6] & 0x0010) L7[3] = 4; else L7[3]--; // B8 最下段は4回光ったままにする if (L7[3] < 0) L7[3] = 0; if (L7[3] > 0 ) Ly_b[7] |= 0x0008; else Ly_b[7] &= ~0x0008; if (Ly_b[5] & 0x0020) Ly_b[6] |= 0x0010; else Ly_b[6] &= ~0x0010; if (Ly_b[4] & 0x0040) Ly_b[5] |= 0x0020; else Ly_b[5] &= ~0x0020; if (Ly_b[3] & 0x0080) Ly_b[4] |= 0x0040; else Ly_b[4] &= ~0x0040; Ly_b[3] &= ~0x0080; } void varticalSeparate() { // 中央から縦に分ける allOn(); // 全点灯 show(500); Ly[0] &= ~0b0000000110000000; Ly[1] &= ~0b0000001111000000; Ly[2] &= ~0b0000010110100000; Ly[3] &= ~0b0000100110010000; Ly[4] &= ~0b0001000110001000; Ly[5] &= ~0b0010000110000100; Ly[6] &= ~0b0100000110000010; Ly[7] &= ~0b1000000110000001; // 中央を縦に消灯 show(200); Ly[2] &= ~0b0000001001000000; Ly[3] &= ~0b0000011001100000; Ly[4] &= ~0b0000101001010000; Ly[5] &= ~0b0001001001001000; Ly[6] &= ~0b0010001001000100; Ly[7] &= ~0b0100001001000010; // 消灯範囲を左右に拡大 show(200); Ly[4] &= ~0b0000010000100000; Ly[6] &= ~0b0001010000101000; Ly[5] &= ~0b0000110000110000; Ly[7] &= ~0b0010010000100100; // 消灯範囲を更に拡大 show(200); Ly[6] &= ~0b0000100000010000; Ly[7] &= ~0b0001100000011000; // 全消灯 show(300); } void setup() { m pinMode(16, OUTPUT); // 割込み確認LED pinMode(25, OUTPUT); // 内蔵LED add_repeating_timer_us(2000, tm1ms, NULL, &st_tm1ms); // タイマー割り込み起動(2ms) // ledTest1(); // ledTest2(); } void loop() { // 表示パターンのレシピ onOff(2); // 全点灯 propeller(1); // プロペラ starSpiralUp(2); // 下から上にスパイラルに点灯(前の内容によってはバグがあるかも?) fallingRing(3); // 落下するリング stackUpDown(2); // UP/DOWN swing(1); // スイング verticalCut(2); // 縦切り rotateAndClimb(2); // 回転しながら登る randomStar(3); // ランダム点灯 引数1で3秒間 fallingSnow(2); // 降雪、積雪 varticalSeparate(); // 中央から縦割り show(1000); }