ctr_mcu/trunk/led.c
N2232 bcefe4d511 ■0.21
いつの間にか使われ方が変わって長手意を表していない変数などを一部名前変更
一部エラーコードで0を返しなどしてた。ERR_SUCCESSなどを返すように修正
ADCのノイズフィルタを改良
ヒステリシス+四捨五入を追加
Volテーブルを更新。最大音量を-10dbに
TWLからの音量設定を無視→反映、スライダの設定と後着優先になるように修正
 Volのポーリング書き込み廃止、CODECリセット時のために強制セットコマンド追加(command.4)
 そのつもりがなかったので修正量が割とあった。
Vol書き込み時、ベリファイ、一度だけリトライするようにした。発生頻度からすれば良かろう。評価中
バッテリー補正パラメータ更新
I2C_mにライトコマンドがきた直後に次の通信が来ると対応出来ずにバスが衝突(ウェイトコンディション理解してくれないから...)してしまっていた。
 結果:一瞬BL消えや突然の電源断
 一時的にスレーブアドレスを変えてNAKを返し、リトライしてもらうことにした。評価中。
電池残量ゼロ時のパターンをとりあえず高速点滅をプリセットにした。
 交換した電池が0や、完全放電などでMCUがリセットされてSoCからパターンをもらってない場合にLEDが青赤とも消灯になりユーザーが心配するため
お知らせLEDのフルカラー化の両対応コードが間違えていてめちゃめちゃになっていたのを修正
お知らせLEDフルカラー判定を誤ることがあった。マージンを増やした。
白箱を実機と誤判定していた。(FPGAの準備がまだ)判定方法を変更
本体設定や無線スイッチでWiFiを切ったときはフェードなしに。すぱっと変化した方がかっこいい
電源OFFにするとき、3DとWiFiはすぱっと消す。電源とお知らせはフェード(以前のまま)
スリープ期間が極短いとSoC.SLP_OのH期間を取り逃す事があった。
 症状:スリープに入ると電源断以外受け付けなくなる
 I2Cで予告してもらう。
歩数計のログポインタ進めるタイミング、秒レジスタ追加。
割り込み禁止区間の調整
電池残量ICとの通信・通信後のケアなど修正
電池残量0での強制電源断復活
.bin,.hexをリポジトリに追加

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@198 013db118-44a6-b54f-8bf7-843cb86687b1
2010-06-30 05:50:16 +00:00

