ctr_mcu/snake_trunk/led.c
n2232 519bd8a323 2.31。IS_CAPTURE 対応
git-svn-id: file:///Volumes/Transfer/gigaleak_20231201/2020-05-23%20-%20ctr.7z%20+%20svn_v1.068.zip/ctr/svn/ctr_mcu@561 013db118-44a6-b54f-8bf7-843cb86687b1
2013-09-09 06:40:21 +00:00

400 lines
10 KiB
C
Raw Permalink 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
$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。( )
        2 カメラ
         WiFi
         (ピンは32kHz out に使用)
        5 充電
        6 電源
        7 電源
*/
// 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 );
}