// 56LEDクリスマスツリーイルミネーション 20201224_56LED_XmasTreeV130 // 2020/12/24 ラジオペンチ volatile unsigned int pM[8]; // 表示パターンメモリー unsigned int pMa[8], pMb[8]; // パターン操作用メモリー float bMag = 1.0; // 明るさ補正倍率 α (最終明るさ = αx + β) float bOffset = 0.0; // 明るさ補正オフセット β volatile byte bSet = 0; // 明るさ設定値(値は0-240, 0なら消灯) void setup() { Serial.begin(115200); pinMode(13, OUTPUT); tc2Setup(); // タイマー2の設定(2ms周期で割り込み) } void loop() { // 表示のデモ 引数で実行回数を指定しているので、本番用は適当に増やす fallingRing(4); // 落下するリング swing(1); // スイング verticalCut(2); // 縦切り rotateAndClimb(1); // 回転しながら登る randomStar(1); // ランダム fallingStar(2); // 流れ星 dimming(4); // 調光 show(1000); } void tc2Setup() { // ダイナミック点灯用のTC2の設定 // 設定方法は居酒屋ガレージ日記さんから下記の記事で教えてもらった。感謝! // http://igarage.cocolog-nifty.com/blog/2020/12/post-4c28b8.html cli(); // 割込禁止 TCCR2B = 0x00; // タイマー2いったん停止 TCCR2A = 0b00000010; // あらためてモード設定 //      |||| ++--- WGM: CTCモード OCR2Aでクリア //      ||++------- COM2B D3 PD3 標準ポート操作(OC2A切断) //     ++--------- COM2A D11 PB3 標準ポート操作(OC2B切断) TCCR2B = 0b00000101; // クロック設定 //       |+++--- CS:1/128 : 125kHz(8μsステップ) //       +------ WGM02 OCR2A = 250 - 1; // 250カウント周期(2ms周期で割り込み) OCR2B = 10 - 1; // 10カウント(80us)で割り込み(値は仮設定) TIMSK2 = 0b00000110; //        ||+---- TOIE2 オーバーフロー割り込みは無し //        |+----- OCIE2A コンペアマッチA割り込み有効 //        +------ OCIE2B コンペアマッチB割り込み有効 sei(); // 割込許可 } void fallingRing(int c) { // 水平線(リング)を下に移動 for (int n = 0; n < c; n++) { // 指定回数 clearArray(); pM[0] = 0xFFFF; // 先頭にネタを仕込んで for (int i = 0; i <= 6; i++) { show(100); // 見せるために待機 pM[i + 1] = pM[i]; // 一つ後ろ(下)にずらす pM[i] = 0; } } clearArray(); // 最後に消灯 delay(1000); } void swing(int n) { // 斜め線を右移動 for (int i = 0; i < n; i++) { // 指定回数 for (int j = 0; j < 2; j++) { // 左回転で3回 pM[0] = 0x0200; // 斜め線を仕込む pM[1] = 0x0400; pM[2] = 0x0800; pM[3] = 0x1000; pM[4] = 0x2000; pM[5] = 0x4000; pM[6] = 0x8000; for (int k = 0; k < 15; k++) { // 16回 for (int m = 0; m < 7; m++) { pM[m] = pM[m] >> 1; // 像を右シフト } show(50); // 表示のために待機 } } show(200); for (int j = 0; j < 2; j++) { // 右回転で3回 pM[0] = 0x0040; // 斜め線を仕込む pM[1] = 0x0020; pM[2] = 0x0010; pM[3] = 0x0008; pM[4] = 0x0004; pM[5] = 0x0002; pM[6] = 0x0001; for (int k = 0; k < 15; k++) { // 16回 for (int m = 0; m < 7; m++) { pM[m] = pM[m] << 1; // 像を右シフト } show(50); // 表示のために待機 } } show(200); for (int j = 0; j < 3; j++) { // 交差スイングで5回 pMa[0] = 0x0200; pMb[0] = 0x0040; // 両側に斜め線を仕込む pMa[1] = 0x0400; pMb[1] = 0x0020; pMa[2] = 0x0800; pMb[2] = 0x0010; pMa[3] = 0x1000; pMb[3] = 0x0008; pMa[4] = 0x2000; pMb[4] = 0x0004; pMa[5] = 0x4000; pMb[5] = 0x0002; pMa[6] = 0x8000; pMb[6] = 0x0001; for (int k = 0; k < 15; k++) { // 16回 for (int m = 0; m < 7; m++) { pMa[m] = pMa[m] >> 1; // aバッファの像を右シフト } for (int m = 0; m < 7; m++) { pMb[m] = pMb[m] << 1; // bバッファの像を左シフト } for (int m = 0; m <= 6; m++) { pM[m] = pMa[m] | pMb[m]; // 表示メモリに合成 } show(50); // 表示のために待機 } } show(500); } } void verticalCut(int n) { clearArray(); for (int i = 0; i < n; i++) { // 指定回数 // 左から右に点灯 pM[6] |= 0b0000100000000000; // 1 show(100); pM[6] |= 0b0001010000000000; // 2 pM[5] |= 0b0000110000000000; pM[4] |= 0b0000010000000000; show(100); pM[6] |= 0b0010001000000000; // 3 pM[5] |= 0b0001001000000000; pM[4] |= 0b0000101000000000; pM[3] |= 0b0000011000000000; pM[2] |= 0b0000001000000000; show(100); pM[6] |= 0b0100000100000000; // 4 pM[5] |= 0b0010000100000000; pM[4] |= 0b0001000100000000; pM[3] |= 0b0000100100000000; pM[2] |= 0b0000010100000000; pM[1] |= 0b0000001100000000; pM[0] |= 0b0000000100000000; show(100); pM[6] |= 0b0000000010000010; // 5 pM[5] |= 0b0000000010000100; pM[4] |= 0b0000000010001000; pM[3] |= 0b0000000010010000; pM[2] |= 0b0000000010100000; pM[1] |= 0b0000000011000000; pM[0] |= 0b0000000010000000; show(100); pM[6] |= 0b0000000001000100; // 6 pM[5] |= 0b0000000001001000; pM[4] |= 0b0000000001010000; pM[3] |= 0b0000000001100000; pM[2] |= 0b0000000001000000; show(100); pM[6] |= 0b0000000000101000; // 7 pM[5] |= 0b0000000000110000; pM[4] |= 0b0000000000100000; show(100); pM[6] |= 0b0000000000010000; // 8 show(500); // 左から右に消灯 pM[6] &= ~0b0000100000000000; // 1 show(100); pM[6] &= ~0b0001010000000000; // 2 pM[5] &= ~0b0000110000000000; pM[4] &= ~0b0000010000000000; show(100); pM[6] &= ~0b0010001000000000; // 3 pM[5] &= ~0b0001001000000000; pM[4] &= ~0b0000101000000000; pM[3] &= ~0b0000011000000000; pM[2] &= ~0b0000001000000000; show(100); pM[6] &= ~0b0100000100000000; // 4 pM[5] &= ~0b0010000100000000; pM[4] &= ~0b0001000100000000; pM[3] &= ~0b0000100100000000; pM[2] &= ~0b0000010100000000; pM[1] &= ~0b0000001100000000; pM[0] &= ~0b0000000100000000; show(100); pM[6] &= ~0b0000000010000010; // 5 pM[5] &= ~0b0000000010000100; pM[4] &= ~0b0000000010001000; pM[3] &= ~0b0000000010010000; pM[2] &= ~0b0000000010100000; pM[1] &= ~0b0000000011000000; pM[0] &= ~0b0000000010000000; show(100); pM[6] &= ~0b0000000001000100; // 6 pM[5] &= ~0b0000000001001000; pM[4] &= ~0b0000000001010000; pM[3] &= ~0b0000000001100000; pM[2] &= ~0b0000000001000000; show(100); pM[6] &= ~0b0000000000101000; // 7 pM[5] &= ~0b0000000000110000; pM[4] &= ~0b0000000000100000; show(150); pM[6] &= ~0b0000000000010000; // 8 右端まで点灯 show(500); // 右から左に点灯 pM[6] |= 0b0000000000010000; // 8 右端から点灯 show(100); pM[6] |= 0b0000000000101000; // 7 pM[5] |= 0b0000000000110000; pM[4] |= 0b0000000000100000; show(100); pM[6] |= 0b0000000001000100; // 6 pM[5] |= 0b0000000001001000; pM[4] |= 0b0000000001010000; pM[3] |= 0b0000000001100000; pM[2] |= 0b0000000001000000; show(100); pM[6] |= 0b0000000010000010; // 5 pM[5] |= 0b0000000010000100; pM[4] |= 0b0000000010001000; pM[3] |= 0b0000000010010000; pM[2] |= 0b0000000010100000; pM[1] |= 0b0000000011000000; pM[0] |= 0b0000000010000000; show(100); pM[6] |= 0b0100000100000000; // 4 pM[5] |= 0b0010000100000000; pM[4] |= 0b0001000100000000; pM[3] |= 0b0000100100000000; pM[2] |= 0b0000010100000000; pM[1] |= 0b0000001100000000; pM[0] |= 0b0000000100000000; show(100); pM[6] |= 0b0010001000000000; // 3 pM[5] |= 0b0001001000000000; pM[4] |= 0b0000101000000000; pM[3] |= 0b0000011000000000; pM[2] |= 0b0000001000000000; show(100); pM[6] |= 0b0001010000000000; // 2 pM[5] |= 0b0000110000000000; pM[4] |= 0b0000010000000000; show(100); pM[6] |= 0b0000100000000000; // 1 show(500); // 右から左に消灯 pM[6] &= ~0b0000000000010000; // 8 show(100); pM[6] &= ~0b0000000000101000; // 7 pM[5] &= ~0b0000000000110000; pM[4] &= ~0b0000000000100000; show(100); pM[6] &= ~0b0000000001000100; // 6 pM[5] &= ~0b0000000001001000; pM[4] &= ~0b0000000001010000; pM[3] &= ~0b0000000001100000; pM[2] &= ~0b0000000001000000; show(100); pM[6] &= ~0b0000000010000010; // 5 pM[5] &= ~0b0000000010000100; pM[4] &= ~0b0000000010001000; pM[3] &= ~0b0000000010010000; pM[2] &= ~0b0000000010100000; pM[1] &= ~0b0000000011000000; pM[0] &= ~0b0000000010000000; show(100); pM[6] &= ~0b0100000100000000; // 4 pM[5] &= ~0b0010000100000000; pM[4] &= ~0b0001000100000000; pM[3] &= ~0b0000100100000000; pM[2] &= ~0b0000010100000000; pM[1] &= ~0b0000001100000000; pM[0] &= ~0b0000000100000000; show(100); pM[6] &= ~0b0010001000000000; // 3 pM[5] &= ~0b0001001000000000; pM[4] &= ~0b0000101000000000; pM[3] &= ~0b0000011000000000; pM[2] &= ~0b0000001000000000; show(100); pM[6] &= ~0b0001010000000000; // 2 pM[5] &= ~0b0000110000000000; pM[4] &= ~0b0000010000000000; show(100); pM[6] &= ~0b0000100000000000; // 1 show(500); } } void rotateAndClimb(int n) { // 回転しながら登る clearArray(); for (int i = 0; i < n; i++) { // 指定回数 for (int j = 0; j < 56 * 3; j++) { if ( (j % 16) > 8) { // 8回置きに、 pM[6] |= 0x0002; // 一番下に星を埋め込む } else { pM[6] &= ~0x0002; // 星を消す } spiral(); show(100); } for (int j = 0; j < 56; j++) { pM[6] &= ~0x0002; spiral(); show(100); } } clearArray(); delay(1000); } void randomStar(int n) { // ランダムに点灯(徐々に点灯数を増やす) for (int i = 0; i < n; i++) { // 指定回数 for (int j = 0; j < 10; j++) { pM[0] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); // 点灯確率1/8 pM[0] |= 0x0180; // 先端の2個は常時点灯 pM[1] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); pM[2] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); pM[3] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); pM[4] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); pM[5] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); pM[6] = random(0, 0xFFFF) & random(0, 0xFFFF) & random(0, 0xFFFF); show(300); } for (int j = 0; j < 10; j++) { pM[0] = random(0, 0xFFFF) & random(0, 0xFFFF); // 点灯確率1/4 pM[0] |= 0x0180; // 先端の2個は常時点灯 pM[1] = random(0, 0xFFFF) & random(0, 0xFFFF); pM[2] = random(0, 0xFFFF) & random(0, 0xFFFF); pM[3] = random(0, 0xFFFF) & random(0, 0xFFFF); pM[4] = random(0, 0xFFFF) & random(0, 0xFFFF); pM[5] = random(0, 0xFFFF) & random(0, 0xFFFF); pM[6] = random(0, 0xFFFF) & random(0, 0xFFFF); show(300); } for (int j = 0; j < 20; j++) { pM[0] = random(0, 0xFFFF); // 点灯確率1/2 pM[0] |= 0x0180; // 先端の2個は常時点灯 pM[1] = random(0, 0xFFFF); pM[2] = random(0, 0xFFFF); pM[3] = random(0, 0xFFFF); pM[4] = random(0, 0xFFFF); pM[5] = random(0, 0xFFFF); pM[6] = random(0, 0xFFFF); show(300); } } // loop n clearArray(); show(1000); } void fallingStar(int n) { // 流れ星 int p = 10; // 星の出現確率(値が大きいと星の量が減る) for (int k = 0; k < n * 50 ; k++) { // if (random(0, p) == 0) pMa[3] = 0x0800; // A1ラインの種(あまり綺麗でないのでやめた) if (random(0, p) == 0) pMa[2] = 0x0400; // A2ラインの種 if (random(0, p) == 0) pMa[1] = 0x0200; // A3ラインの種 if (random(0, p) == 0) pMa[1] = 0x0100; // A4ラインの種 if (random(0, p) == 0) pMa[1] = 0x0080; // A5ラインの種 if (random(0, p) == 0) pMa[1] = 0x0040; // A6ラインの種 if (random(0, p) == 0) pMa[2] = 0x0020; // A7ラインの種 // if (random(0, p) == 0) pMa[3] = 0x0010; // A8ラインの種 // if (random(0, p) == 0) pMb[3] = 0x0100; // B1ラインの種 if (random(0, p) == 0) pMb[2] = 0x0100; // B2ラインの種 if (random(0, p) == 0) pMb[1] = 0x0100; // B3ラインの種 if (random(0, p) == 0) pMb[1] = 0x0200; // B4ラインの種 if (random(0, p) == 0) pMb[1] = 0x0040; // B5ラインの種 if (random(0, p) == 0) pMb[1] = 0x0080; // B6ラインの種 if (random(0, p) == 0) pMb[2] = 0x0080; // B7ラインの種 // if (random(0, p) == 0) pMb[3] = 0x0080; // B8ラインの種 for (int j = 0; j < 7; j++) { pM[j] = pMa[j] | pMb[j]; // 表示メモリに転送 } pM[0] |= 0x0180; //先端の星を点灯 show(80); stepDown(); // 星を一つ下に流す } // next k clearArray(); show(1000); } void stepDown() { // バッファ内の星をルートに従い下に落とす if (pMa[5] & 0x0800) pMa[6] |= 0x0800; else pMa[6] &= ~0x0800; // A1 if (pMa[4] & 0x0800) pMa[5] |= 0x0800; else pMa[5] &= ~0x0800; if (pMa[3] & 0x0800) pMa[4] |= 0x0800; else pMa[4] &= ~0x0800; pMa[3] &= ~0x0800; if (pMa[5] & 0x0400) pMa[6] |= 0x0400; else pMa[6] &= ~0x0400; // A2 if (pMa[4] & 0x0400) pMa[5] |= 0x0400; else pMa[5] &= ~0x0400; if (pMa[3] & 0x0400) pMa[4] |= 0x0400; else pMa[4] &= ~0x0400; if (pMa[2] & 0x0400) pMa[3] |= 0x0400; else pMa[3] &= ~0x0400; pMa[2] &= ~0x0400; if (pMa[5] & 0x0200) pMa[6] |= 0x0200; else pMa[6] &= ~0x0200; // A3 if (pMa[4] & 0x0200) pMa[5] |= 0x0200; else pMa[5] &= ~0x0200; if (pMa[3] & 0x0200) pMa[4] |= 0x0200; else pMa[4] &= ~0x0200; if (pMa[2] & 0x0200) pMa[3] |= 0x0200; else pMa[3] &= ~0x0200; if (pMa[1] & 0x0200) pMa[2] |= 0x0200; else pMa[2] &= ~0x0200; pMa[1] &= ~0x0200; if (pMa[5] & 0x0100) pMa[6] |= 0x0100; else pMa[6] &= ~0x0100; // A4 if (pMa[4] & 0x0100) pMa[5] |= 0x0100; else pMa[5] &= ~0x0100; if (pMa[3] & 0x0100) pMa[4] |= 0x0100; else pMa[4] &= ~0x0100; if (pMa[2] & 0x0100) pMa[3] |= 0x0100; else pMa[3] &= ~0x0100; if (pMa[1] & 0x0100) pMa[2] |= 0x0100; else pMa[2] &= ~0x0100; pMa[1] &= ~0x0100; if (pMa[5] & 0x0080) pMa[6] |= 0x0080; else pMa[6] &= ~0x0080; // A5 if (pMa[4] & 0x0080) pMa[5] |= 0x0080; else pMa[5] &= ~0x0080; if (pMa[3] & 0x0080) pMa[4] |= 0x0080; else pMa[4] &= ~0x0080; if (pMa[2] & 0x0080) pMa[3] |= 0x0080; else pMa[3] &= ~0x0080; if (pMa[1] & 0x0080) pMa[2] |= 0x0080; else pMa[2] &= ~0x0080; pMa[1] &= ~0x0080; if (pMa[5] & 0x0040) pMa[6] |= 0x0040; else pMa[6] &= ~0x0040; // A6 if (pMa[4] & 0x0040) pMa[5] |= 0x0040; else pMa[5] &= ~0x0040; if (pMa[3] & 0x0040) pMa[4] |= 0x0040; else pMa[4] &= ~0x0040; if (pMa[2] & 0x0040) pMa[3] |= 0x0040; else pMa[3] &= ~0x0040; if (pMa[1] & 0x0040) pMa[2] |= 0x0040; else pMa[2] &= ~0x0040; pMa[1] &= ~0x0040; if (pMa[5] & 0x0020) pMa[6] |= 0x0020; else pMa[6] &= ~0x0020; // A7 if (pMa[4] & 0x0020) pMa[5] |= 0x0020; else pMa[5] &= ~0x0020; if (pMa[3] & 0x0020) pMa[4] |= 0x0020; else pMa[4] &= ~0x0020; if (pMa[2] & 0x0020) pMa[3] |= 0x0020; else pMa[3] &= ~0x0020; pMa[2] &= ~0x0020; if (pMa[5] & 0x0010) pMa[6] |= 0x0010; else pMa[6] &= ~0x0010; // A8 if (pMa[4] & 0x0010) pMa[5] |= 0x0010; else pMa[5] &= ~0x0010; if (pMa[3] & 0x0010) pMa[4] |= 0x0010; else pMa[4] &= ~0x0010; pMa[3] &= ~0x0010; // B1-B8ラインの星を流す if (pMb[5] & 0x0400) pMb[6] |= 0x0800; else pMb[6] &= ~0x0800; // B1 if (pMb[4] & 0x0200) pMb[5] |= 0x0400; else pMb[5] &= ~0x0400; if (pMb[3] & 0x0100) pMb[4] |= 0x0200; else pMb[4] &= ~0x0200; pMb[3] &= ~0x0100; if (pMb[5] & 0x0800) pMb[6] |= 0x1000; else pMb[6] &= ~0x1000; // B2 if (pMb[4] & 0x0400) pMb[5] |= 0x0800; else pMb[5] &= ~0x0800; if (pMb[3] & 0x0200) pMb[4] |= 0x0400; else pMb[4] &= ~0x0400; if (pMb[2] & 0x0100) pMb[3] |= 0x0200; else pMb[3] &= ~0x0200; pMb[2] &= ~0x0100; if (pMb[5] & 0x1000) pMb[6] |= 0x2000; else pMb[6] &= ~0x2000; // B3 if (pMb[4] & 0x0800) pMb[5] |= 0x1000; else pMb[5] &= ~0x1000; if (pMb[3] & 0x0400) pMb[4] |= 0x0800; else pMb[4] &= ~0x0800; if (pMb[2] & 0x0200) pMb[3] |= 0x0400; else pMb[3] &= ~0x0400; if (pMb[1] & 0x0100) pMb[2] |= 0x0200; else pMb[2] &= ~0x0200; pMb[1] &= ~0x0100; if (pMb[5] & 0x2000) pMb[6] |= 0x4000; else pMb[6] &= ~0x4000; // B4 if (pMb[4] & 0x1000) pMb[5] |= 0x2000; else pMb[5] &= ~0x2000; if (pMb[3] & 0x0800) pMb[4] |= 0x1000; else pMb[4] &= ~0x1000; if (pMb[2] & 0x0400) pMb[3] |= 0x0800; else pMb[3] &= ~0x0800; if (pMb[1] & 0x0200) pMb[2] |= 0x0400; else pMb[2] &= ~0x0400; pMb[1] &= ~0x0200; if (pMb[5] & 0x0004) pMb[6] |= 0x0002; else pMb[6] &= ~0x0002; // B5 if (pMb[4] & 0x0008) pMb[5] |= 0x0004; else pMb[5] &= ~0x0004; if (pMb[3] & 0x0010) pMb[4] |= 0x0008; else pMb[4] &= ~0x0008; if (pMb[2] & 0x0020) pMb[3] |= 0x0010; else pMb[3] &= ~0x0010; if (pMb[1] & 0x0040) pMb[2] |= 0x0020; else pMb[2] &= ~0x0020; pMb[1] &= ~0x0040; if (pMb[5] & 0x0008) pMb[6] |= 0x0004; else pMb[6] &= ~0x0004; // B6 if (pMb[4] & 0x0010) pMb[5] |= 0x0008; else pMb[5] &= ~0x0008; if (pMb[3] & 0x0020) pMb[4] |= 0x0010; else pMb[4] &= ~0x0010; if (pMb[2] & 0x0040) pMb[3] |= 0x0020; else pMb[3] &= ~0x0020; if (pMb[1] & 0x0080) pMb[2] |= 0x0040; else pMb[2] &= ~0x0040; pMb[1] &= ~0x0080; if (pMb[5] & 0x0010) pMb[6] |= 0x0008; else pMb[6] &= ~0x0008; // B7 if (pMb[4] & 0x0020) pMb[5] |= 0x0010; else pMb[5] &= ~0x0010; if (pMb[3] & 0x0040) pMb[4] |= 0x0020; else pMb[4] &= ~0x0020; if (pMb[2] & 0x0080) pMb[3] |= 0x0040; else pMb[3] &= ~0x0040; pMb[2] &= ~0x0080; if (pMb[5] & 0x0020) pMb[6] |= 0x0010; else pMb[6] &= ~0x0010; // B8 if (pMb[4] & 0x0040) pMb[5] |= 0x0020; else pMb[5] &= ~0x0020; if (pMb[3] & 0x0080) pMb[4] |= 0x0040; else pMb[4] &= ~0x0040; pMb[3] &= ~0x0080; } void dimming(int c) { // ゆっくり増光、減光 float x, ratio; bMag = 0.0; // 一旦光量ゼロに設定 show(10); // 明るさ設定値を反映させる pM[0] = 0xFFFF; // 表示パターン設定 pM[1] = 0xFFFF; pM[2] = 0xFFFF; pM[3] = 0xFFFF; pM[4] = 0xFFFF; pM[5] = 0xFFFF; pM[6] = 0xFFFF; x = OCR2B; // 開始時の明るさを記録 ratio = pow(2.0 * x, 1.0 / 40.0); // 明るさを2倍にするための増光比率を計算 for (int j = 0; j < c; j++) { // 指定回数 bMag = 1.0 / x; for (int i = 0; i <= 40; i++) { // 等比級数で増光 bMag *= ratio; // 値を補正 show(30); } for (int i = 40; i >= 0; i--) { // 減光 bMag /= ratio; show(30); } show(100); } clearArray(); // パターンメモリーを消す bMag = 1.0; // 明るさ補正係数をデフォルトに戻す show(500); // 最後に消灯 } void clearArray() { // パターンメモリー消去 for (int i = 0; i < 8; i++) { pM[i] = 0; pMa[i] = 0; pMb[i] = 0; } } void spiral() { // スパイラル上昇 pM[0] &= 0x0180; // 表示領域外をクリア pM[1] &= 0x03C0; pM[2] &= 0x07E0; pM[3] &= 0x0FF0; pM[4] &= 0x1FF8; pM[5] &= 0x3FFC; pM[6] &= 0x7FFE; pM[0] = pM[0] << 1; if (pM[1] & 0x0200) pM[0] |= 0x0080; // pM[1]の左端が1だったら、pM[0]の右端を1にする pM[1] = pM[1] << 1; if (pM[2] & 0x0400) pM[1] |= 0x0040; // pM[2]の左端が1だったら、pM[1]の右端を1にする pM[2] = pM[2] << 1; if (pM[3] & 0x0800) pM[2] |= 0x0020; // pM[3]の左端が1だったら、pM[2]の右端を1にする pM[3] = pM[3] << 1; if (pM[4] & 0x1000) pM[3] |= 0x0010; // pM[4]の左端が1だったら、pM[3]の右端を1にする pM[4] = pM[4] << 1; if (pM[5] & 0x2000) pM[4] |= 0x0008; // pM[5]の左端が1だったら、pM[4]の右端を1にする pM[5] = pM[5] << 1; if (pM[6] & 0x4000) pM[5] |= 0x0004; // pM[6]の左端が1だったら、pM[5]の右端を1にする pM[6] = pM[6] << 1; } void show(unsigned long t) { // 見せるために指定時間待機。同時に調光の計算を行う int x; delay(t); x = analogRead(0); // 明るさセンサの値を読む x = map(x, 0, 1023, 10, 240); // ADCの値を10-240の範囲にスケーリング x = x * bMag + bOffset; // 明るさ補正計算 bSet = constrain(x, 0, 240); // 最終的な明るさ(割込みルーチンでPWMの設定用に使用) } ISR(TIMER2_COMPA_vect) { // タイマー2 A割り込み(指定LEDを点灯) static int scanN = 0; // リフレッシュ位置カウンタ if (bSet > 0) { // 明るさ設定値が0以上なら(bSetは8ビットなので割込み禁止しなくてもOK) 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; default: break; } } scanN ++; // スキャン番号を更新 if (scanN > 7) { // 上限超えたらゼロに戻す scanN = 0; } } ISR(TIMER2_COMPB_vect) { // タイマー2 B割り込み(消灯と明るさ設定) int bSetBuff; ledOff(); // 全LED消灯 bSetBuff = bSet; // 処理中に値が変わると困るのでコピー(bSetは8ビットなので割込み禁止しなくてもOK) if (bSetBuff <= 0) { // 0かマイナスなら OCR2B = 0; // OCR2Bに0を設定(0を設定しても最小時間光るので COMPA 側で強制消灯させる) } else { // そうでなければ(1以上なら) OCR2B = bSetBuff - 1; // マイナス1した値を設定 } } int getBright() { // 明るさを測定して 0-240の値に変換 int x; x = analogRead(0); // 明るさセンサの値を読む x = map(x, 0, 1023, 10, 240); // ADCの値を10-240の範囲にスケーリング return x; } void d2High() { // D2ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000000000000010 ) DDRD |= B00001000; // D3 を出力にアサイン if ( pM[6] & 0b0000000000001000 ) DDRD |= B00010000; // D4 if ( pM[6] & 0b0000000000100000 ) DDRD |= B00100000; // D5 if ( pM[6] & 0b0000000010000000 ) DDRD |= B01000000; // D6 if ( pM[6] & 0b0000001000000000 ) DDRD |= B10000000; // D7 if ( pM[6] & 0b0000100000000000 ) DDRB |= B00000001; // D8 ここからBポート if ( pM[6] & 0b0010000000000000 ) DDRB |= B00000010; // D9 DDRD |= B00000100; // D2を出力にアサイン PORTD |= B00000100; // D2をHigh。これでLED点灯(光量最小化のため最後にやる) } void d3High() { // D3ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000000000000100 ) DDRD |= B00000100; // D2 を出力にアサイン if ( pM[5] & 0b0000000000000100 ) DDRD |= B00010000; // D4 if ( pM[5] & 0b0000000000010000 ) DDRD |= B00100000; // D5 if ( pM[5] & 0b0000000001000000 ) DDRD |= B01000000; // D6 if ( pM[5] & 0b0000000100000000 ) DDRD |= B10000000; // D7 if ( pM[5] & 0b0000010000000000 ) DDRB |= B00000001; // D8 ここからBポート if ( pM[5] & 0b0001000000000000 ) DDRB |= B00000010; // D9 DDRD |= B00001000; // D3を出力にアサイン PORTD |= B00001000; // D3をHigh(これでLEDが光る) } void d4High() { // D4ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000000000010000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0000000000001000 ) DDRD |= B00001000; if ( pM[4] & 0b0000000000001000 ) DDRD |= B00100000; if ( pM[4] & 0b0000000000100000 ) DDRD |= B01000000; if ( pM[4] & 0b0000000010000000 ) DDRD |= B10000000; if ( pM[4] & 0b0000001000000000 ) DDRB |= B00000001; // ここからBポート if ( pM[4] & 0b0000100000000000 ) DDRB |= B00000010; DDRD |= B00010000; // D4を出力にアサイン PORTD |= B00010000; // D4をHigh(これでLEDが光る) } void d5High() { // D5ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000000001000000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0000000000100000 ) DDRD |= B00001000; if ( pM[4] & 0b0000000000010000 ) DDRD |= B00010000; if ( pM[3] & 0b0000000000010000 ) DDRD |= B01000000; if ( pM[3] & 0b0000000001000000 ) DDRD |= B10000000; if ( pM[3] & 0b0000000100000000 ) DDRB |= B00000001; // ここからBポート if ( pM[3] & 0b0000010000000000 ) DDRB |= B00000010; DDRD |= B00100000; // D5を出力にアサイン PORTD |= B00100000; // D5をHigh(これでLEDが光る) } void d6High() { // D6ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000000100000000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0000000010000000 ) DDRD |= B00001000; if ( pM[4] & 0b0000000001000000 ) DDRD |= B00010000; if ( pM[3] & 0b0000000000100000 ) DDRD |= B00100000; if ( pM[2] & 0b0000000000100000 ) DDRD |= B10000000; if ( pM[2] & 0b0000000010000000 ) DDRB |= B00000001; // ここからBポート if ( pM[2] & 0b0000001000000000 ) DDRB |= B00000010; DDRD |= B01000000; // D6を出力にアサイン PORTD |= B01000000; // D6をHigh(これでLEDが光る) } void d7High() { // D7ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0000010000000000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0000001000000000 ) DDRD |= B00001000; if ( pM[4] & 0b0000000100000000 ) DDRD |= B00010000; if ( pM[3] & 0b0000000010000000 ) DDRD |= B00100000; if ( pM[2] & 0b0000000001000000 ) DDRD |= B01000000; if ( pM[1] & 0b0000000001000000 ) DDRB |= B00000001; // ここからBポート if ( pM[1] & 0b0000000100000000 ) DDRB |= B00000010; DDRD |= B10000000; // D7を出力にアサイン PORTD |= B10000000; // D7をHigh(これでLEDが光る) } void d8High() { // D8ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0001000000000000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0000100000000000 ) DDRD |= B00001000; if ( pM[4] & 0b0000010000000000 ) DDRD |= B00010000; if ( pM[3] & 0b0000001000000000 ) DDRD |= B00100000; if ( pM[2] & 0b0000000100000000 ) DDRD |= B01000000; if ( pM[1] & 0b0000000010000000 ) DDRD |= B10000000; if ( pM[0] & 0b0000000010000000 ) DDRB |= B00000010; // D9 DDRB |= B00000001; // D8を出力にアサイン PORTB |= B00000001; // D8をHigh(これでLEDが光る) } void d9High() { // D8ポートからHighを出力し、指定のLEDを点灯 ledOff(); // LEDポートを初期化(入力でLowに設定) if ( pM[6] & 0b0100000000000000 ) DDRD |= B00000100; // 該当ビットを出力にアサイン if ( pM[5] & 0b0010000000000000 ) DDRD |= B00001000; if ( pM[4] & 0b0001000000000000 ) DDRD |= B00010000; if ( pM[3] & 0b0000100000000000 ) DDRD |= B00100000; if ( pM[2] & 0b0000010000000000 ) DDRD |= B01000000; if ( pM[1] & 0b0000001000000000 ) DDRD |= B10000000; if ( pM[0] & 0b0000000100000000 ) DDRB |= B00000001; // D8 DDRB |= B00000010; // D9を出力にアサイン PORTB |= B00000010; // D9をHigh(これでLEDが光る) } void ledOff() { // 全LED消灯(LED接続ピンを全て入力/Lowに設定) PORTD &= B00000011; // D2-7をLOW PORTB &= B11111100; // D8,9をLOW DDRD &= B00000010; // D2-7を入力にアサイン DDRB &= B11111100; // D8,9を入力にアサイン }