703 lines
17 KiB
C
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/* ========================================================
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 void led_pow_bt_empty();
// ========================================================
// お知らせLEDのパターンデータ
uni_info_LED info_LED;
// 赤LEDの電池残量LEDの点滅パターン
st_led_red_batt_empty led_red_batt_empty = { 0xAA, 0xAA, 0xAA, 0xAA };
// フルカラーとの自動判別のため、一時領域としてもっておく
bit LED_pow_red_Mirror;
bit info_led_off;
bit info_led_override;
bit cam_led_update;
// ========================================================
#define led_fade_to( now, goal ) now = fade_to( now, goal )
/* ========================================================
reg_ledをgoalになるまでグラデーションする
とりあえず、ステップ固定
====================================================== */
u8 fade_to( u8 now, u8 goal )
{
if( now != goal )
{
if( now > goal )
{
now -= 1;
}
else
{
now += 1;
}
}
return( now );
}
// ========================================================
#define led_fade_to2( led, status ) \
led = fade_to2( status )
u8 fade_to2( st_LED_dim_status* status )
{
if( status->now != status->to )
{
if( abs(( status->to - status->now )) > abs(status->delta) )
{
status->now += status->delta;
}
else
{
status->now = status->to;
}
}
return( status->now / 128 );
}
// ========================================================
// ========================================================
void LED_init( )
{
/**
PWMのセット、とりあえず全部消灯
マスタチャネル:0 (P01:/reset2) マスターは偶数チャネルしかできない
スレーブ    1 SLTO。( )
        2 カメラ
         WiFi
         (ピンは32kHz out に使用)
        5 充電
        6 電源
        7 電源
*/
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
// お知らせLEDを識別 //
INFO_LED_IS_FULLCOLOR_PU = 1;
system_status.info_fullcolor = 0;
if( system_status.model == MODEL_TS_BOARD )
{
#ifdef _FORCE_INFO_LED_FULLCOLOR_
// todo debug //
system_status.info_fullcolor = 1;
#endif
}
else
{
if( !INFO_LED_IS_FULLCOLOR_n )
{
system_status.info_fullcolor = 1;
}
}
INFO_LED_IS_FULLCOLOR_PU = 0;
if( system_status.reboot )
{
vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO;
LED_duty_pow_blu = LED_BRIGHT_MAX;
}
info_led_off = 0;
}
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
};
enum LED_ILUM_MODE{
LED_POW_ILM_AUTO,
LED_POW_ILM_ON,
LED_POW_ILM_HOTARU,
LED_POW_ILM_CEOFF
};
======================================================== */
void tsk_led_pow( )
{
info_led_override = 0;
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_HOTARU ):
led_pow_hotaru( );
break;
case ( LED_POW_ILM_ON ):
default:
led_pow_normal( );
break;
case ( LED_POW_ILM_OFF ):
led_fade_to( LED_duty_pow_blu, 0 );
LED_pow_red_Mirror = 0;
break;
case ( LED_POW_ILM_ONLY_RED ):
LED_duty_pow_blu = 0;
LED_pow_red_Mirror = 1;
break;
case ( LED_POW_ILM_ONLY_BLUE ):
LED_duty_pow_blu = LED_BRIGHT_MAX;
LED_pow_red_Mirror = 0;
break;
case ( LED_POW_ILM_FORCE_BT_EMPTY ):
led_pow_bt_empty();
break;
}
// 実際にLEDの更新
if( system_status.info_fullcolor )
{
LED_pow_red = LED_pow_red_Mirror;
}
else
{
LED_old_pow_red = LED_pow_red_Mirror;
}
if( info_led_override )
{
if( system_status.info_fullcolor )
{
LED_duty_notify_blu = 0;
LED_duty_notify_grn = 0;
LED_duty_notify_red = LED_pow_red_Mirror ? 255: 0;
}
else
{
LED_duty_old_NOTIFY = LED_pow_red_Mirror ? 255: 0;
}
}
}
/* ========================================================
電池残量で、 青→赤→赤点滅
======================================================== */
static void led_pow_normal( )
{
if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_EMPTY )
{
led_pow_bt_empty();
}
else if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO )
{
// 赤点灯
led_fade_to( LED_duty_pow_blu, 0 );
LED_pow_red_Mirror = 1;
}
else
{
// 青点灯
led_fade_to( LED_duty_pow_blu, vreg_ctr[VREG_C_LED_BRIGHT] );
LED_pow_red_Mirror = 0;
}
}
static void led_pow_bt_empty()
{
static u8 delay;
static u8 red_blink_poi;
info_led_override = 1;
// 赤点滅
led_fade_to( LED_duty_pow_blu, 0 );
// 赤の点滅パターンも指定できる
delay += 1;
if( delay < 64 ) // フレームの保持時間稼ぎ
{
return;
}
delay = 0;
if( led_red_batt_empty.dats[ red_blink_poi / 8 ] & ( 1 << ( red_blink_poi % 8 )) )
{
LED_pow_red_Mirror = 1;
}
else
{
LED_pow_red_Mirror = 0;
}
red_blink_poi += 1;
if( red_blink_poi >= 32 )
{
red_blink_poi = 0;
}
}
/* ========================================================
ホタルパターン
======================================================== */
static void led_pow_hotaru( )
{
static u8 delay;
static u8 state;
static u16 blue_to;
if( delay != 0 )
{
delay -= 1;
return;
}
delay = 4;
switch ( state )
{
// フェードイン
case ( 0 ):
case ( 2 ):
case ( 4 ):
if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO )
{
blue_to = 0;
LED_pow_red_Mirror = 1;
}
else
{
blue_to = vreg_ctr[VREG_C_LED_BRIGHT];
LED_pow_red_Mirror = 0;
}
break;
default:
// フェードアウト
if( vreg_ctr[VREG_C_BT_REMAIN] <= BATT_TH_LO )
{
LED_pow_red_Mirror = 0;
}
else
{
blue_to = 2;
}
break;
}
// LED更新
if( LED_duty_pow_blu != blue_to )
{
if( LED_duty_pow_blu > blue_to )
{
LED_duty_pow_blu -= 1;
}
else
{
LED_duty_pow_blu += 1;
}
}
if( LED_duty_pow_blu == blue_to )
{
state += 1;
}
return;
}
/* ========================================================
* 割り込みそのものは使いません *
LED_Wifi 3
======================================================== */
void tsk_led_wifi( )
{
static u8 task_interval;
static u8 state_wifi_tx;
static u8 flag_wifi_TX;
if( task_interval-- != 0 )
{
return;
}
// 送信パルスのラッチ
if( WIFI_txLatch ) // 割り込みフラグそのものを使ってしまう
{
WIFI_txLatch = 0;
flag_wifi_TX = 2;
}
if( flag_wifi_TX != 0 )
{
vreg_ctr[ VREG_C_STATUS_1 ] |= REG_BIT_WIFI_TX;
// 送信パターン
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
{
task_interval = 30;
// 送信フラグ待ち
vreg_ctr[ VREG_C_STATUS_1 ] &= ~REG_BIT_WIFI_TX;
if( vreg_ctr[VREG_C_LED_WIFI] == WIFI_LED_OFF )
{
LED_duty_WiFi = 0;
return;
}
else
{
if( LED_duty_WiFi == vreg_ctr[VREG_C_LED_BRIGHT] )
{
return;
}
else if( LED_duty_WiFi < vreg_ctr[VREG_C_LED_BRIGHT] )
{
LED_duty_WiFi += 1;
}
else
{
LED_duty_WiFi -= 1;
}
}
task_interval = 3;
return;
}
}
/* ========================================================
お知らせLED
======================================================== */
void tsk_led_notify( )
{
// static u8 task_interval;
static u8 time_to_next_frame;
static u8 frame;
static u8 loops_to_go;
static st_LED_dim_status LED_dim_status_info_R, LED_dim_status_info_G, LED_dim_status_info_B;
if( info_led_override )
{
// 電池切れが優先する
return;
}
if( system_status.pwr_state == ON_TRIG )
{
LED_duty_notify_blu = 0;
LED_duty_notify_red = 0;
LED_duty_notify_grn = 0;
LED_dim_status_info_R.to = 0;
LED_dim_status_info_G.to = 0;
LED_dim_status_info_B.to = 0;
LED_dim_status_info_R.now = 0;
LED_dim_status_info_G.now = 0;
LED_dim_status_info_B.now = 0;
}
if( !info_led_off )
{
// 次のフレームに進める?
if( time_to_next_frame == 0 )
{
time_to_next_frame = info_LED.info_LED.term;
if( frame >= NOTIFY_LED_TERM -1 )
{
vreg_ctr[ VREG_C_LED_NOTIFY_FLAG ] |= REG_BIT_IN_LOOP;
if( info_LED.info_LED.last_loop != 255 ) // 255:無限ループ
{
if( loops_to_go != 0 )
{
loops_to_go -= 1;
}
else
{
loops_to_go = info_LED.info_LED.last_loop;
frame = 0;
}
}
}
else
{
vreg_ctr[ VREG_C_LED_NOTIFY_FLAG ] &= ~REG_BIT_IN_LOOP;
frame = (( frame + 1 ) & 0x1F ); // ←ここでマスクをかけておかないと最終フレーム~先頭間のグラデが効かない
}
LED_dim_status_info_R.to = info_LED.info_LED.red[frame] * 128;
LED_dim_status_info_G.to = info_LED.info_LED.grn[frame] * 128;
LED_dim_status_info_B.to = info_LED.info_LED.blu[frame] * 128;
// グラデーションのデルタを計算
LED_dim_status_info_R.delta = (( LED_dim_status_info_R.to - LED_dim_status_info_R.now ) ) / info_LED.info_LED.fade_time;
LED_dim_status_info_G.delta = (( LED_dim_status_info_G.to - LED_dim_status_info_G.now ) ) / info_LED.info_LED.fade_time;
LED_dim_status_info_B.delta = (( LED_dim_status_info_B.to - LED_dim_status_info_B.now ) ) / info_LED.info_LED.fade_time;
}
time_to_next_frame -= 1;
}
else
{
// フェードアウトさせる
LED_dim_status_info_R.to = 0;
LED_dim_status_info_G.to = 0;
LED_dim_status_info_B.to = 0;
LED_dim_status_info_R.delta = 0 - LED_dim_status_info_R.now / 64;
LED_dim_status_info_G.delta = 0 - LED_dim_status_info_G.now / 64;
LED_dim_status_info_B.delta = 0 - LED_dim_status_info_B.now / 64;
}
if( system_status.info_fullcolor )
{
led_fade_to2( LED_duty_notify_blu, &LED_dim_status_info_B );
led_fade_to2( LED_duty_notify_red, &LED_dim_status_info_R );
led_fade_to2( LED_duty_notify_grn, &LED_dim_status_info_G );
}
else
{
led_fade_to2( LED_duty_old_NOTIFY, &LED_dim_status_info_B );
}
}
/******************************************************//**
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;
u8 LED_CAM_mirror;
if( !cam_led_update )
{
if( task_interval != 0 )
{
task_interval -= 1;
return;
}
}
cam_led_update = 0; // TWL のブリンク設定(一発だけ点灯)のため
// ブリンクのように待たせたいとき以外は毎週起動する
// (レジスタの変更にすぐに反応する)
switch ( vreg_ctr[VREG_C_LED_CAM] )
{
case ( CAM_LED_OFF ):
default:
LED_CAM_mirror = 0;
state_led_cam = 0;
break;
case ( CAM_LED_ON ):
LED_CAM_mirror = 1;
state_led_cam = 0;
break;
case ( CAM_LED_BLINK ):
if( state_led_cam == 0 )
{
LED_CAM_mirror = 1;
state_led_cam = 1;
}
else
{
LED_CAM_mirror = 0;
state_led_cam = 0;
}
task_interval = 250;
break;
case ( CAM_LED_ON_PLUSE ):
if( state_led_cam == 0 )
{
LED_CAM_mirror = 1;
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_CAM_mirror = 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_CAM_mirror = 0;
state_led_cam = 0;
break;
case( TWL_CAMLED_BLINK ):
if( state_led_cam == 0 )
{
LED_CAM_mirror = 1;
state_led_cam = 1;
}
else
{
LED_CAM_mirror = 0;
state_led_cam = 0;
}
task_interval = 250;
break;
case( TWL_CAMLED_ON ):
case( TWL_CAMLED_DEF_ON ):
default:
LED_CAM_mirror = 1;
state_led_cam = 1;
break;
}
}
// 輝度更新 //
if( system_status.info_fullcolor )
{
LED_CAM = LED_CAM_mirror;
}
else
{
LED_old_CAM = LED_CAM_mirror;
}
}