mirror of
https://github.com/rvtr/ctr_mcu.git
synced 2025-06-18 16:45:33 -04:00
619 lines
15 KiB
C
619 lines
15 KiB
C
/* ========================================================
|
||
LED.c
|
||
|
||
======================================================== */
|
||
#pragma sfr
|
||
|
||
|
||
#include "incs.h"
|
||
#include "led.h"
|
||
|
||
|
||
|
||
// ========================================================
|
||
// TPS0
|
||
#define BIT_PRS012 ( 1 << 2 )
|
||
#define BIT_PRS002 ( 1 << 6 )
|
||
|
||
// TMR0
|
||
#define BIT_CKS0 15
|
||
#define BIT_CCS0 12
|
||
#define BIT_MASTER0 11
|
||
#define BIT_STS0 8
|
||
#define BIT_CIS0 6
|
||
#define BIT_MD123 1
|
||
#define BIT_MD0 0
|
||
|
||
// ========================================================
|
||
static void led_pow_normal( );
|
||
static void led_pow_hotaru( );
|
||
|
||
|
||
|
||
// ========================================================
|
||
static const char MSG_MAIL[] = { 0b11110110, 0b11011010, 0b01101110, 0b10010100 };
|
||
#define MSG_SPD 60
|
||
// ↑255/3以下であること!
|
||
|
||
// ========================================================
|
||
void LED_init( )
|
||
{
|
||
/**
|
||
PWMのセット、とりあえず全部消灯
|
||
|
||
マスタチャネル:0 (P01:/reset2) マスターは偶数チャネルしかできない
|
||
スレーブ 1 SLTO。(3D LED?)
|
||
2 カメラ
|
||
3 WiFi
|
||
4 (ピンはRTC32kHz out に使用)
|
||
5 充電
|
||
6 電源 L
|
||
7 電源 H
|
||
*/
|
||
TAU0EN = 1;
|
||
TPS0 = BIT_PRS012 | BIT_PRS002; // マスタークロックはCK01,8M/2 /2^4 = 250kHz
|
||
|
||
TMR00 =
|
||
1 << BIT_CKS0 | 0 << BIT_CCS0 | 1 << BIT_MASTER0 | 0 << BIT_STS0 | 0
|
||
<< BIT_CIS0 | 0 << BIT_MD123 | 1 << BIT_MD0;
|
||
TMR01 = TMR02 = TMR03 = TMR04 = TMR05 = TMR06 = TMR07 =
|
||
1 << BIT_CKS0 | 0 << BIT_CCS0 | 0 << BIT_MASTER0 | 4 << BIT_STS0 | 0
|
||
<< BIT_CIS0 | 4 << BIT_MD123 | 1 << BIT_MD0;
|
||
ISC = 0;
|
||
TOM0 = 0b0000000011111110; // 出力モード。4はPWM出力しないが1にしないとTO5以降にクロックが届かない
|
||
|
||
#ifdef _MCU_BSR_
|
||
TOL0 = 0b0000000000000000; // 出力を反転させるかフラグ
|
||
#else
|
||
TOL0 = 0b0000000000000100; // 出力を反転させるかフラグ
|
||
#endif
|
||
|
||
TO0 = 0; // タイマー動作中で、タイマー出力にしてないときのピンのラッチ。タイマー出力を使わないなら0
|
||
TOE0 = 0b0000000011101110; // TOxをタイマーモジュールが制御?
|
||
TS0 = 0b0000000011101111; // 動作開始
|
||
|
||
TDR00 = LED_BRIGHT_MAX - 1; // 10bit, 周期
|
||
|
||
if( system_status.reboot )
|
||
{
|
||
vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO;
|
||
LED_duty_pow_H = LED_BRIGHT_MAX;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
void LED_stop( )
|
||
{
|
||
TT0 = 0b0000000011101111; // 一斉停止(しないとだめ)
|
||
TOE0 = 0b0000000000000000; // TOxをタイマーモジュールが制御?(GPIOになる)
|
||
TAU0EN = 0;
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
// 電源LED
|
||
LED_POW_B,R 6,7
|
||
|
||
TDR00 周期(0x03FF。TPS0で250kHzでカウントアップ。10bitなら250Hz位になる)
|
||
TDR0x Duty 0で消灯、TDR00(より大 =0x03FF以上)で点灯です。
|
||
|
||
enum pwr_state_{
|
||
OFF_TRIG = 0,
|
||
OFF,
|
||
ON_TRIG,
|
||
ON,
|
||
SLEEP_TRIG,
|
||
SLEEP
|
||
};
|
||
|
||
enum LED_ILUM_MODE{
|
||
LED_POW_ILM_AUTO,
|
||
LED_POW_ILM_ON,
|
||
LED_POW_ILM_HOTARU,
|
||
LED_POW_ILM_CEOFF
|
||
};
|
||
======================================================== */
|
||
void tsk_led_pow( )
|
||
{
|
||
switch ( vreg_ctr[VREG_C_LED_POW] )
|
||
{
|
||
// 自動切り替え
|
||
case ( LED_POW_ILM_AUTO ):
|
||
switch ( system_status.pwr_state )
|
||
{
|
||
case SLEEP:
|
||
led_pow_hotaru( );
|
||
break;
|
||
|
||
case ON:
|
||
led_pow_normal( );
|
||
break;
|
||
|
||
default:
|
||
break;
|
||
}
|
||
break;
|
||
|
||
// 強制
|
||
case ( LED_POW_ILM_OFF ):
|
||
LED_duty_pow_H -= ( LED_duty_pow_H == 0x0000 ) ? 0 : 1;
|
||
LED_duty_pow_L -= ( LED_duty_pow_L == 0x0000 ) ? 0 : 1;
|
||
break;
|
||
|
||
case ( LED_POW_ILM_HOTARU ):
|
||
led_pow_hotaru( );
|
||
break;
|
||
|
||
case ( LED_POW_ILM_ON ):
|
||
default:
|
||
led_pow_normal( );
|
||
break;
|
||
|
||
case ( LED_POW_ILM_ONLY_RED ):
|
||
LED_duty_pow_H = 0x0000;
|
||
LED_duty_pow_L = LED_BRIGHT_MAX;
|
||
break;
|
||
|
||
case ( LED_POW_ILM_ONLY_BLUE ):
|
||
LED_duty_pow_H = LED_BRIGHT_MAX;
|
||
LED_duty_pow_L = 0x0000;
|
||
break;
|
||
}
|
||
|
||
}
|
||
|
||
|
||
|
||
/* ========================================================
|
||
電池残量で、 青→赤→赤点滅
|
||
======================================================== */
|
||
static void led_pow_normal( )
|
||
{
|
||
static u8 state;
|
||
|
||
if( vreg_ctr[VREG_C_BT_REMAIN] < 3 )
|
||
{
|
||
// 赤点滅
|
||
state++;
|
||
if( state < 127 )
|
||
{
|
||
LED_duty_pow_H = 0x0000;
|
||
LED_duty_pow_L = 0x0000;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_pow_L = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
}
|
||
return;
|
||
|
||
}
|
||
else if( vreg_ctr[VREG_C_BT_REMAIN] < 12 )
|
||
{
|
||
// 赤点灯
|
||
if( LED_duty_pow_H != 0x0000 )
|
||
{ // 青フェードアウト
|
||
LED_duty_pow_H -= 1;
|
||
}
|
||
if( LED_duty_pow_L != vreg_ctr[VREG_C_LED_BRIGHT] )
|
||
{ // 赤フェードイン
|
||
LED_duty_pow_L += ( LED_duty_pow_L < vreg_ctr[VREG_C_LED_BRIGHT] ) ? 1 : -1;
|
||
}
|
||
return;
|
||
|
||
}
|
||
else
|
||
{
|
||
// 青点灯
|
||
if( LED_duty_pow_H != vreg_ctr[VREG_C_LED_BRIGHT] )
|
||
{
|
||
LED_duty_pow_H += ( LED_duty_pow_H < vreg_ctr[VREG_C_LED_BRIGHT] ) ? 1 : -1;
|
||
}
|
||
if( LED_duty_pow_L != 0x0000 )
|
||
{
|
||
LED_duty_pow_L -= 1;
|
||
}
|
||
}
|
||
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
/* ========================================================
|
||
ホタルパターン
|
||
======================================================== */
|
||
static void led_pow_hotaru( )
|
||
{
|
||
static u8 delay;
|
||
static u8 state;
|
||
static u16 blue_to;
|
||
static u16 red_to;
|
||
|
||
if( delay != 0 )
|
||
{
|
||
delay -= 1;
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
delay = 10;
|
||
}
|
||
|
||
if( LED_duty_pow_L != red_to )
|
||
{
|
||
if( LED_duty_pow_L > red_to )
|
||
{
|
||
LED_duty_pow_L -= 1;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_pow_L += 2;
|
||
}
|
||
}
|
||
|
||
if( LED_duty_pow_H != blue_to )
|
||
{
|
||
if( LED_duty_pow_H > blue_to )
|
||
{
|
||
LED_duty_pow_H -= 1;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_pow_H += 2;
|
||
}
|
||
}
|
||
|
||
switch ( state )
|
||
{
|
||
// フェードイン
|
||
case ( 0 ):
|
||
case ( 2 ):
|
||
case ( 4 ):
|
||
if( vreg_ctr[VREG_C_BT_REMAIN] < 12 )
|
||
{
|
||
// 赤いとき
|
||
blue_to = 0;
|
||
red_to = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
}
|
||
else
|
||
{
|
||
blue_to = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
red_to = 0;
|
||
}
|
||
break;
|
||
|
||
default:
|
||
// フェードアウト
|
||
if( vreg_ctr[VREG_C_BT_REMAIN] < 12 )
|
||
{
|
||
red_to = 2;
|
||
}
|
||
else
|
||
{
|
||
blue_to = 2;
|
||
}
|
||
break;
|
||
}
|
||
|
||
if( ( LED_duty_pow_H == blue_to ) && ( LED_duty_pow_L == red_to ) )
|
||
{
|
||
state += 1;
|
||
}
|
||
return;
|
||
}
|
||
|
||
|
||
|
||
/* ========================================================
|
||
* 割り込みそのものは使いません *
|
||
LED_Wifi 3
|
||
todo 直書きの点滅間隔など
|
||
======================================================== */
|
||
void tsk_led_wifi( )
|
||
{
|
||
static u8 task_interval;
|
||
static u8 remain_wifi_tx;
|
||
static u8 state_wifi_tx;
|
||
static u8 flag_wifi_TX;
|
||
|
||
|
||
if( task_interval-- != 0 )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 送信パルスのラッチ
|
||
if( vreg_ctr[VREG_C_LED_WIFI] == WIFI_LED_TXAUTO )
|
||
{
|
||
if( WIFI_txLatch )
|
||
{
|
||
WIFI_txLatch = 0;
|
||
flag_wifi_TX = 2;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
flag_wifi_TX = 0;
|
||
}
|
||
|
||
|
||
switch ( vreg_ctr[VREG_C_LED_WIFI] )
|
||
{
|
||
case ( WIFI_LED_OFF ):
|
||
default:
|
||
LED_duty_WiFi = 0;
|
||
state_wifi_tx = 0;
|
||
remain_wifi_tx = 0;
|
||
break;
|
||
|
||
case ( WIFI_LED_ON ):
|
||
LED_duty_WiFi = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_wifi_tx = 0;
|
||
remain_wifi_tx = 0;
|
||
break;
|
||
|
||
case ( WIFI_LED_TXAUTO ):
|
||
if( flag_wifi_TX != 0 ) // 短いパルスを捕まえるために、割り込みフラグを見る
|
||
{
|
||
// 送信パターン
|
||
switch ( state_wifi_tx )
|
||
{
|
||
case ( 1 ):
|
||
case ( 3 ):
|
||
case ( 5 ):
|
||
LED_duty_WiFi = 0;
|
||
break;
|
||
default:
|
||
LED_duty_WiFi = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
}
|
||
state_wifi_tx++;
|
||
if( state_wifi_tx == 32 )
|
||
{
|
||
state_wifi_tx = 0;
|
||
flag_wifi_TX -= 1;
|
||
}
|
||
task_interval = 22;
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
// 送信フラグ待ち
|
||
LED_duty_WiFi = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
task_interval = 200;
|
||
return;
|
||
}
|
||
break;
|
||
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/* ========================================================
|
||
* 割り込みそのものは使いません *
|
||
LED_Wifi2 P24 (未)
|
||
======================================================== */
|
||
void tsk_led_notify( )
|
||
{
|
||
static u8 task_interval;
|
||
static u8 flg_char_space;
|
||
static u8 state_notify_led; // 点灯パターンの進行具合
|
||
static u8 flag_wifi_TX;
|
||
|
||
|
||
if( task_interval-- != 0 )
|
||
{
|
||
return;
|
||
}
|
||
|
||
switch ( vreg_ctr[VREG_C_LED_NOTIFY] )
|
||
{
|
||
case ( NOTIFY_LED_OFF ):
|
||
default:
|
||
LED_duty_NOTIFY = 0;
|
||
state_notify_led = 0;
|
||
flg_char_space = 0;
|
||
break;
|
||
|
||
case ( NOTIFY_LED_ON ):
|
||
LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_notify_led = 0;
|
||
flg_char_space = 0;
|
||
break;
|
||
|
||
case ( NOTIFY_LED_PTN0 ):
|
||
// ゆっくりバースト
|
||
switch ( state_notify_led )
|
||
{
|
||
case ( 1 ):
|
||
case ( 3 ):
|
||
case ( 5 ):
|
||
LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
break;
|
||
default:
|
||
LED_duty_NOTIFY = 0;
|
||
}
|
||
state_notify_led++;
|
||
if( state_notify_led == 16 )
|
||
{
|
||
state_notify_led = 0;
|
||
}
|
||
task_interval = 50;
|
||
return;
|
||
|
||
case ( NOTIFY_LED_PTN1 ):
|
||
// データテーブルに従って点滅
|
||
{
|
||
u8 dat;
|
||
|
||
task_interval = MSG_SPD; // 共通のため。場合によって上書き
|
||
|
||
if( flg_char_space != 0 )
|
||
{
|
||
LED_duty_NOTIFY = 0;
|
||
flg_char_space = 0;
|
||
return;
|
||
}
|
||
|
||
// データバッファの見る位置の更新
|
||
dat = ( MSG_MAIL[state_notify_led / 4] << ( ( state_notify_led % 4 ) * 2 ) ) & 0xC0;
|
||
if( dat == 0 )
|
||
{
|
||
state_notify_led = 0;
|
||
}
|
||
else
|
||
{
|
||
state_notify_led += 1;
|
||
}
|
||
|
||
flg_char_space = 1;
|
||
if(( dat & 0b10000000 ) != 0 )
|
||
{
|
||
// 点灯はさせる
|
||
LED_duty_NOTIFY = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
if(( dat & 0b01000000 ) == 0 )
|
||
{
|
||
// 短
|
||
// nothing to do
|
||
}
|
||
else
|
||
{
|
||
// 長
|
||
task_interval = ( MSG_SPD * 3 );
|
||
}
|
||
// 次は単語間休み、とかの判定をさせたかったが
|
||
/// 1バイトに2ビットずつデータが並んでおり、次のバイトに
|
||
/// またがるようなときが面倒なのでやめる
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
if(( dat & 0b01000000 ) == 0 )
|
||
{
|
||
// 一文終了
|
||
task_interval = ( MSG_SPD * 3 );
|
||
}
|
||
else
|
||
{
|
||
// 単語間
|
||
// nothing to do
|
||
}
|
||
return;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
/******************************************************//**
|
||
LED_Cam TO02
|
||
\n BLINK,*_PLUSE の時は、1周期分は必ずその状態になります。
|
||
\n その間に OFF→BLINK などされると、OFFが無視されます。
|
||
*********************************************************/
|
||
void tsk_led_cam( )
|
||
{
|
||
static u8 state_led_cam = 0;
|
||
static u8 task_interval;
|
||
static u8 state_led_cam_twl;
|
||
|
||
if( task_interval != 0 )
|
||
{
|
||
task_interval -= 1;
|
||
return;
|
||
}
|
||
|
||
// ブリンクのように待たせたいとき以外は毎週起動する
|
||
// (レジスタの変更にすぐに反応する)
|
||
|
||
switch ( vreg_ctr[VREG_C_LED_CAM] )
|
||
{
|
||
case ( CAM_LED_OFF ):
|
||
default:
|
||
LED_duty_CAM = 0;
|
||
state_led_cam = 0;
|
||
break;
|
||
|
||
case ( CAM_LED_ON ):
|
||
LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_led_cam = 0;
|
||
break;
|
||
|
||
case ( CAM_LED_BLINK ):
|
||
if( state_led_cam == 0 )
|
||
{
|
||
LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_led_cam = 1;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_CAM = 0;
|
||
state_led_cam = 0;
|
||
}
|
||
task_interval = 250;
|
||
break;
|
||
|
||
case ( CAM_LED_ON_PLUSE ):
|
||
if( state_led_cam == 0 )
|
||
{
|
||
LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_led_cam = 1;
|
||
task_interval = 250;
|
||
}
|
||
else
|
||
{
|
||
vreg_ctr[VREG_C_LED_CAM] = CAM_LED_OFF;
|
||
}
|
||
break;
|
||
|
||
case ( CAM_LED_OFF_PLUSE ):
|
||
if( state_led_cam == 0 )
|
||
{
|
||
LED_duty_CAM = 0;
|
||
state_led_cam = 1;
|
||
task_interval = 250;
|
||
}
|
||
else
|
||
{
|
||
vreg_ctr[VREG_C_LED_CAM] = CAM_LED_ON;
|
||
}
|
||
break;
|
||
|
||
case ( CAM_LED_BY_TWL ):
|
||
switch ( vreg_twl[ REG_TWL_INT_ADRS_CAM ] ){ // switchのネストとか…
|
||
case( TWL_CAMLED_OFF ):
|
||
LED_duty_CAM = 0;
|
||
state_led_cam = 0;
|
||
break;
|
||
|
||
case( TWL_CAMLED_BLINK ):
|
||
if( state_led_cam == 0 )
|
||
{
|
||
LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_led_cam = 1;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_CAM = 0;
|
||
state_led_cam = 0;
|
||
}
|
||
task_interval = 250;
|
||
break;
|
||
|
||
case( TWL_CAMLED_ON ):
|
||
case( TWL_CAMLED_DEF_ON ):
|
||
default:
|
||
LED_duty_CAM = vreg_ctr[VREG_C_LED_BRIGHT];
|
||
state_led_cam = 1;
|
||
break;
|
||
}
|
||
}
|
||
return;
|
||
}
|
||
|