mirror of
https://github.com/rvtr/ctr_mcu.git
synced 2025-06-18 16:45:33 -04:00

git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@539 013db118-44a6-b54f-8bf7-843cb86687b1
400 lines
10 KiB
C
400 lines
10 KiB
C
/* ========================================================
|
||
LED.c
|
||
|
||
$Id: LED.c 418 2011-09-22 01:35:37Z n2232 $
|
||
======================================================== */
|
||
#ifndef _WIN32
|
||
|
||
#pragma sfr
|
||
|
||
#endif
|
||
|
||
#include "incs.h"
|
||
#include "led.h"
|
||
|
||
|
||
// ========================================================
|
||
static void LED_oshirase_init();
|
||
|
||
|
||
|
||
// ========================================================
|
||
// 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
|
||
|
||
|
||
|
||
// ========================================================
|
||
bit ledInitialized;
|
||
|
||
|
||
// お知らせLED
|
||
uni_info_LED info_LED; // パターンデータ
|
||
bit info_led_off; // 電源off時など、強制消灯フラグ
|
||
bit info_led_override; // 電池残量僅少強制点滅上書きビット
|
||
|
||
// wifi led ステート
|
||
static u8 state_wifi_tx;
|
||
static u8 flag_wifi_TX;
|
||
|
||
|
||
// ========================================================
|
||
#define led_fade_to( now, goal ) now = fade_to( now, goal )
|
||
|
||
|
||
/********************************************//**
|
||
now を goal になるまで inc / dec する。何度も呼ぶとグラデーション
|
||
|
||
とりあえず、ステップ固定
|
||
***********************************************/
|
||
u8 fade_to( u8 now, u8 goal )
|
||
{
|
||
if( now != goal )
|
||
{
|
||
if( now > goal )
|
||
{
|
||
now --;
|
||
}
|
||
else
|
||
{
|
||
now ++;
|
||
}
|
||
}
|
||
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
|
||
{
|
||
// delta が小さいときは to の値にぶつけてしまう
|
||
status->now = status->to;
|
||
}
|
||
}
|
||
return( status->now / 128 );
|
||
}
|
||
|
||
|
||
|
||
|
||
/********************************************//**
|
||
LEDの初期化
|
||
|
||
HWタイマーを使うのでそれらの初期化を行う
|
||
***********************************************/
|
||
void LED_init( )
|
||
{
|
||
/**
|
||
PWMのセット、とりあえず全部消灯
|
||
|
||
マスタチャネル:0 (P01:/reset2) マスターは偶数チャネルしかできない
|
||
スレーブ 1 SLTO。(3D LED?)
|
||
2 カメラ
|
||
3 WiFi
|
||
4 (ピンはRTC32kHz out に使用)
|
||
5 充電
|
||
6 電源 L
|
||
7 電源 H
|
||
*/
|
||
// LED_oshirase_init(); // お知らせパターン初期化
|
||
|
||
/// ペリフェラル初期化 ///
|
||
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 = 0x00FE; // 出力モード。4はPWM出力しないが1にしないとTO5以降にクロックが届かない
|
||
|
||
TOL0 = 0x0000; // 出力を反転させるかフラグ
|
||
|
||
TO0 = 0x0000; // タイマー動作中で、タイマー出力にしてないときのピンのラッチ。タイマー出力を使わないなら0
|
||
TOE0 = 0x00EE; // TOxをタイマーモジュールが制御?
|
||
|
||
TS0 = 0x00EF; // 動作開始
|
||
|
||
TDR00 = LED_BRIGHT_MAX - 1; // 周期 10bit
|
||
|
||
// アップデートなどでマイコンのみリブートしたとき
|
||
if( system_status.reboot )
|
||
{
|
||
// SoC からのコマンドを待たず、自動で電源 LED をつける
|
||
vreg_ctr[VREG_C_LED_POW] = LED_POW_ILM_AUTO;
|
||
LED_duty_pow_blu = LED_BRIGHT_MAX;
|
||
}
|
||
info_led_off = false; // 強制消灯 解除
|
||
ledInitialized = true;
|
||
}
|
||
|
||
|
||
static void LED_oshirase_init()
|
||
{
|
||
char* p_tgt = &info_LED;
|
||
int i;
|
||
|
||
for( i = 0; i < sizeof(info_LED); i++ )
|
||
{
|
||
*p_tgt = 0;
|
||
p_tgt++;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
|
||
/********************************************//**
|
||
LEDの停止。
|
||
|
||
HWタイマーの停止
|
||
***********************************************/
|
||
|
||
void LED_stop( )
|
||
{
|
||
TT0 = 0x00EF; // 一斉停止(しないとだめ)
|
||
TOE0 = 0x0000; // TOxをタイマーモジュールが制御?(GPIOになる)
|
||
TAU0EN = 0;
|
||
LED_pow_red = 0;
|
||
LED_CAM = 0;
|
||
|
||
LED_duty_notify_red = 0;
|
||
LED_duty_notify_blu = 0;
|
||
LED_duty_notify_grn = 0;
|
||
LED_pow_red = 0;
|
||
LED_CAM = 0;
|
||
|
||
WIFI_txLatch = 0;
|
||
flag_wifi_TX = 0;
|
||
state_wifi_tx = 0;
|
||
|
||
ledInitialized = false;
|
||
}
|
||
|
||
|
||
|
||
|
||
/********************************************//**
|
||
WiFi LED の更新
|
||
|
||
- レジスタの設定で on / off
|
||
- off であってもモジュールからの送信パルスで -_-_-_--------_-_-_-------のパターン点滅
|
||
***********************************************/
|
||
void tsk_led_wifi( )
|
||
{
|
||
static u8 task_interval;
|
||
|
||
if( task_interval-- != 0 )
|
||
{
|
||
return;
|
||
}
|
||
|
||
// 送信パルスのラッチ
|
||
if( WIFI_txLatch ) // 割り込みフラグそのものを使ってしまう
|
||
{
|
||
WIFI_txLatch = 0;
|
||
flag_wifi_TX = 1;
|
||
}
|
||
|
||
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 = 0;
|
||
}
|
||
task_interval = 25;
|
||
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 ++;
|
||
}
|
||
else
|
||
{
|
||
LED_duty_WiFi --;
|
||
}
|
||
}
|
||
task_interval = 3;
|
||
return;
|
||
}
|
||
}
|
||
|
||
|
||
|
||
|
||
bit info_led_pattern_updated;
|
||
/********************************************//**
|
||
お知らせLED
|
||
|
||
フェードアウト計算
|
||
***********************************************/
|
||
static void calc_info_led_fade_out( st_LED_dim_status* tgt_led )
|
||
{
|
||
tgt_led -> to = 0;
|
||
tgt_led -> delta = ( 0 - tgt_led -> now ) / 64;
|
||
// フェードアウト限定(ゼロに向かっていく。符号の向きを想定してしまう。)
|
||
if(( tgt_led -> now != 0 ) && ( tgt_led -> delta == 0 ))
|
||
{
|
||
tgt_led -> delta = (sx16)-1;
|
||
}
|
||
}
|
||
|
||
|
||
/********************************************//**
|
||
お知らせLED
|
||
|
||
グラデーション計算
|
||
***********************************************/
|
||
static void calc_info_led_next_frame( st_LED_dim_status* tgt_led, u8 color )
|
||
{
|
||
tgt_led -> to = color * 128;
|
||
// グラデーションのデルタを計算
|
||
tgt_led -> delta = (( tgt_led -> to - tgt_led -> now ) ) / info_LED.info_LED.fade_time;
|
||
}
|
||
|
||
|
||
/********************************************//**
|
||
お知らせLED
|
||
***********************************************/
|
||
void tsk_led_notify( )
|
||
{
|
||
static u8 time_to_next_frame;
|
||
static u8 frame;
|
||
static u8 loops;
|
||
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.now = 0;
|
||
LED_dim_status_info_G.now = 0;
|
||
LED_dim_status_info_B.now = 0;
|
||
}
|
||
|
||
if( info_led_off ) // ←電源off時など強制off
|
||
{
|
||
// フェードアウトさせる
|
||
calc_info_led_fade_out( &LED_dim_status_info_R );
|
||
calc_info_led_fade_out( &LED_dim_status_info_G );
|
||
calc_info_led_fade_out( &LED_dim_status_info_B );
|
||
}
|
||
else
|
||
{
|
||
// 通常運転
|
||
if( info_led_pattern_updated )
|
||
{
|
||
info_led_pattern_updated = false;
|
||
vreg_ctr[ VREG_C_LED_NOTIFY_FLAG ] &= ~REG_BIT_IN_LOOP;
|
||
frame = 0; // ちゃんと書こう
|
||
time_to_next_frame = 0;
|
||
}
|
||
else
|
||
{
|
||
// 次のフレームに進める?
|
||
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:無限ループ
|
||
{
|
||
loops ++;
|
||
if( loops > info_LED.info_LED.last_loop )
|
||
{
|
||
frame = 0;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
frame = (( frame + 1 ) & 0x1F ); // ←ここでマスクをかけておかないと最終フレーム~先頭間のグラデが効かない
|
||
vreg_ctr[ VREG_C_LED_NOTIFY_FLAG ] &= ~REG_BIT_IN_LOOP;
|
||
loops = 0;
|
||
}
|
||
|
||
// グラデーション計算
|
||
calc_info_led_next_frame( &LED_dim_status_info_R, info_LED.info_LED.red[frame] );
|
||
calc_info_led_next_frame( &LED_dim_status_info_G, info_LED.info_LED.grn[frame] );
|
||
calc_info_led_next_frame( &LED_dim_status_info_B, info_LED.info_LED.blu[frame] );
|
||
|
||
}
|
||
time_to_next_frame --;
|
||
}
|
||
}
|
||
|
||
led_fade_to2( LED_duty_notify_red, &LED_dim_status_info_R );
|
||
led_fade_to2( LED_duty_notify_grn, &LED_dim_status_info_G );
|
||
led_fade_to2( LED_duty_notify_blu, &LED_dim_status_info_B );
|
||
}
|