/*----------------------------------------------------------------------*/ /* poslamp.c - ポジションランプ用ファームウェア */ /* */ /* ※取り敢えず ATMEL AT90S2313 用 */ /*----------------------------------------------------------------------*/ /* ********** 修正履歴 * No. Date Comments By * --- ---------- --------------------------------------------- ---------- * 001 2002/04/13 新規作成(取り敢えず白で点灯)。 Terashima * 002 2002/04/13 3個のLEDの色が個別に変化するパターンに変更。 Terashima * --- ---------- --------------------------------------------- ---------- * 003 2002/04/14 Version 1.00 Terashima * 以下の3つの動作モードを電源投入で切り替えする * ようにして正式版とする。 * NORMAL: 常時白色点灯 * DEMO1 : 3個のLEDの色が個別に変化する * DEMO2 : ナイトライダー風 * 004 2002/04/21 Version 1.10 Terashima * LED基板の変更によるI/Oポート再割り当て。 * 005 2002/04/28 Version 1.20 Terashima * 動作モードを追加&変更。 * NORMAL: 常時白色点灯 * DEMO1A: 3個のLEDの色が同時に変化する * DEMO1B: 3個のLEDの色が同時に変化し点滅する * DEMO2 : ナイトライダー風 * DEMO3 : 白色で点滅する * 006 2002/04/30 Version 1.30 Terashima * 以下の修正。 * 1) LED左右逆転を修正。 * 2) DEMO2 の開始を動きのある所からに修正。 * * */ #include #include #include #include #include #define SYSCLK 10000000L /* CLK = 10MHz */ /*----------------------------------------------------------------------*/ /* 各種マクロ定義 */ /*----------------------------------------------------------------------*/ #define TRUE (1==1) #define FALSE (1==0) /*----------------------------------------------------------------------*/ /* EEPROM 割り当て定義 */ /*----------------------------------------------------------------------*/ #define EEPROM_MODE_BYTE 0x10 /* 点灯モード保存領域 */ # define MODE_NORMAL 0xFF /* 通常(白色全点灯) */ # define MODE_DEMO1A 0x00 /* 3個のLEDの色が個別に変化 */ # define MODE_DEMO1B 0x01 /* LEDの色が変化しながら点滅 */ # define MODE_DEMO2 0x02 /* 左右へ流れる */ # define MODE_DEMO3 0x03 /* 白の点滅 */ /*----------------------------------------------------------------------*/ /* I/Oポート割り当て定義 */ /* */ /* --- ---- ----------------------------------------------------------- */ /* PD0:+OUT (予備) */ /* PD1:+OUT (予備) */ /* PD2:+OUT (予備) */ /* PD3:+OUT (予備) */ /* PD4:+OUT (予備) */ /* PD5:+OUT (予備) */ /* PD6:-OUT 左側-緑LED(0:点灯、1:消灯) */ /* --- ---- ----------------------------------------------------------- */ /* PB0:-OUT 左側-青LED(0:点灯、1:消灯) */ /* PB1:-OUT 左側-赤LED(0:点灯、1:消灯) */ /* PB2:-OUT 中央-緑LED(0:点灯、1:消灯) */ /* PB3:-OUT 中央-青LED(0:点灯、1:消灯) */ /* PB4:-OUT 中央-赤LED(0:点灯、1:消灯) */ /* PB5:-OUT 右側-緑LED(0:点灯、1:消灯) */ /* PB6:-OUT 右側-青LED(0:点灯、1:消灯) */ /* PB7:-OUT 右側-赤LED(0:点灯、1:消灯) */ /*----------------------------------------------------------------------*/ #define LG_On() cbi(PORTD, PD6) #define LG_Off() sbi(PORTD, PD6) #define LB_On() cbi(PORTB, PB0) #define LB_Off() sbi(PORTB, PB0) #define LR_On() cbi(PORTB, PB1) #define LR_Off() sbi(PORTB, PB1) #define CG_On() cbi(PORTB, PB2) #define CG_Off() sbi(PORTB, PB2) #define CB_On() cbi(PORTB, PB3) #define CB_Off() sbi(PORTB, PB3) #define CR_On() cbi(PORTB, PB4) #define CR_Off() sbi(PORTB, PB4) #define RG_On() cbi(PORTB, PB5) #define RG_Off() sbi(PORTB, PB5) #define RB_On() cbi(PORTB, PB6) #define RB_Off() sbi(PORTB, PB6) #define RR_On() cbi(PORTB, PB7) #define RR_Off() sbi(PORTB, PB7) #define PORTB_OMASK 0xFF #define PORTD_OMASK 0x7F #define PORTB_NEG 0xFF #define PORTD_NEG 0x40 /*----------------------------------------------------------------------*/ /* 大域変数 */ /*----------------------------------------------------------------------*/ volatile int t_tick; /* 0.1ms周期にONになるフラグ */ struct RGB_CTRL { int red; int green; int blue; unsigned char timer; } led_left, led_center, led_right; char led_off; /*----------------------------------------------------------------------*/ /* I/Oポート初期化 */ /* void InitPorts(void) */ /*----------------------------------------------------------------------*/ static inline void InitPorts(void) { /* 全入力ポートをプルアップ抵抗有りにする */ outp(0xFF, PORTB); outp(0xFF, PORTD); /* 全ての出力をOFFに初期化しておく */ LR_Off(); LG_Off(); LB_Off(); CR_Off(); CG_Off(); CB_Off(); RR_Off(); RG_Off(); RB_Off(); /* 出力ポートを設定する */ outp(PORTB_OMASK, DDRB); outp(PORTD_OMASK, DDRD); } /*----------------------------------------------------------------------*/ /* RGB輝度設定 */ /*----------------------------------------------------------------------*/ void RGB_Setup(struct RGB_CTRL *rgb, int r, int g, int b) { cli(); rgb->red = (r * 64) / 255; rgb->green = (g * 64) / 255; rgb->blue = (b * 64) / 255; sei(); } /*----------------------------------------------------------------------*/ /* ワークエリア初期化 */ /* void InitWorkArea(void) */ /*----------------------------------------------------------------------*/ static inline void InitWorkArea(void) { t_tick = FALSE; led_off = FALSE; /* LEDを白色で全点灯 */ RGB_Setup(&led_left, 255, 255, 255); RGB_Setup(&led_center, 255, 255, 255); RGB_Setup(&led_right, 255, 255, 255); } /*----------------------------------------------------------------------*/ /* フルカラーLED制御 */ /*----------------------------------------------------------------------*/ void LED_Control() { if (led_left.timer < led_left.red) { LR_On(); } else { LR_Off(); } if (led_left.timer < led_left.green) { LG_On(); } else { LG_Off(); } if (led_left.timer < led_left.blue) { LB_On(); } else { LB_Off(); } led_left.timer = (led_left.timer < 63) ? led_left.timer + 1 : 0; if (led_center.timer < led_center.red) { CR_On(); } else { CR_Off(); } if (led_center.timer < led_center.green) { CG_On(); } else { CG_Off(); } if (led_center.timer < led_center.blue) { CB_On(); } else { CB_Off(); } led_center.timer = (led_center.timer < 63) ? led_center.timer + 1 : 0; if (led_right.timer < led_right.red) { RR_On(); } else { RR_Off(); } if (led_right.timer < led_right.green) { RG_On(); } else { RG_Off(); } if (led_right.timer < led_right.blue) { RB_On(); } else { RB_Off(); } led_right.timer = (led_right.timer < 63) ? led_right.timer + 1 : 0; } /*----------------------------------------------------------------------*/ /* 0.1ms周期タイマ(TMR0割り込み)ハンドラ */ /*----------------------------------------------------------------------*/ SIGNAL(SIG_OVERFLOW0) { /* 1ms周期に CNT0 をリロードする */ outp(256-(SYSCLK/10/(8L*1000L)), TCNT0); if (led_off) { LR_Off(); LG_Off(); LB_Off(); CR_Off(); CG_Off(); CB_Off(); RR_Off(); RG_Off(); RB_Off(); } else { LED_Control(); } t_tick = TRUE; } /*----------------------------------------------------------------------*/ /* TMR0 初期化 (1ms周期) */ /* void InitTMR0(void) */ /*----------------------------------------------------------------------*/ void InitTMR0(void) { /* 0.1ms周期に CNT0 を初期化する */ outp(256-(SYSCLK/10/(8L*1000L)), TCNT0); outp(2, TCCR0); /* CK/8 にプリスケーラを設定 */ /* TMR0 割り込みを許可する */ outp(inp(TIMSK)|BV(TOIE0),TIMSK); } /*----------------------------------------------------------------------*/ /* 指定時間待ち */ /*----------------------------------------------------------------------*/ void t_sleep(int timer) { while (timer > 0) { int i; for (i = 0; i < 10; i++) { /* 10回待って1ms待ちにする */ while (!t_tick) { /* 0.1ms 同期タイミング待ち */ asm("sleep"); /* タイマ割込みを待つ */ } t_tick = FALSE; } timer--; } } /*----------------------------------------------------------------------*/ /* 動作モードを得る */ /*----------------------------------------------------------------------*/ int LoadMode() { while (!eeprom_is_ready()) ; return eeprom_rb(EEPROM_MODE_BYTE); } /*----------------------------------------------------------------------*/ /* 次回起動時の動作モードを保存する */ /*----------------------------------------------------------------------*/ void SaveMode(int mode) { while (!eeprom_is_ready()) ; eeprom_wb(EEPROM_MODE_BYTE, mode); } /*----------------------------------------------------------------------*/ /* デモパターン1 */ /*----------------------------------------------------------------------*/ void Demo1(int sw) { int r, g, b; char sr, sg, sb; #if 0 /* 起動デモパターン表示 */ RGB_Setup(&led_right, 0, 255, 128); RGB_Setup(&led_center, 255, 255, 0); RGB_Setup(&led_left, 255, 0, 0); t_sleep(1000); /* ROM容量が足りないので起動デモは無し */ RGB_Setup(&led_right, 255, 0, 0); RGB_Setup(&led_center, 0, 0, 0); RGB_Setup(&led_left, 0, 0, 0); t_sleep(1000); RGB_Setup(&led_center, 255, 0, 0); t_sleep(1000); RGB_Setup(&led_left, 255, 0, 0); t_sleep(1000); RGB_Setup(&led_right, 0, 255, 128); RGB_Setup(&led_center, 0, 255, 128); RGB_Setup(&led_left, 0, 255, 128); t_sleep(1000); #endif /* メインループ */ r = 0; g = 100; b = 200; sr = 5; sg = 3; sb = 2; while (1) { r += sr; g += sg; b += sb; if (r < 0) { r = 0; sr = -sr; } else if (r > 255) { r = 255; sr = -sr; } if (g < 50) { g = 50; sg = -sg; } else if (g > 255) { g = 255; sg = -sg; } if (b < 0) { b = 0; sb = -sb; } else if (b > 255) { b = 255; sb = -sb; } RGB_Setup(&led_left, r, g, b); RGB_Setup(&led_center, r, g, b); RGB_Setup(&led_right, r, g, b); if (sw == 0) { t_sleep(30); /* 30ms待ち */ } else { led_off = FALSE; /* LED点灯 */ t_sleep(80); /* 80ms待ち */ led_off = TRUE; /* LED消灯 */ t_sleep(80); /* 80ms待ち */ } } } /*----------------------------------------------------------------------*/ /* デモパターン2 */ /*----------------------------------------------------------------------*/ PROGMEM char ctbl[8][3] = { /* R G B */ { 0, 0, 0 }, /* 黒(消灯) */ { 0, 0, 255 }, /* 青 */ { 0, 255, 0 }, /* 緑 */ { 0, 255, 255 }, /* 水色 */ { 255, 0, 0 }, /* 赤 */ { 255, 0, 255 }, /* 紫 */ { 255, 255, 0 }, /* 黄 */ { 255, 255, 255 } /* 白 */ }; void Demo2_GoColor(struct RGB_CTRL *rgb, int color) { int i; int r, g, b; int sr, sg, sb; r = rgb->red * 255 / 64; g = rgb->green * 255 / 64; b = rgb->blue * 255 / 64; sr = (PRG_RDB(&ctbl[color][0]) - r) / 255; sg = (PRG_RDB(&ctbl[color][1]) - g) / 255; sb = (PRG_RDB(&ctbl[color][2]) - b) / 255; for (i = 1; i < 256; i++) { t_sleep(1); /* 1ms待ち */ r += sr; g += sg; b += sb; RGB_Setup(rgb, r, g, b); } } void Demo2(void) { /* メインループ */ while (1) { int i; for (i = 1; i < 7; i++) { Demo2_GoColor(&led_left, i); Demo2_GoColor(&led_center, i); Demo2_GoColor(&led_right, i); Demo2_GoColor(&led_left, 7); Demo2_GoColor(&led_center, 7); Demo2_GoColor(&led_right, 7); t_sleep(1000); /* 1秒だけ白を維持する */ Demo2_GoColor(&led_right, i); Demo2_GoColor(&led_center, i); Demo2_GoColor(&led_left, i); Demo2_GoColor(&led_right, 7); Demo2_GoColor(&led_center, 7); Demo2_GoColor(&led_left, 7); t_sleep(1000); /* 1秒だけ白を維持する */ } } } /*----------------------------------------------------------------------*/ /* メイン処理 */ /*----------------------------------------------------------------------*/ int main(void) { InitPorts(); /* I/Oポートを初期化 */ InitWorkArea(); /* ワークエリアを初期化 */ InitTMR0(); /* タイマ(TMR0)を初期化 */ sei(); /* 割り込み許可 */ cbi(MCUCR, SM); /* スリープ種別はアイドルモード */ sbi(MCUCR, SE); /* スリープ許可 */ switch (LoadMode()) { case MODE_DEMO1A: /* デモパターン1Aの次はデモパターン1B */ SaveMode(MODE_DEMO1B); Demo1(0); /* デモパターン1Aを実行 */ break; case MODE_DEMO1B: /* デモパターン1Bの次はデモパターン2 */ SaveMode(MODE_DEMO2); Demo1(1); /* デモパターン1Bを実行 */ break; case MODE_DEMO2: /* デモパターン2の次はでもパターン3 */ SaveMode(MODE_DEMO3); Demo2(); /* デモパターン3を実行 */ break; case MODE_DEMO3: /* デモパターン3の次はノーマル */ SaveMode(MODE_NORMAL); while (1) { led_off = FALSE; t_sleep(80); led_off = TRUE; t_sleep(80); } break; default: /* ノーマルの次はデモパターン1A */ SaveMode(MODE_DEMO1A); while (1) { t_sleep(30); } } return 0; }