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

This commit is contained in:
fujita_ryohei 2009-07-06 06:27:40 +00:00
parent 96796eccec
commit 938ea96c94
18 changed files with 3347 additions and 0 deletions

8
trunk/WDT.c Normal file
View File

@ -0,0 +1,8 @@
#pragma sfr
#include "incs_loader.h"
void WDT_Restart( void ){
WDTE = 0xAC; // restart watch dog timer
}

133
trunk/accero.c Normal file
View File

@ -0,0 +1,133 @@
/*****************************************************************************
 加速度センサ関係
・データ更新完了でデータを吸い上げ手レジスタを更新、CPUに割り込み
・フラグが立っていれば歩数カウント
・加速度センサ割り込みからタスクを登録して下さい。(I2Cの競合回避などがあるので)
*****************************************************************************/
#pragma SFR
#pragma NOP
#pragma HALT
#pragma STOP
#include "incs.h"
// レジスタ名
#define ACC_REG_WHOAMI 0x0F
#define ACC_REG_CTRL1 0x20
#define ACC_REG_CTRL5 0x24
#define ACC_REG_X 0x28
// ビット位置
#define ACC_bP_PM0 5
#define ACC_bP_DR0 3
// ビット設定値
#define ACC_BITS_PM_PDN 0
#define ACC_BITS_PM_NORM 1
#define ACC_BITS_PM_LP0R5 2
#define ACC_BITS_PM_LP1 3
#define ACC_BITS_PM_LP2 4
#define ACC_BITS_PM_LP5 5
#define ACC_BITS_PM_LP10 6
#define ACC_BITS_DR_50Hz 0
#define ACC_BITS_DR_100Hz 1
#define ACC_BITS_DR_400Hz 2
#define ACC_BITS_DR_1000Hz 3
#define ACC_BITS_ALL_AXIS_ON 7
//*************************************
u8 hosu_mode = 0;
/*
0: power down 停止
1: 動作
*/
/*****************************************************************************
 ・割り込みを確認してデータを吸い上げ、レジスタに書き出します
・本当であればコールバック関数を登録しておけばいいじゃんとなるのですが、
I2Cが使用中だったら?とか考えると私ではそこまでできないのです。
・自動歩数計とかでも結局
*****************************************************************************/
task_status_immed tsk_cbk_accero(){
static u8 sequence;
u8* dest_adrs;
if( system_status.pwr_state == ON ){
// if( 自動歩数計? )
// todo
sequence += 1;
vreg_ctr[VREG_C_ACC_0SEQ + 7 * ( sequence & 0x03 )] = sequence;
dest_adrs = &vreg_ctr[VREG_C_ACC_0XH] + 7 * ( sequence & 0x03 );
iic_mcu_read( IIC_SLA_ACCEL, ( ACC_REG_X | 0x80 ), 6, dest_adrs );
#if 0
switch( system_status.pwr_state ){
case OFF:
case ON_TRIG:
case ON:
case SLEEP_TRIG:
case SLEEP:
case OFF_TRIG:
default:
break;
}
#endif
}
return( ERR_SUCCESS );
}
/*****************************************************************************
 自動歩数カウントモードにセット
todo 他のモードだったら止めたり、復帰させたり
割り込みルーチンなどでカウント判定が必要
*****************************************************************************/
err accero_hosu_start(){
u8 temp;
u8 err;
u8 str_send_buf[4];
if( system_status.pwr_state == ON ){
err = iic_mcu_read( IIC_SLA_ACCEL, ACC_REG_WHOAMI, 1, &temp );
if( err == ERR_NAK ){
vreg_ctr[ VREG_C_ACC_STATUS ] |= 0x80;
return( ERR_ERR );
}
str_send_buf[0] = ( ACC_BITS_PM_NORM << ACC_bP_PM0 | ACC_BITS_DR_100Hz << ACC_bP_DR0 | ACC_BITS_ALL_AXIS_ON ); // cont1
str_send_buf[1] = 0x00; // 泣ける...
str_send_buf[2] = 0x02;
str_send_buf[3] = 0x80;
err = iic_mcu_write( IIC_SLA_ACCEL, ( ACC_REG_CTRL1 | 0x80 ), 4, str_send_buf );
// str_send_buf[0] = 0x00;
// err |= iic_mcu_write( IIC_SLA_ACCEL, ACC_REG_CTRL5, 1, str_send_buf );
return( err );
}
}
err accero_hosu_stop(){
u8 err;
u8 str_send_buf[4];
str_send_buf[0] = ( ACC_BITS_PM_PDN << ACC_bP_PM0 | 0 << ACC_bP_DR0 | ACC_BITS_ALL_AXIS_ON );
str_send_buf[1] = 0x00; // 泣ける...
str_send_buf[2] = 0x02;
str_send_buf[3] = 0x80;
err = iic_mcu_write( IIC_SLA_ACCEL, ( ACC_REG_CTRL1 | 0x80 ) , 4, str_send_buf );
return( err );
}

105
trunk/adc.c Normal file
View File

@ -0,0 +1,105 @@
/******************************************************************************
対PMIC_TWL2 I2C通信
de JHL 藤田@開技
nintendo
'09 Apr
*******************************************************************************/
#include "incs_loader.h"
#include "adc.h"
#include "pm.h"
/******************************************************************************
ADC設定と、開始
以下のピンは主にここで操作・監視されます。
・BT_TEMP,_P
・ADIN1
・VOL
関係ありそうですが別のところで管理しています
・PM_BT_DET,_P PM_init
******************************************************************************/
task_status tsk_adc(){
if(( system_status.pwr_state == ON )
|| ( system_status.pwr_state == SLEEP )){
ADCEN = 1;
ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから
ADPC = 0x07; // ADCポートのセレクト
ADS = ADC_SEL_3D;
ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける
ADIF = 0;
ADMK = 0;
return( 8 );
}
}
/******************************************************************************
 自前で次のチャンネル
  一通り終わったら止める
*******************************************************************************/
__interrupt void int_adc(){
switch( ADS ){
case( ADC_SEL_3D ):
vreg_ctr[ VREG_C_3D_DEPTH ] = ADCRH;
break;
case( ADC_SEL_VOL ):
vreg_ctr[ VREG_C_VOL ] = ADCRH;
// todo: テーブル引きなど
break;
case( ADC_SEL_BATT_TEMP ):
raw_adc_temperature = ADCR;
break;
case( ADC_SEL_BATT_DET ):
// vreg_ctr[ VREG_C_DBG_BATT_DET ] = ADCRH;
break;
}
// if( ADS == ADC_SEL_BATT_DET ){
// もっとまともな書き方がありそうだ
if( ADS == ADC_SEL_BATT_TEMP ){ // 電池判別は電源投入の一回で良いよね
ADCEN = 0; // いっそのこと、止めてしまう
}else{
ADS += 1; // 次のチャンネル
}
}
/******************************************************************************
tsk_adcと競合することを考慮していません。
*******************************************************************************/
u16 get_adc( u8 ch ){
u16 temp;
ADMK = 1;
ADIF = 0;
ADCEN = 1;
ADM = 0b00011011; // セレクトモード、章圧、fCLK/6 ///ここから
ADPC = 0x07; // ADCポートのセレクト
ADS = ch;
ADCS = 1; // AD開始。 /// ここまでに、1us以上開ける
ADMK = 0;
while( ADIF == 0 ){;}
temp = ADCR;
ADCEN = 0;
return( temp );
}

230
trunk/i2c_ctr.c Normal file
View File

@ -0,0 +1,230 @@
/******************************************************************************
対SoC 新規チャンネル I2C通信
de JHL 藤田@開技.nintendo
'09 Apr
*******************************************************************************/
#include "incs_loader.h"
u8 vreg_adrs;
u8 pre_dat;
u16 tot;
/*****************************************************************************
*****************************************************************************/
enum{
IIC_IDLE = 0,
IIC_RCV_REG_ADRS,
IIC_TX_OR_RX,
IIC_TX,
IIC_RX
};
#if 0
// 1バイト送受の度に割り込みが発生するバージョン
__interrupt void int_iica(){
static u8 state = 0;
static u8 reg_adrs;
static u8 reg_adrs_internal;
static u8 temp;
if( SPD ){
state = IIC_IDLE;
SPIE = 0;
return;
}
if( ACKD == 0 ){
LREL = 1;
state = IIC_IDLE;
return;
}
DBG_P_n = 1;
switch( state ){
case( IIC_IDLE ):
// 自局呼び出しに応答。
// 初期化など
WREL = 1; // ウェイト解除
SPIE = 1;
state = IIC_RCV_REG_ADRS;
break;
case( IIC_RCV_REG_ADRS ):
// レジスタアドレス受信
reg_adrs = IICA & 0x1F;
WREL = 1;
reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs );
temp = vreg_ctr_read( reg_adrs_internal );
// temp = vreg_ctr[ reg_adrs ];
state = IIC_TX_OR_RX;
break;
case( IIC_TX_OR_RX ):
if( STD ){
// リードされる
if( !COI ){
// リスタートで違うデバイスが呼ばれた!
WREL = 1; // ウェイト解除?
state = IIC_IDLE; // 終了処理
SPIE = 0;
}else{
state = IIC_TX;
}
}else{
state = IIC_RX;
}
// no break;
default:
if( state == IIC_TX ){
IICA = temp;
}else{
temp = IICA;
WREL = 1;
vreg_ctr_write( reg_adrs_internal, temp );
// vreg_ctr[ reg_adrs ] = temp;
}
reg_adrs = ( reg_adrs + 1 ) & 0x1F;
reg_adrs_internal = adrs_table_ctr_ext2int( reg_adrs );
if( state == IIC_TX ){
temp = vreg_ctr_read( reg_adrs_internal );
// temp = vreg_ctr[ reg_adrs ];
}
break;
}
DBG_P_n = 0;
}
#endif
//#if 0
//一度通信が始まったら終わるまで戻らないバージョン
__interrupt void int_iica(){
static u8 state = 0;
static u8 reg_adrs;
static u8 reg_adrs_internal;
static u8 trx_buf;
DBG_P_n = 1;
// 自局呼び出しに応答。
// 初期化など
WREL = 1; // ウェイト解除
DBG_P_n = 0;
while( !IICAIF ){;}
IICAIF = 0;
DBG_P_n = 1;
// レジスタアドレス受信
reg_adrs = IICA;
WREL = 1;
trx_buf = vreg_ctr_read( reg_adrs ); // データの準備をしておく
DBG_P_n = 0;
while( !IICAIF ){;}
IICAIF = 0;
if( STD ){ // リスタートコンディション
// リードされる
if( !COI ){
// リスタートで違うデバイスが呼ばれた!
WREL = 1; // ウェイト解除?
state = IIC_IDLE; // 終了処理
SPIE = 0;
return;
}else{
state = IIC_TX;
}
}else{ // ライト続行
state = IIC_RX;
}
DBG_P_n = 0;
if( state == IIC_TX ){ // 送信 //
do{
DBG_P_n = 1;
IICA = trx_buf;
reg_adrs += 1;
trx_buf = vreg_ctr_read( reg_adrs );
DBG_P_n = 0;
while( !IICAIF ){;}
IICAIF = 0;
}while( ACKD );
LREL = 1;
}else{ // 受信 //
SPIE = 1;
do{
DBG_P_n = 1;
trx_buf = IICA;
WREL = 1;
vreg_ctr_write( reg_adrs, trx_buf );
reg_adrs += 1;
DBG_P_n = 0;
while( !IICAIF ){;}
IICAIF = 0;
}while( !SPD );
SPIE = 0;
}
vreg_c_iic_release();
state = IIC_IDLE;
}
//#endif
/*****************************************************************************
基本API
*****************************************************************************/
void IICA_Init( void ){
IICAEN = 1;
IICE = 0; /* IICA disable */
IICAMK = 1; /* INTIICA disable */
IICAIF = 0; /* clear INTIICA interrupt flag */
IICAPR0 = 0; /* set INTIICA high priority */
IICAPR1 = 0; /* set INTIICA high priority */
P6 &= ~0x3;
SVA = IIC_C_SLAVEADDRESS;
IICF = 0x01;
STCEN = 1; // リスタートの許可
IICRSV = 1; // 通信予約をさせない:スレーブに徹する
SPIE = 0; // ストップコンディションでの割り込みを禁止
WTIM = 1; // 自動でACKを返した後clkをLに固定する
ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない
IICWL = 6; // L期間の長さ(?)
IICWH = 5;
IICAMK = 0; // 割り込みを許可
IICE = 1;
PM6 &= ~0x3; /* set clock pin for IICA */
}
//****************************************************************************
void IICA_Stop( void ){
IICE = 0; /* IICA disable */
IICAEN = 0;
}

476
trunk/i2c_mcu.c Normal file
View File

@ -0,0 +1,476 @@
/******************************************************************************
簡易I2C(内蔵ペリフェラル使用)通信
de JHL 藤田@開技
'09 Feb -
*******************************************************************************/
#pragma sfr
#pragma di
#pragma ei
#pragma nop
#pragma inline // memcpy()をインライン展開する
#include "incs_loader.h"
#include "i2c_mcu.h"
//#include <string.h>
bit iic_mcu_wo_dma;
volatile bit iic_mcu_busy;
volatile bit iic_mcu_initialized;
// SSR0n
#define bit_TSF0 6
// SIR0n
#define PECT0 ( 1 << 1 )
// SSR0n
#define PEF0 ( 1 << 1 )
#define TXE0 ( 1 << 15 )
#define RXE0 ( 1 << 14 )
#define SLC02 4
#define DLS02 0
#define TSF0 ( 1 << 6 )
#define DRS ( 1 << 6 )
#define TAUS_MASK 0b0000101100001011;
static void iic_mcu_send_st();
static void iic_mcu_send_re_st();
static void iic_mcu_send_sp();
static err iic_mcu_send_a_byte( u8 );
static err iic_mcu_call_slave( u8 slave );
u8 iic_send_work[4];
u8* p_iic_send_wo_dma_dat;
u8 iic_send_wo_dma_len;
volatile u8 interrupted;
u8 dma_state;
/*****
スレーブからの 『1文字』 リード
返値がデータそのものです。
エラー判定ができません。
******************************************************************************/
u8 iic_mcu_read_a_byte( u8 SLA, u8 adrs ){
u8 dat;
iic_mcu_read( SLA, adrs, 1, &dat );
return( dat );
}
/******************************************************************************
スレーブからのリード
0 正常終了
1 スレーブが応答しない
2 バスが誰かに占有されていてタイムアウト
3 意味不明エラー
【注】
スレーブがウェイトコンディションを出すことは禁止です。
その場合でもエラー検出などできません
******************************************************************************/
err iic_mcu_read( u8 slave, u8 adrs, u8 len, u8* dest ){
//*
// 使用中なら待つ
if( iic_mcu_initialized == 0 ){
#ifdef _debug_
iic_mcu_start();
#else
while(1){};
#endif
}
while( iic_mcu_busy ){
DBG_M_n = 1;
NOP();
}
DBG_M_n = 0;
/*/
// 使用中なら帰る
if( iic_mcu_initialized == 0 ){
return(0x80);
}
if( iic_mcu_busy != 0 ){
return( 3 );
}
//*/
// スタートコンディションとスレーブの呼び出し、レジスタアドレスの送信
if( iic_mcu_call_slave( slave ) != 0 ){
return( ERR_NAK );
}
// レジスタアドレスの送信
iic_mcu_send_a_byte( adrs ); // 終わるまで帰ってこない
// if( err != ERR_SUCCESS )~
// データ受信 //
iic_mcu_send_re_st(); // リスタートコンディション
iic_mcu_send_a_byte( slave | 0x01 ); // 送信完了まで戻ってきません。
// データ受信
ST0 = 0x0004; // 受信モードに設定を変えるのでロジック停止
SCR02 = RXE0 | 1 << SLC02 | 7 << DLS02; // 受信設定
SS0 = 0x0004; // 通信待機
while( len != 0 ){
if( len == 1 ){
SOE0 &= ~0x0004;
}
IICIF10 = 0;
SIO10 = 0xFF; // ダミーデータを書くと受信開始
while( IICIF10 == 0 ){;}
*dest = SIO10;
dest++;
len--;
}
iic_mcu_send_sp();
IICIF10 = 0;
iic_mcu_busy = 0;
return( ERR_SUCCESS );
}
/*****
スレーブへ 『1バイト』 ライト
前の転送が終わるのを待って、ライトします。
返値 iic_mcu_write に同じ
■元のデータをそのまま使って、書きっぱなしにするので、
ポインタをとっておかないと破壊されてしまう…気がする
******************************************************************************/
err iic_mcu_write_a_byte( u8 SLA, u8 adrs, u8 dat ){
volatile static u8 temp;
while( iic_mcu_busy ){
DBG_M_n = 1;
NOP();
}
DBG_M_n = 0;
temp = dat;
return( iic_mcu_write( SLA, adrs, 1, &temp ) );
}
u8* p_src_work; // DMA送信バッファ
u8 len_work;
/******************************************************************************
スレーブへライト
レジスタ adrs を先頭に、
*strから
len文字書きます。
0 正常終了
1 スレーブが応答しない
2 バスが誰かに占有されていてタイムアウト
3 前に指示された通信がまだ終わってない
【注】
スレーブがウェイトコンディションを出すことは禁止です。
その場合でもエラー検出などできません
DMA1を使用します。
******************************************************************************/
err iic_mcu_write( u8 slave, u8 adrs, u8 len, u8* src ){
//*
// 使用中なら待つ
if( iic_mcu_initialized == 0 ){
#ifdef _debug_
iic_mcu_start();
#else
while(1){};
#endif
}
while( iic_mcu_busy ){
DBG_M_n = 1;
NOP();
}
DBG_M_n = 0;
/*/
// 使用中なら帰る
if( iic_mcu_initialized == 0 ){
return(0x80);
}
if( iic_mcu_busy != 0 ){
return( 3 );
}
//*/
// スタートコンディションとスレーブの呼び出し...
IICMK10 = 1;
if( iic_mcu_call_slave( slave ) != 0 ){
return( ERR_NAK );
}
iic_mcu_busy = 1;
dma_state = 0;
if( !iic_mcu_wo_dma ){
// DMAを使用する(通常)
// レジスタアドレスの送信
memcpy( iic_send_work, src, 4 ); //バッファとして4バイトしか用意して無いため。
// DMAセット
while( DST1 ){;};
DEN1 = 1;
DSA1 = (u8)( &SIO10 );
DRA1 = (u16)iic_send_work;
DBC1 = len;
DMC1 = DRS | 8; // RAM -> SFR, 8bit, IRQ, IIC10
DMAIF1 = 0;
DMAMK1 = 0;
DST1 = 1;
IICIF10 = 0;
SIO10 = adrs; // 書きっぱなし! 割り込みが発生してDMAスタート
}else{
// DMAを使用しない //
// レジスタアドレスの送信
IICIF10 = 0;
SIO10 = adrs;
IICMK10 = 0;
iic_send_wo_dma_len = len;
p_iic_send_wo_dma_dat = src;
// 残りは割り込みルーチン内で
}
dma_state = 1;
return( ERR_SUCCESS );
}
/******************************************************************************
DMA1転送終了割り込み
IIC_mcu の送信完了コールバック関数のようなもの
注:DMA転送が終わっただけで、I2Cの転送は終わってません
******************************************************************************/
__interrupt void int_dma1(){
dma_state = 2;
DMAMK1 = 1;
DEN1 = 0;
IICMK10 = 0;
// 最後のバイト転送後、I2C割り込みが発生する
}
/**
IIC MCUのバイト送出完了割り込み
******************************************************************************/
__interrupt void int_iic10(){
dma_state = 3;
if( iic_mcu_wo_dma ){
// DMA使用せず、転送途中
if( iic_send_wo_dma_len != 0 ){
SIO10 = *p_iic_send_wo_dma_dat;
p_iic_send_wo_dma_dat++;
iic_send_wo_dma_len--;
return;
}
}
// 共通(最終バイト送信完了)
IICMK10 = 1;
iic_mcu_send_sp();
iic_mcu_wo_dma = 0;
iic_mcu_busy = 0;
}
/******************************************************************************
スレーブの呼び出し
 スレーブアドレスを呼んで、ACKの確認。
ACK →                 返:0
 NACK → ストップコンディションを出す。 返:1
******************************************************************************/
static err iic_mcu_call_slave( u8 slave ){
// スレーブの呼び出し //
iic_mcu_send_st();
// SIR02 = SSR02; // NAKエラーのフラグクリア
#if 0
if( iic_mcu_send_a_byte( slave ) != 0 ){
iic_mcu_send_sp();
return( 1 ); // 指定のスレーブがいない / busy
}
#else
IICIF10 = 0;
SIO10 = slave;
while( IICIF10 == 0 ){
NOP();
} // 通信中
if( SSR02 != 0 ){
SIR02 = SSR02;
iic_mcu_send_sp();
return( ERR_NAK );
}
#endif
return( ERR_SUCCESS );
}
/**
I2C単機能API
ほんとに1バイト書くだけ。
書き終わるまで帰りません
******************************************************************************/
static err iic_mcu_send_a_byte( u8 dat ){
IICIF10 = 0;
SIO10 = dat;
while( IICIF10 == 0 ){
NOP();
} // 通信中
if( SSR02 != 0 ){
SIR02 = SSR02;
return( 1 ); // NAK
}
return( 0 );
}
/**
スタートコンディションを発行
自力でぱたぱたしなくてはならない
*******************************************************************************/
static void iic_mcu_send_st(){
SO0 &= ~0x0004; // SDA
NOP();
NOP();
NOP();
NOP();
SO0 &= ~0x0400; // SCL
SOE0 = 0x0004; // ハード制御へ
SCR02 = TXE0 | 1 << SLC02 | 7 << DLS02; // 送信許可、データは8ビット単位
SS0 = 0x0004; // 通信待機
}
/**
リスタート発行
*******************************************************************************/
static void iic_mcu_send_re_st(){
ST0 |= 0x0004;
SO0 |= 0x0400 | TAUS_MASK; // ( SDA = H ), SCL -> H
NOP();
NOP();
NOP();
NOP();
SOE0 &= ~0x0004; // ( SCL = H ), SDA -> L
NOP();
NOP();
NOP();
NOP();
iic_mcu_send_st();
}
/**
ストップコンディション発行
この前に最後のバイトの送受信の時に前準備が必要です。
*******************************************************************************/
static void iic_mcu_send_sp(){
ST0 |= 0x0004;
SOE0 = 0; // 受信の時はもっと前に「も」設定してる。(NACK出力)
SO0 = 0x0000 | TAUS_MASK; // SCL
NOP();
NOP();
NOP();
NOP();
SO0 = 0x0400 | TAUS_MASK; // SCL
NOP();
NOP();
NOP();
NOP();
SO0 = 0x0404 | TAUS_MASK;
}
/**
バスのリセット
(ストップコンディションが出せそうだったらすかさず出す。
******************************************************************************/
void iic2m_bus_reset(){
u8 count;
/*
for( count = 19; count != 0; count-- ){
iics_sda_H;
iics_scl_H;
PM1.1 = 1; // SDA
if( iics_sda != 0 ){
PM1.1 = 0;
iic_mcu_send_sp;
return;
}
PM1.1 = 0;
iics_scl_L;
}
return;
*/
}
/**
* ペリフェラルモジュールの初期化
*****************************************************************************/
void iic_mcu_start(){
I2C_PU = 1;
SAU0EN = 1;
NOP(); // 4clkあける
NOP();
NOP();
NOP();
SPS0 = 0x0000; // シリアルユニットのクロック0。(8M/2)/1
SMR02 = 0 << 15 | 0 << 14 | 0 << 7 | 0 << 5 | 1 << 4 | 1 << 2; // I2Cとそのクロックなど設定
SDR02 = 5 << 9; // ボーレート設定 (8M/2)/1/(x+1)/2
SO0 = 0x0404 | TAUS_MASK; // 最初はHH
iic_mcu_busy = 0;
iic_mcu_wo_dma = 0;
iic_mcu_initialized = 1;
}
/**
* モジュールの停止
* 再度使うときは初期化が必要
*****************************************************************************/
void iic_mcu_stop(){
while( iic_mcu_busy ){;} // DMA動作中はもう少し待つ
iic_mcu_send_re_st(); // SCL,SDAをLLにする
I2C_PU = 0;
SAU0EN = 0;
iic_mcu_initialized = 0;
}

157
trunk/i2c_twl.c Normal file
View File

@ -0,0 +1,157 @@
#pragma sfr /* 特殊機能レジスタ使用 */
#ifndef _TEG_
// KE3Lの間はプレースホルダ
void IICB_Init( void ){}
void IICB_Stop( void ){}
void IICB_SlaveReceiveStart(){}
#else
/*============================================================================*/
#include "incs.h"
#include "i2c_twl_defs.h"
extern u8 vreg_twl[];
/*============================================================================*/
u8 vreg_adrs;
u8 pre_dat;
u16 tot;
// 注! ↓はマクロなので、returnはメインループに戻ります。
#define wait_next { \
tot = 0; \
while( IICAIF != 1 ){ \
if( SPD ){ \
LREL = 1; \
return; \
} \
tot++; \
if( tot == 0 ){ \
LREL = 1; \
return; \
} \
} \
}
__interrupt void int_iicb(){
WREL = 1; // ウェイト解除して次のバイトを待つ
// WDT_Restart();
// フラグ1回目 スレーブアドレス,R/W
if( COI != 1 ){ // 被呼び出し?
LREL = 1; // 呼ばれたのは他のID
return;
}else{
// ACKE0 = 1; // 自動でackを返すようにする
// WREL = 1; // ウェイト解除して次のバイトを待つ
}
wait_next; // 1バイト受信完了を待つ
// 2回目 R/W レジスタアドレス
WREL = 1;
IICBIF = 0;
vreg_adrs = adrs_table_twl_ext2int( IICB );
// 3回目
// スタートコンディションか、データ受信完了フラグ待ち
while( 1 ){
if( IICBIF == 1 ){
// 受信 //
IICBIF = 0;
WREL = 1;
// 通常アクセス(ライト) //
LREL = 1;
vreg_twl_write( vreg_adrs, IICB );
return; // 受信おしまい //
}else if( STD ){
// 送信 // (スタートコンディション検出)
pre_dat = vreg_twl_read( vreg_adrs ); // mcu内部アドレスを渡す。一バイト目の準備 IICBに書き込むとウェイト解除
// 自局をRで呼ばれるのを待つ
wait_next;
IICBIF = 0;
if( COI != 1 ){ // 被呼び出し?
LREL = 1; // 呼ばれたのは他のID(あれ?)
return;
}
IICB = pre_dat; // データを送る
wait_next;
// 4回目。(送信データ後の、ACK/NACK後) どうしても発生してしまう。
IICBIF = 0; // おしまい
LREL = 1;
return;
}else if( SPD ){ // 強制終了
LREL = 1;
return;
}
}
}
/*****************************************************************************
基本API
*****************************************************************************/
void IICB_Init( void )
{
IICBEN = 1;
IICE = 0; /* IICB disable */
IICBMK = 1; /* INTIICB disable */
IICBIF = 0; /* clear INTIICB interrupt flag */
IICBPR0 = 0; /* set INTIICB high priority */
IICBPR1 = 0; /* set INTIICB high priority */
PM6 &= ~0x3; /* set clock pin for IICB */
P6 &= ~0x3;
SVA = IIC_T_SLAVEADDRESS;
IICF = 0x01;
STCEN = 1; // リスタートの許可
IICRSV = 1; // 通信予約をさせない:スレーブに徹する
SPIE = 0; // ストップコンディションでの割り込みを禁止
WTIM = 1; // 自動でACKを返した後clkをLに固定する
ACKE = 1; // ダメCPUは無視して次の通信をはじめるかもしれないんで早くclkを開放しないといけない
IICBMK = 0; // 割り込みを許可
IICE = 1;
// spie のセット
// 使用時に再初期化
// IICE0を1にしていいのはscl,sdaがHHの時だけ
}
//****************************************************************************
void IICB_Stop( void ){
IICE = 0; /* IICB disable */
}
void IICB_SlaveReceiveStart(){
IICE = 1;
LREL = 1;
return;
}
#endif

98
trunk/ini_VECT.c Normal file
View File

@ -0,0 +1,98 @@
#include "config.h"
//#pragma interrupt INTWDTI fn_intwdti // 未使用
//#pragma interrupt INTLVI fn_intlvi // 未使用
#pragma interrupt INTP0 intp0 // SLP
//#pragma interrupt INTP1 fn_intp1 // (I2C)
//#pragma interrupt INTP2 fn_intp2 // (I2C)
//#pragma interrupt INTP3 fn_intp3 // 未搭載
#pragma interrupt INTP4 intp4 // EXTDC
#pragma interrupt INTP5 intp5 // SHELL_CLOSE
//#pragma interrupt INTCMP0 fn_intcmp0
//#pragma interrupt INTCMP1 fn_intcmp1
//#pragma interrupt INTDMA0 fn_intdma0
#pragma interrupt INTDMA1 int_dma1
//#pragma interrupt INTST0 fn_intst0
/* #pragma interrupt INTCSI00 fn_intcsi00 */
//#pragma interrupt INTSR0 fn_intsr0
/* #pragma interrupt INTCSI01 fn_intcsi01 */
//#pragma interrupt INTSRE0 fn_intsre0
//#pragma interrupt INTST1 fn_intst1
/* #pragma interrupt INTCSI10 fn_intcsi10 */
#pragma interrupt INTIIC10 int_iic10
//#pragma interrupt INTSR1 fn_intsr1
//#pragma interrupt INTSRE1 fn_intsre1
#pragma interrupt INTIICA int_iica // CTR側
#ifndef _TEG_
#pragma interrupt INTIICB int_iicb // TWL側
#endif
//#pragma interrupt INTTM00 fn_inttm00
//#pragma interrupt INTTM01 fn_inttm01
//#pragma interrupt INTTM02 fn_inttm02
//#pragma interrupt INTTM03 fn_inttm03
#pragma interrupt INTAD int_adc
//#pragma interrupt INTRTC int_rtc
#pragma interrupt INTRTCI int_rtc_int
#pragma interrupt INTKR int_kr
//#pragma interrupt INTMD fn_intmd
//#pragma interrupt INTTM04 fn_inttm04
//#pragma interrupt INTTM05 fn_inttm05
//#pragma interrupt INTTM06 fn_inttm06
//#pragma interrupt INTTM07 fn_inttm07
#pragma interrupt INTP6 fn_intp6
#pragma interrupt INTP7 fn_intp7
/****************************************************/
/* 未使用時のダミー関数定義 */
/****************************************************/
__interrupt void fn_intwdti(){ while(1){}; }
__interrupt void fn_intlvi(){ while(1){}; }
//__interrupt void fn_intp0(){}
__interrupt void fn_intp1(){ while(1){}; } //
__interrupt void fn_intp2(){ while(1){}; }
__interrupt void fn_intp3(){ while(1){}; }
__interrupt void fn_intp4(){ while(1){}; }
__interrupt void fn_intp5(){ while(1){}; }
__interrupt void fn_intcmp0(){ while(1){}; }
__interrupt void fn_intcmp1(){ while(1){}; }
__interrupt void fn_intdma0(){ while(1){}; }
//__interrupt void fn_intdma1(){} // i2c_mcu.cにある
__interrupt void fn_intst0(){ while(1){}; }
/* __interrupt void fn_intcsi00(){} */
__interrupt void fn_intsr0(){ while(1){}; }
/* __interrupt void fn_intcsi01(){} */
__interrupt void fn_intsre0(){ while(1){}; }
__interrupt void fn_intst1(){ while(1){}; }
/* __interrupt void fn_intcsi10(){} */
//__interrupt void fn_intiic10(){ while(1){}; }
__interrupt void fn_intsr1(){ while(1){}; }
__interrupt void fn_intsre1(){ while(1){}; }
//__interrupt void fn_intiica(){} // i2c.cにある
/* __interrupt void fn_inttm00(){} */ /* sub.cにて定義 */
__interrupt void fn_inttm01(){ while(1){}; }
__interrupt void fn_inttm02(){ while(1){}; }
__interrupt void fn_inttm03(){ while(1){}; }
//__interrupt void fn_intad(){ while(1){}; } // adc.c
__interrupt void fn_intrtc(){ while(1){}; }
//__interrupt void int_rtcint(){} // rtc.cにある
//__interrupt void fn_intkr(){} // main.c
__interrupt void fn_intmd(){ while(1){}; }
__interrupt void fn_inttm04(){ while(1){}; }
__interrupt void fn_inttm05(){ while(1){}; }
__interrupt void fn_inttm06(){ while(1){}; }
__interrupt void fn_inttm07(){ while(1){}; }
__interrupt void fn_intp6(){ while(1){}; }
__interrupt void fn_intp7(){ while(1){}; }

119
trunk/led.c Normal file
View File

@ -0,0 +1,119 @@
#pragma sfr
#include "incs.h"
#include "led.h"
// TPS0
#define BIT_PRS01 4
#define BIT_PRS00 0
// 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
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 = 1 << BIT_PRS01 | 1 << BIT_PRS00; // マスタークロックは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以降にクロックが届かない
TOL0 = 0;
TO0 = 0; // タイマー動作中で、タイマー出力にしてないときのピンのラッチ。タイマー出力を使わないなら0
TOE0 = 0b0000000011101110; // TOxをタイマーモジュールが制御?
TS0 = 0b0000000011101111; // 動作開始
TDR00 = 0x03FE; // 10bit, 周期
}
void LED_stop(){
TT0 = 0b0000000011101111; // 一斉停止(しないとだめ)
TOE0 = 0b0000000000000000; // TOxをタイマーモジュールが制御?(GPIOになる)
TAU0EN = 0;
}
/*******************************************************************************
LED
LED_Cam TO02
LED_Charge 5
LED_POW_B,R 6,7
LED_Wifi,2 3, P24
LED_3D 4
基本的にそれぞれの関係するタスクが管理するが、余ってしまったのはここで管理
TDR00 周期(0x03FF。TPS0で250kHzでカウントアップ。10bitなら250Hz位になる)
TDR0x Duty 0で消灯、TDR00(より大 =0x03FF以上)で点灯です。
*******************************************************************************/
task_status tsk_led(){
switch( system_status.pwr_state ){
case OFF:
break;
case ON_TRIG:
LED_duty_pow_H = 0x01FF;
LED_duty_pow_L = 0x0100;
LED_duty_WiFi = 0x03FF;
LED_duty_CAM = 0x0040;
LED_duty_3D = 0x0001;
break;
case ON:
LED_duty_WiFi = vreg_ctr[ VREG_C_3D_DEPTH ];
LED_duty_CAM = vreg_ctr[ VREG_C_VOL ];
LED_duty_3D = vreg_ctr[ VREG_C_BT_TEMP ];
break;
case SLEEP_TRIG:
LED_duty_pow_H = 0x0010;
LED_duty_pow_L = 0x0400;
LED_duty_WiFi = 0x0020;
LED_duty_CAM = 0x0080;
LED_duty_3D = 0x0100;
break;
case SLEEP:
break;
case OFF_TRIG:
LED_duty_pow_L = 0x03FE;
break;
default:
break;
}
return( 10 );
}

357
trunk/loader.c Normal file
View File

@ -0,0 +1,357 @@
/*============================================================================
MCU CTR BSR
2009/03/30
開発技術部 藤田
ブートローダー部
ホストの通信と、自己書き換え、ファームのチェックを行う。
============================================================================*/
#pragma SFR
#pragma di
#pragma ei
#pragma nop
#pragma stop
#pragma halt
#include "incs_loader.h"
#include "fsl.h"
#include "fsl_user.h"
#include "i2c_ctr.h"
#include "i2c_mcu.h"
#include "pm.h"
#include "rtc.h"
/*============================================================================*/
#define VER_HEADER 0x2100
#define VER_FOOTER 0x7000
/*============================================================================*/
#if (FSL_DATA_BUFFER_SIZE>0)
fsl_u08 fsl_data_buffer[FSL_DATA_BUFFER_SIZE];
#endif
#ifdef FSL_INT_BACKUP
static fsl_u08 fsl_MK0L_bak_u08; /* if (interrupt backup required) */
static fsl_u08 fsl_MK0H_bak_u08; /* { */
static fsl_u08 fsl_MK1L_bak_u08; /* reserve space for backup information */
static fsl_u08 fsl_MK1H_bak_u08; /* of interrupt mask flags */
static fsl_u08 fsl_MK2L_bak_u08; /* */
static fsl_u08 fsl_MK2H_bak_u08; /* } */
#endif
/*============================================================================*/
void FSL_Open(void);
void FSL_Close(void);
void hdwinit(void);
static void emergency_boot();
void power_save();
extern void main_loop();
/*============================================================================*/
void main(){
while(1){
// 電池投入 //
// hdwinit(); 自動実行
// 電池投入時のみ初期化
/// ファーム更新に最低限必要な物
//
u8 temp;
FSL_GetActiveBootCluster( &temp );
// ファームの整合性チェック
// とは言っても、領域の先頭と最後のマジックナンバーを見るだけ
{
u8 i;
u8 comp = 0;
for( i = 0; i < sizeof( __TIME__ ); i++ ){
comp |= ( *((u8*)( VER_HEADER + i )) ^ *((u8*)( VER_FOOTER + i )) );
}
if( comp != 0 ){
while(1){
emergency_boot();
P1.4 = 0;
IICA_Stop();
iic_mcu_stop();
BT_TEMP_P = 0;
KRM = KR_SW_POW;
EGP0 = 0b00000000; // 0で検出しない
EGN0 = 0b00000000; // SHELL, EXTDC
// intp20系は後ほど
MK0 = 0b1111111111111111; // SHELL, EXTDC
MK1 = 0b1111011111111111; // KR
// MK1 = 0b1111010111111111; // KR, RTC(Alarm)
MK2L= 0b11111111;
// pullup_off();
{
PU5 = 0b00000000;
PU7 = 0b00010000;
}
STOP();
}
}
}
// 通常運転
main_loop();
}
}
/******************************************************************************
ファームが壊れた場合、
(必要なら)勝手に電源投入を試みて、ファーム異常割り込みを掛けます。
電池切れ等だったら、電源ボタンが押されるのを待つ
メインループを回せないのです。
******************************************************************************/
void emergency_boot(){
// 電源を入れる
iic_mcu_start();
PM_init();
// PM_bt_auth(ほげ)
if( iic_mcu_read_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_VDD_SYS ) != 0 ){
if( PM_sys_pow_on() != ERR_SUCCESS ){ // 電源起動不可エラー
return;
}
}
//*
if( PM_LCD_on() == 0 ){
return;
}
//*/
// LEDの強制点灯
P1.4 = 1;
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DIR, 0x00 );
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x80 );
RTC_32k_on();
vreg_ctr[ VREG_C_MCU_STATUS ] |= REG_BIT_MCU_FIRMBROKEN;
vreg_ctr[ VREG_C_IRQ0 ] |= REG_BIT_IRQ0_MCUSTATUS;
IICA_Init();
IRQ_0_ast; // レジスタリードのところで ngtする
while(1){ // ファームが送られてくるのを待つ
u16 pwsw_count = 0;
if( renge_flg_interval ){
renge_flg_interval = 0;
if( !SW_POW_n ){ // 電源長押しされたら強制電源OFF
pwsw_count += 1;
if( pwsw_count > 400 ){
return;
}
}else{
pwsw_count = 0;
}
}
HALT();
}
}
void power_save(){
if( !renge_task_interval_run_force ){
HALT();
}
}
/******************************************************************************
キーリターン割り込み
一度にいくつものビットを使わないつもりなんだが
******************************************************************************/
__interrupt void int_kr(){
if( system_status.pwr_state == OFF ){
// 電源onのカウント。特にすることはない
}
}
/******************************************************************************
ext dc
******************************************************************************/
__interrupt void intp4(){
}
/******************************************************************************
shell close
******************************************************************************/
__interrupt void intp5(){
}
/*============================================================================*/
void hdwinit(void){ // スタートアップルーチンが勝手に呼びます
DI(); /* マスタ割り込み禁止 */
CMC = 0b00010110; /* X1発振せず(入力ポート)、XT1使用、推奨の推奨で超低電力発振 */
CSC = 0b10000000; /* X1発振なし、XT1発振あり、高速内蔵発振動作 */
// OSMC = 0x00; /* フラッシュ・メモリの高速動作用昇圧回路 */
CKC = 0b00001001; /* CPU/周辺クロック=fMAIN、fMAIN=fMX、fCLK=fMX */
/*--- 低電圧検出回路の設定 ---*/
/* リセット解除時のデフォルトは、オプション・バイトにて指定される */
LVIS = 0b00000000; /* VLVI = 4.22±0.1V */
LVIM = 0b00000000; /* LVI動作禁止 */
/* 電源電圧(VDD)<検出電圧(VLVI)時に割込発生 */
/* 電源電圧(VDD)≧検出電圧<VLVI)、または動作禁止時に低電圧検出 */
// ポート設定
P0 = 0b00000000;
P1 = 0b00000000;
P2 = 0b00000000;
P3 = 0b00000110; // 簡易I2Cは出力ラッチを1にする
P4 = 0b00000000;
P5 = 0b00000000;
P6 = 0b00000000;
P7 = 0b01000000;
P12 = 0b00000000;
P14 = 0b00000000;
/// P20 = 0b00000000;
P15 = 0b00000000;
// プルアップ
PU0 = 0b00000000; // バッテリ認証後にそれぞれセット
PU1 = 0b00000000;
PU3 = 0b00000000;
PU4 = 0b00000000;
PU5 = 0b00000011;
PU7 = 0b00011001;
PU12 = 0b00000000;
PU14 = 0b00000000;
/// PU20 = 0b00000000;
PM0 = 0b00000000; // 0で出力
PM1 = 0b00000000;
PM2 = 0b11101001;
PM3 = 0b00000001; // P31,32は簡易I2C
PM4 = 0b00001011;
PM5 = 0b00000011;
PM6 = 0b00000000; // I2CのラインがL出力になってしまうが、システムがOFFなのでかまわない
PM7 = 0b00011111;
PM12 = 0b00011111; // 32kHzクロックのピン設定はどっちでもよい
PM14 = 0b00000001; // debugger[1] とりあえず出力
PM15 = 0b00000111;
/// PM20 = 0b00111100;
// ポート入力モード・レジスタ設定
// [0:通常入力バッファ 1:TTL入力バッファ]
PIM3 = 0b00000000;
PIM7 = 0b00000000;
// ポート出力モード・レジスタ設定
// [0:通常出力モード 1:N-chオープン・ドレーン出力]
POM3 = 0b00000110;
POM7 = 0b00000000;
/*--- 割り込み設定 ---------*/
IF0L = 0b00000000; /* 割り込み要求フラグクリア */
IF0H = 0b00000000;
IF1L = 0b00000000;
IF1H = 0b00000000;
IF2L = 0b00000000;
MK0L = 0b11111111; /* 割り込み禁止 */
MK0H = 0b11111111;
MK1L = 0b11111111;
MK1H = 0b11111111;
MK2L = 0b11111111;
PR00L = 0b11111111; /* 割り込み優先順位、全て低位(LV3) */
PR10L = 0b11111111;
PR00H = 0b11111111;
PR10H = 0b11111111;
PR01L = 0b11111111;
PR11L = 0b11111111;
PR01H = 0b11111111;
PR11H = 0b11111111;
PR02L = 0b11111111;
PR12L = 0b11111111;
/*--- 外部割込の有効エッジ設定 ---*/
EGP0 = 0b00000000; /* 立上りエッジの検出禁止 */
EGN0 = 0b00000000; /* 立下りエッジの検出禁止 */
/*--- キー割り込み設定 ---*/
KRM = 0b00000000; /* 全キー割り込み信号を検出しない */
/*--- タイマ・アレイ・ユニットの動作停止 ---*/
TAU0EN = 0; /* タイマ・アレイ・ユニットへのクロック供給停止 */
TT0 = 0x00ff; /* 全タイマ・チャネルの動作停止 */
/*--- RTCの動作停止 ---*/
// RTCEN = 0; /* RTCへのクロック供給停止 */
// RTCC0 = 0b00000000; /* カウンタ動作停止 */
// 別途初期化関数
/*--- コンパレータ/プログラマブル・ゲイン・アップの動作停止 ---*/
OACMPEN = 0; /* クロック供給停止 */
OAM = 0x00; /* プログラマブル・ゲイン・アップの動作停止 */
C0CTL = 0x00; /* コンパレータ0動作停止 */
C1CTL = 0x00; /* コンパレータ1動作停止 */
/*--- クロック出力/ブザー出力停止 ---*/
CKS0 = 0b0000000;
CKS1 = 0b0000000;
/*--- ADCの動作停止 ---*/
ADCEN = 0; /* ADCへのクロック供給停止 */
ADM = 0b00000000; /* 変換動作停止 */
/*--- シリアル・アレイ・ユニットの動作停止 ---*/
SAU0EN = 0; /* シリアル・アレイ・ユニット0へのクロック供給停止 */
SCR00 = 0x0087; /* 各チャンネルの通信禁止 */
SCR01 = 0x0087;
SCR02 = 0x0087;
SCR03 = 0x0087;
/*--- IICAの動作停止 ---*/
IICAEN = 0; /* IICAへのクロック供給停止 */
IICCTL0 = 0x00; /* IICA動作停止 */
/*
// IICBの動作停止
IICAEN = 0; // IICAへのクロック供給停止
IICCTL0 = 0x00; // IICA動作停止
*/
/*--- DMAの動作停止 ---*/
DRC0 = 0b00000000; /* DMAチャネル0の動作禁止 */
DRC1 = 0b00000000; /* DMAチャネル1の動作禁止 */
}

12
trunk/magic.c Normal file
View File

@ -0,0 +1,12 @@
/*****************************************************************************
ビルド時刻を埋め込みます。
ビルドの度に更新されるようにする必要がありますよ。
(touchしてね)
****************************************************************************/
#pragma section @@CNST MGC_HEAD AT 0x02100
static const unsigned char VER_HEADER[] = __TIME__;
#pragma section @@CNST MGC_TAIL AT 0x07000
static const unsigned char VER_FOOTER[] = __TIME__;

141
trunk/main.c Normal file
View File

@ -0,0 +1,141 @@
/******************************************************************************
MCU CTR BSR
2008,2009 nintendo
開発技術部 藤田
ばさら(婆娑羅)。十二神将の2番目、丑の守り神だそうだ。
二番目のプロダクトなので。中二っぽい。
前回の BP_TWL の BP は (The) back player を文字って back processor 。後衛です。
レーザーマーキングの文字数の制限のため。
todo:
>1) BL用PWMはスリープに入る時にはOffにしておかないとまずいですよね?
> 結局順序の保証がいるので、MCUに「PMIC I2C Busy」フラグが欲しいのです
> が、いかがでしょうか?>藤田君
> 仕様として、SoCからのPMICへの処理依頼の書き込み終了直後に 1 である
> ことが保証され、PMICへの全通信完了後に 0 になるというものです。
> LCD Off時は50msec待っている間もずっと 1 の方がうれしい気がします。
> 無理なら、「BL Setting Busy」フラグでも良いですが。
>
>2) 前、齋藤君がLCD Offの期間 100 msec 保証は SoCの起動に 100 msec かかる
> から心配ないようなことを書いていましたが、実際には、LCD Offシーケンス
> に 50 msec かかるので、LCD Offシーケンス開始からだと合計 150 msec 必
> 要です。SoCからMCUにLCD Off指示、直後にスリープ、直後にスリープ復帰、
> 直後にLCD Onとした場合に、十分なOff期間があるかちゃんと計算しておいて
> ください。>これも藤田君?
>
> よく考えたら、スリープに入らずに Off → On する場合も考えておかないと
> いけないので、MCUに「LCD On許可」フラグも用意してもらうべきかも。
>
> (NITROのスリープで苦労した時間計測もMCUがあれば楽々解決ですね!)
■・電源OFFシーケンス中にモデルゲージ(加速度センサ)への通信は止めてください。
>電源が遅く切り替わると内部回路の最低動作電圧で内部の制御回路が不安定になるの
>でバスをLOWに引っ張ることはないことを保証できないため
*****************************************************************************/
/*
管理担当がついてない
pm_irq
snd_depop
/fcram_reset
/mcu_irq
/reset1
/reset2
slp
/wl_reset
wl_rx
wl_tx
extopt_det
accel_valid
accel_int
dbg
shell_close,_p
*/
//*****************************************************************************
#include "incs.h"
#include "WDT.h"
#include "rtc.h"
#include "pm.h"
#include "accero.h"
//*****************************************************************************
err to_sleep();
static void read_dipsw();
unsigned char temp_teg;
extern void power_save();
//*****************************************************************************
bit active;
bit sleep;
bit rsv_to_sleep;
bit rsv_LCD_on;
bit rsv_BL_on;
system_status_ system_status;
u8 off_delay; // 電源 OFF から PWSW 等で電源オンする際、押してる時間をカウントするのに使う
/******************************************************************************
本当のエントリ関数は loader.c にあります
*****************************************************************************/
void main_loop( void ){
// 電池投入時の1回のみ
vreg_ctr_init();
RTC_init(); // 電池初投入ビットも立てます
PM_reset();
vreg_twl_init();
read_dipsw();
// 特定スイッチで何かするか?
renge_init();
system_status.pwr_state = OFF_TRIG;
renge_task_interval_run_force = 1;
EI();
// メインループ //
while(1){ // システムtick、または割り込みで廻ります。
WDT_Restart();
DBG_P_n = 1;
renge_task_interval_run(); // 内部で、システムtickまたは強制起動します
DBG_P_n = 0;
DBG_P_n = 1;
renge_task_immed_run(); // ここのループが廻る度に実行されます
DBG_P_n = 0;
power_save();
}
}
static void read_dipsw(){
// ソフトディップスイッチ読み込み
PU4 |= 0x03; // dip sw 0,1
system_status.dipsw0 = ( DIPSW_0 == 0 )? 0: 1;
system_status.dipsw1 = ( DIPSW_1 == 0 )? 0: 1;
PU4 &= ~0x03;
}

485
trunk/pm.c Normal file
View File

@ -0,0 +1,485 @@
/******************************************************************************
対PMIC_TWL2 I2C通信
de JHL 藤田@開技
nintendo
'08 Dec
*******************************************************************************/
#pragma nop
#include "incs_loader.h"
#include "i2c_mcu.h"
#include "adc.h"
#include "led.h"
#include "pm.h"
#define BT_GAUGE_UNLOCK_ADRS 0x3E
#define BT_BT_PARAM_ADRS 0x40
#define BT_BT_PARAM_PANA_RCOMP_ADRS 0x0C
// -1.45 ,-3.9}
static const u8 BT_BT_PARAM_PANA[64] = {
0xEA, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F,
0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x27,
0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F };
static const u8 BT_BT_PARAM_PANA_RCOMP_AND_PARAM[3] = { 158, 1, 4 }; // RCOMP, TempCoUp, ---Down;
u16 raw_adc_temperature;
#define _TEG_
/*****************************************************************************
バッテリの認証を行います。
引数 無し
返値 (ERR)ERR_SUCCESS 成功
それ以外 失敗
*****************************************************************************/
err PM_bt_auth(){
/*
todo
マキシムなら Dallas-1wire 通信
SHA-1計算
*/
return( ERR_SUCCESS );
}
/*****************************************************************************
バッテリ固有のパラメータをセット
 ・64バイトのパラメータを直接ROM領域においておきたかったのだが、
  なんと、DMAがROMRAM領域からしか持ってこられないので
  ランタイムルーチンにスタックにコピーしてもらう orz
・スタックが不安なので、ベンダの数だけ関数を作る
引数 無し
返値 無し
*****************************************************************************/
static void BT_set_batt_vend1(){
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_BT_PARAM_PANA_RCOMP_ADRS,
sizeof( BT_BT_PARAM_PANA_RCOMP_AND_PARAM ),
BT_BT_PARAM_PANA_RCOMP_AND_PARAM
);
iic_mcu_set_wo_dma();
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_BT_PARAM_ADRS,
sizeof( BT_BT_PARAM_PANA ),
BT_BT_PARAM_PANA
);
/*
ベリファイしなさいと書いてあるが意味がわからないです
todo あとで
The host must then verify that the model was written properly to the device. The MAX17040 does not allow the
user to read the model directly. In order to verify the model, the host should write the maximum OCV point from
the model to the OCV register (memory location 0x0Eh) and verify that the SOC register (memory location 0x04)
matches the desired SOC value from the model. Before updating the OCV register, the host should read the OCV
register, so that the original value can be rewritten to the device after the model is verified.
//Read Original OCV Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
RESTART
Send Slave Address (0x6Dh)
Send Memory Location (0x0Eh)
Read Data Byte OriginalOCV1
Read Data Byte OriginalOCV2
STOP
//Write OCV Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
Send Data Byte (0xh)
Send Data Byte (0xh)
STOP
//Read SOC Register
START
Send Slave Address (0x6Ch)
Send Memory Location (0x04h)
RESTART
Send Slave Address (0x6Dh)
Send Memory Location (0x04h)
Read Data Byte SOC1
Read Data Byte SOC2
STOP
//Compare value
//Write OCV Register back to original
START
Send Slave Address (0x6Ch)
Send Memory Location (0x0Eh)
Send Data Byte (OriginalOCV1)
Send Data Byte (OriginalOCV2)
STOP
To lock the model the host software must write 0x00h to memory location 0x3Eh and 0x00h to memory location
0x3Fh.
//Lock Model Access
START
Send Slave Address (0x6Ch)
Send Memory Location (0x3Eh)
Send Data Byte (0x00h)
Send Data Byte (0x00h)
STOP
*/
return;
}
/*****************************************************************************
PMICにリセットコマンドを送る
電池接続時に一回だけ
*****************************************************************************/
err PM_reset(){
iic_mcu_start();
return( iic_mcu_write_a_byte( IIC_SLA_PMIC, PM_REG_ADRS_CONT, 0x00 ) );
}
/*****************************************************************************
PMIC達の初期化
電池メーカー識別
電池残量ICのセット
バージョン情報の取得
以下のピンは主にここで操作・監視されます。
・PM_BT_DET,_P
*****************************************************************************/
void PM_init(){
u8 temp;
u8 result;
u8 BT_GAUGE_UNLOCK_KEY[2] = { 0x4A, 0x57 };
u8 BT_GAUGE_QUICK_START[2] = { 0x40, 0x00 };
// バッテリ残量ICクイックスタート
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_REG_MODE,
2,
BT_GAUGE_QUICK_START[0] );
BT_TEMP_P = 1; // 電池温度監視スタート
// 電池固有パラメータの書き込み
iic_mcu_write( IIC_SLA_BT_GAUGE,
BT_GAUGE_UNLOCK_ADRS,
sizeof( BT_GAUGE_UNLOCK_KEY ),
BT_GAUGE_UNLOCK_KEY );
// 電池メーカーのセット
BT_DET_P = 1;
temp = (u8)( get_adc( ADC_SEL_BATT_DET ) >> 6 );
BT_DET_P = 0;
switch( temp ){
// case( BT_VENDER_PANA ):
default:
BT_set_batt_vend1();
break;
}
// 電池温度測定
raw_adc_temperature = get_adc( ADC_SEL_BATT_TEMP ); // 温度のtemp。
PM_bt_temp_update();
// PMIC バージョン読み出し
result = iic_mcu_read( IIC_SLA_PMIC, PM_REG_ADRS_VER, 1, &temp );
vreg_ctr[ VREG_C_PM_INFO ] = temp;
/*
PMICのセット
 LCD DACの値のセット
*/
}
/*****************************************************************************
raw_adc_temperatureに入っている値を℃に変換するとともに、
・レジスタにセット
・残量ICにセット
*****************************************************************************/
err PM_bt_temp_update(){
static u8 temp_threash_hi, temp_threash_lo;
u8 temp[2];
/*
サーミスタ - 10kΩ分圧点の時、
常用温度では分圧比のカーブがほぼリニアで、
村田 T[℃] = 81.48 - 111.97 x ratio
TDK T = 81.406 - 111.81 x ratio
*/
vreg_ctr[ VREG_C_BT_TEMP ] = ( 163 - ( 224 * ( raw_adc_temperature )) ) / 2;
/*
If Temperature > 20 Then
NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoUp)
ElseIf Temp < 20 Then
NewRCOMP = StartingRCOMP + ((Temperature - 20) * TempCoDown)
Else
NewRCOMP = StartingRCOMP
End If
*/
// 変化が少なかったら書きに行かない
// todo
return( iic_mcu_write( IIC_SLA_BT_GAUGE, BT_BT_PARAM_PANA_RCOMP_ADRS, 2, temp ) );
}
/*****************************************************************************
バックライト周り
*****************************************************************************/
#ifdef _TEG_
err PM_LCD_on(){
PM_TEG_LCD_OFF = 0;
return( PM_chk_LDSW() );
}
err PM_BL_on(){ return( PM_chk_LDSW() ); }
err PM_BL_off(){ return( PM_chk_LDSW() ); }
err PM_LCD_off(){
PM_TEG_LCD_OFF = 1;
return( PM_chk_LDSW() );
}
#else
err PM_LCD_on(){
PM_VDDLCD_on();
wait_ms( DELAY_PM_TSS_50B );
PM_TCOM_VCS_on();
return( PM_chk_LDSW() );
}
err PM_BL_on(){
PM_set_BL( 0x03 );
wait_ms( 10 );
return( PM_chk_LDSW() );
}
err PM_BL_off(){
PM_set_BL( 0x00 );
return( ERR_SUCCESS );
}
err PM_LCD_off(){
PM_TCOM_VCS_off();
wait_ms( 1 + 50 );
PM_VDDLCD_off(); // 残ってたの全部止めます。
return( ERR_SUCCESS );
}
#endif
/*****************************************************************************
シーケンスの通り電源を立ち上げてゆきます。
返値 0 最後まで正常に完了した。
1 ショートなどで電源があがりきらなかった
以下のピンは主にここで操作・監視されます。
・POW_CONT1,2 TEG電源のみ
*****************************************************************************/
err PM_sys_pow_on(){
#ifndef _TEG_
u8 temp;
// 電池温度測定
while( ADCEN != 0 ){;}
BT_TEMP_P = 1;
vreg_ctr[ VREG_C_DBG_BATT_TEMP ] = get_adc( ADC_SEL_BATT_TEMP );
BT_TEMP_P = 0;
temp = vreg_ctr[ VREG_C_DBG_BATT_TEMP ];
PM_set_batt_temp( temp ); // 温度のtemp。 残量ICに行きます
// 残量チェック
PM_get_batt_left();
if( temp < 0 ){
return( 1 );
}
vreg_ctr[ VREG_C_BATT_INFO ] = temp;
// 電源順次立ち上げ
PM_LDSW_on();
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD_on();
wait_ms( DELAY_PM_TW_PWUP );
PM_VDD50A_on();
wait_ms( DELAY_PM_TW_PWUP );
if( PM_chk_LDSW() == 0 ){
return( ERR_ERR );
}
PM_reset_neg();
RESET2_n = 1;
return( ERR_SUCCESS );
#else
// KE3-L で開発
u8 temp;
// 電源投入
RESETs_ast;
FCRAM_RST_ast;
PM_TEG_PWSW = 1;
wait_ms( 160 );
PM_TEG_PWSW = 0;
// 残量確認
PM_get_batt_left();
if( temp < 0 ){
return( 1 );
}
vreg_ctr[ VREG_C_BT_LEFT ] = temp;
RESET1_ngt;
wait_ms( 1 );
if( !RESET1_n ){
// 起動失敗
RESET2_ast;
FCRAM_RST_ast;
return( ERR_ERR );
}
RESET2_ngt;
FCRAM_RST_ngt;
return( ERR_SUCCESS );
#endif
}
err to_sleep(){
PM_LCD_off();
return 0;
}
err to_off(){
PM_LCD_off();
RESETs_ast;
PM_off();
PM_LDSW_off();
return 0;
}
/*****************************************************************************
電池の管理
以下のピンは主にここで操作・監視されます。
・PM_BT_AUTH 現状、GPI in
・PM_CHARGE_n CCIC /CHG in
・PM_CHARGE_ERR_n /FLT in
・PM_EXTDC_n /DOK INTP4 in
・PM_CHARGE_EN_n /CEN out
以下の物は関係ありそうですが別のところで主に監視されています。
・LED_Pow R, B, Charge tsk_LED
・BT_TEMP,_P tsk_ADC
PM_EXTDCは割り込みメインにするかも
*****************************************************************************/
#define set_bit( cond, reg, pos ) \
{ \
if( cond ){ \
reg |= pos; \
}else{ \
reg &= ~pos; \
} \
}
task_status tsk_batt(){
static u8 bt_stat = 0;
static u8 charge_hys = 0; // ヒステリシスで上限下限を拡張するとき1
// 電源周りのステータスが変化?
set_bit( PM_EXTDC, vreg_ctr[ VREG_C_STATUS0 ], 0x80 );
set_bit( BT_CHG_EN, vreg_ctr[ VREG_C_STATUS0 ], 0x40 );
set_bit( !BT_CHG_ERR_n, vreg_ctr[ VREG_C_STATUS0 ], 0x20 );
if( ( ( vreg_ctr[ VREG_C_STATUS0 ] ^ bt_stat ) & 0xE0 ) != 0 ){
vreg_ctr[ VREG_C_IRQ1 ] |= 0x80;
}
bt_stat = vreg_ctr[ VREG_C_STATUS0 ];
// 充電
if( (( 345 / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) && ( vreg_ctr[ VREG_C_BT_TEMP ] < ( 739 / 4 )) ){
charge_hys = 1;
}
if(( (( 345 - 65 ) / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] ) && ( vreg_ctr[ VREG_C_BT_TEMP ] < (( 739 + 18 ) / 4 )) ){
charge_hys = 0;
}
if( ( ( charge_hys == 1 )
&& ( (( 345 - 65 ) / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] )
&& ( vreg_ctr[ VREG_C_BT_TEMP ] < (( 739 + 18 ) / 4 )) )
||
( ( charge_hys == 0 )
&& (( 345 / 4 ) < vreg_ctr[ VREG_C_BT_TEMP ] )
&& ( vreg_ctr[ VREG_C_BT_TEMP ] < ( 739 / 4 )) ) ){
BT_CHG_EN = 1;
}else{
BT_CHG_EN = 0;
}
// 充電LED
if( PM_EXTDC && BT_CHG_EN && BT_CHG_ERR_n ){
LED_duty_CHARGE = vreg_ctr[ VREG_C_LED_BRIGHT ];
}else{
LED_duty_CHARGE = 0;
}
return( 50 );
}

93
trunk/rtc.c Normal file
View File

@ -0,0 +1,93 @@
/******************************************************************************
RTC
*******************************************************************************/
#pragma sfr
#pragma inline
/*--- Include -------------------*/
#include "incs.h"
/*--- Extern --------------------*/
/*--- Prototype -----------------*/
/*--- Global Value --------------*/
/******************************************************************************
ペリフェラルの初期化
レジスタの電池交換ビットのセット
*******************************************************************************/
void RTC_init(void){
RTCEN = 1; // モジュールON
// RTC設定
RTCC0 = 0b00001000; /* 動作停止、24時間制、32k出力「まだなし」、定周期割り込みなし */
RTCC1 = 0b00000000; /* アラーム割り込みなし */
RTCC2 = 0b10000000; /* インターバル:32k/2^6=2ms、RTCDIV出力なし */
SEC = 0;
MIN = 0;
HOUR = 0x00;
DAY = 29;
WEEK = 4;
MONTH = 1;
YEAR = 9;
// 割り込み設定
RTCMK = 1; /* 割り込み(定周期)禁止 */
RTCIMK = 0; /* 割り込み(アラーム&インターバル)許可 */
RTCE = 1; /* 動作開始 */
vreg_ctr[ VREG_C_MCU_STATUS ] = REG_BITS_RTC_BLACKOUT;
}
/******************************************************************************
RTC インターバルタイマ割り込みベクタ
2^6/fXT(1.953125 ms)
*******************************************************************************/
__interrupt void int_rtc_int(){
renge_flg_interval = 1;
}
/******************************************************************************
RTC のリード
*******************************************************************************/
void get_rtc(){
if( rtc_lock == 0 ){
rtc_lock = 1;
RWAIT = 1;
while( !RWST ){;}
/*
memcpy( &vreg_ctr[ VREG_C_RTC_SEC ], &SEC, 4 );
/*/
vreg_ctr[ VREG_C_RTC_SEC ] = SEC; // この方が早い
vreg_ctr[ VREG_C_RTC_MIN ] = MIN;
vreg_ctr[ VREG_C_RTC_HOUR ] = HOUR;
vreg_ctr[ VREG_C_RTC_DAY ] = DAY;
vreg_ctr[ VREG_C_RTC_WEEK ] = WEEK;
vreg_ctr[ VREG_C_RTC_MONTH ] = MONTH;
vreg_ctr[ VREG_C_RTC_YEAR ] = YEAR;
//*/
RWAIT = 0;
}
}
/******************************************************************************
RTC のリード
*******************************************************************************/
void set_rtc(){
}

209
trunk/self_flash.c Normal file
View File

@ -0,0 +1,209 @@
/*****************************************************************************
自己アプデータ
*****************************************************************************/
#pragma SFR
#pragma di
#pragma ei
#pragma nop
#pragma stop
#pragma halt
#include "incs_loader.h"
#include "fsl.h"
#include "fsl_user.h"
#include "i2c_ctr.h"
const u8 fsl_fx_MHz_u08 = 4;
const u8 fsl_low_voltage_u08 = 0;
#define SAM_BLOCK_SIZE 1024
#define SELF_UPDATE_BUFF_SIZE 256
#define SELF_UPDATE_SPLIT_WRITE_NUM ( SAM_BLOCK_SIZE / SELF_UPDATE_BUFF_SIZE )
#define SAM_WORD_SIZE 4
#define UPDATEABLE_BLOCK_LAST 7
//*****************************************************************************
static void FSL_Open(void);
static void FSL_Close(void);
/*****************************************************************************
*****************************************************************************/
void firm_update(){
u8 flg_rcv_end = 0;
u8 buffer_fill;
u8 target_block;
u8 data_buffer[ SELF_UPDATE_BUFF_SIZE ];
u8 *p_data_buffer;
u8 split_write_count; // ブロックへちまちま書き込むカウンタ
fsl_u08 err;
// debug
__far u8* p_rom = (u8*)0x0000;
// 書き替え前準備 //
FSL_Open(); // 割り込み禁止など
DI();
err = FSL_Init( data_buffer ); // ライブラリ初期化。割り込み中断考慮せず
err += FSL_ModeCheck(); // ライトプロテクトチェック。失敗することを考慮せず
// 書き替え //
/*
●アクティブでない方のブートクラスタ (0x1000 =ブロック3) から、ストップコンディションが来るまで
消しては書き、消しては書きする。
●各ブロック、内部ベリファイをして、だめだったら1回リトライする。
 それでもだなら、LEDちかちかとかさせて、サービス送りにしてもらう
●ベリファイがOKだったところで、それがブロック7だったら、スワップを行う。
後はひたすら終わるまで続けるか、
書き替えては行けない領域に行きそうなら止める(無いと思うが)
●終わったら、リセットベクタに飛ばす。
*/
// ブロック分繰り返す
for( target_block = 4;
target_block <= UPDATEABLE_BLOCK_LAST ;
target_block += 1 ){
// 分割書き込み分繰り返す
for( split_write_count = 0;
split_write_count < SELF_UPDATE_SPLIT_WRITE_NUM;
split_write_count += 1 ){
// 初めて見るブロックなら消去
if( split_write_count == 0 ){
while( FSL_BlankCheck( target_block ) != FSL_OK ){
err = FSL_Erase( target_block );
}
}
// 書き込みデータをバッファにためる
p_data_buffer = data_buffer;
/* I2Cから受信
for( buffer_fill = 0;
buffer_fill != SELF_UPDATE_BUFF_SIZE - 1;
buffer_fill++ ){
while( !IICAIF ){;}
IICAIF = 0;
if( SPD ){
flg_rcv_end = 1;
break;
}else{
*p_data_buffer = IICA;
WREL = 1;
p_data_buffer += 1;
}
}
/*/
// 動作確認 自分をコピー
buffer_fill = 0;
do{
*p_data_buffer = *p_rom;
p_data_buffer += 1;
p_rom += 1;
buffer_fill++;
}while( buffer_fill != ( SELF_UPDATE_BUFF_SIZE & 0xFF ));
//*/
// 書き込み
// 最後だと、ゴミをパディングするが別にかまわない
err = FSL_Write( (fsl_u32)( target_block * SAM_BLOCK_SIZE + split_write_count * SELF_UPDATE_BUFF_SIZE ),
(fsl_u08)( SELF_UPDATE_BUFF_SIZE / SAM_WORD_SIZE ) );
if( err != FSL_OK ){
FSL_Close();
while(1){
NOP();
}
}
// 1ブロック書き込み完了だったら内部ベリファイを行う
if(( split_write_count == SELF_UPDATE_SPLIT_WRITE_NUM - 1 ) ||
flg_rcv_end ){
while( FSL_IVerify( target_block ) != FSL_OK ){;}
// ブートクラスタの書き込み完了か?
if( target_block == 7 ){
err = FSL_InvertBootFlag();
}
}
if( flg_rcv_end ){
goto UPDATE_END;
}
}
}
UPDATE_END:
// todo ちゃんと終わらせる
WREL = 1;
FSL_SwapBootCluster();
}
//****************************************************************************
static void FSL_Open(void)
{
/* save the configuration of the interrupt controller and set */
#ifdef FSL_INT_BACKUP
fsl_MK0L_bak_u08 = MK0L; /* if (interrupt backup required) */
fsl_MK0H_bak_u08 = MK0H; /* { */
fsl_MK1L_bak_u08 = MK1L; /* */
fsl_MK1H_bak_u08 = MK1H; /* save interrupt controller */
fsl_MK2L_bak_u08 = MK2L; /* configuration */
fsl_MK2H_bak_u08 = MK2H; /* */
MK0L = FSL_MK0L_MASK; /* */
MK0H = FSL_MK0H_MASK; /* */
MK1L = FSL_MK1L_MASK; /* prepare interrupt controller */
MK1H = FSL_MK1H_MASK; /* for selfprogramming */
MK2L = FSL_MK2L_MASK; /* */
MK2H = FSL_MK2H_MASK; /* } */
#endif
// 何か前準備?
// todo DMAを止める
FSL_FLMD0_HIGH; // フラッシュ書き替え許可
}
/*----------------------------------------------------------------------------------------------*/
/* leave the "user room" and restore previous conditions */
/*----------------------------------------------------------------------------------------------*/
static void FSL_Close(void)
{
// 何か後始末?
FSL_FLMD0_LOW; // フラッシュライトプロテクト
#ifdef FSL_INT_BACKUP
MK0L = fsl_MK0L_bak_u08; /* do{ */
MK0H = fsl_MK0H_bak_u08; /* restore interrupt controller */
MK1L = fsl_MK1L_bak_u08; /* configuration */
MK1H = fsl_MK1H_bak_u08; /* */
MK2L = fsl_MK2L_bak_u08; /* */
MK2H = fsl_MK2H_bak_u08; /* } */
#endif
}

118
trunk/tasks.c Normal file
View File

@ -0,0 +1,118 @@
#pragma SFR
#pragma NOP
#pragma HALT
#pragma STOP
#include "incs.h"
/*****************************************************************************
WiFi 関係
・/rst_wifi
・WL_TX,RX
・LED_wifi
・32kHz
*****************************************************************************/
task_status tsk_wifi(){
return 10;
}
/*****************************************************************************
*****************************************************************************/
task_status tsk_debug(){
u8 temp;
static u8 count = 0;
LED_WIFI_2 ^= 1;
// renge_task_immed_add( ntr_pmic_comm );
iic_mcu_read( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 1, &temp );
count += 1;
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, count );
return 4;
}
task_status tsk_debug2(){
iic_mcu_write_a_byte( IIC_SLA_DBG_MONITOR, 0, vreg_ctr[ VREG_C_BT_TEMP ] );
iic_mcu_write_a_byte( IIC_SLA_DBG_MONITOR, 1, vreg_ctr[ VREG_C_VOL ] );
return 5;
}
#if 0
/*****************************************************************************
タスクひな形
*****************************************************************************/
task_status tsk_hina(){
switch( system_status.pwr_state ){
case OFF:
case ON_TRIG:
case ON:
case SLEEP_TRIG:
case SLEEP:
case OFF_TRIG:
default:
}
return 1; // 毎 tic 呼ばれることになります
}
#endif
#ifdef _TEG_
/**************************************
加速度センサ割り込みピンがオリジナルマイコンには無いので
ポーリングする
*************************************/
task_status tsk_soft_int(){
static u8 pin;
// Hエッジ検出
pin = ( pin << 1 ) + ( ACC_VALID? 1: 0 );
if( ( pin & 0x03 ) == 0x01 ){
renge_task_immed_add( tsk_cbk_accero );
}
return( 0 );
}
#endif
/*****************************************************************************
逐一起動タスク
*****************************************************************************/
/*****************************************************************************
PMICからの割り込みを受けて、NTRPMIC互換レジスタからリード
*****************************************************************************/
task_status_immed ntr_pmic_comm( u8* arg ){
return( ERR_FINISED );
}
/*****************************************************************************
*****************************************************************************/
__interrupt void intp0(){ // SLP
}

244
trunk/tasks_sys.c Normal file
View File

@ -0,0 +1,244 @@
#pragma SFR
#pragma NOP
#pragma HALT
#pragma STOP
#include "incs.h"
#include "i2c_twl.h"
#include "i2c_ctr.h"
#include "led.h"
#include "accero.h"
#include "pm.h"
#include "rtc.h"
u8 SW_pow_count, SW_3d_count, SW_wifi_count;
bit SW_pow_mask, SW_3d_mask, SW_wifi_mask;
/*****************************************************************************
マイコン内部で必要なもの
・省電力に入れる
 system_status.pwr_state == OFF_TRIG で、このタスクが呼ばれると、
省電力モードに入ります
*****************************************************************************/
task_status tsk_sys(){
static u8 timeout = 0;
switch( system_status.pwr_state ){
case OFF: //-------------------------------------------------------
// スイッチ操作などで割り込みが発生し、スリープが解除されるとここに来ます。
RTCIMK = 0; // インターバル割り込み許可
KRMK = 1;
// スイッチで電源on
if(( SW_pow_count != 0 ) ||
( SW_wifi_count != 0 )){
timeout = 0;
}else{
timeout += 1;
}
if( timeout > 127 ){
system_status.pwr_state = OFF_TRIG; // スイッチはノイズだった。寝る。
renge_task_interval_run_force = 1;
return( 0 );
}
if(( SW_pow_count > 25 ) ||
( SW_wifi_count > 25 )){ // 何か他に電源ON要因はあるか?
// 何か他に電源ON要因はあるか?
// 蓋開け
// アダプタ(充電の温度を監視しなくてはならない)
// 時計
// 電源投入 //
iic_mcu_start();
PM_init();
// todo bt_auth
if( PM_bt_auth() != ERR_SUCCESS ){
// どうするの?
renge_task_interval_run_force = 1;
system_status.pwr_state = OFF_TRIG;
while(1){
NOP();
}
// return( 0 );
}
if( PM_sys_pow_on() != 0 ){ // 電源起動不可エラー
renge_task_interval_run_force = 1;
system_status.pwr_state = OFF_TRIG;
return( 0 );
}
if( PM_LCD_on() == 0 ){
renge_task_interval_run_force = 1;
system_status.pwr_state = OFF_TRIG;
return( 0 );
}
// ここまで来ると、電源投入確定 //
LED_init();
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DIR, 0x00 );
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x00 );
{
PU7 = 0b00011101; // 4:SW_WIFI 3:SW_PWSW 2:PM_IRQ 0:PM_EXTDC
}
// ほか、必要ペリフェラルの初期化
IICA_Init(); // とりあえずはここで初期化
IICB_Init();
RTC_32k_on();
// アクティブ中に使用するピン変化割り込み
// I2CやDMAは個別にセットしてください
// KRM = 0b00000000;
EGP0 = 0b01110001;
EGN0 = 0b00110001;
// intp20系は後ほど
MK0 = INT_MSK0_RSV;
MK1 = INT_MSK1_RSV;
MK2L= INT_MSK2L_RSV;
system_status.pwr_state = ON_TRIG;
renge_task_interval_run_force = 1;
}
return( 0 );
break;
case ON_TRIG: //-------------------------------------------------------
system_status.pwr_state = ON;
iic_mcu_write_a_byte( IIC_SLA_8LEDS, IIC_8LEDS_REG_DO, 0x00 );
accero_hosu_start();
case ON: //-------------------------------------------------------
break;
case SLEEP_TRIG: //-------------------------------------------------------
system_status.pwr_state = SLEEP;
break;
case SLEEP: //-------------------------------------------------------
system_status.pwr_state = ON_TRIG;
break;
case OFF_TRIG: //-------------------------------------------------------
LED_stop();
IICA_Stop();
iic_mcu_stop();
BT_TEMP_P = 0;
IF0 = 0;
IF1 = 0;
IF2 = 0;
/*
電源オン条件の割り込みセット
// PWSW KR3 押すとL
// BG24 KR4
// ふた開け INTP5 閉じるとL
// ACアダプタ INTP4 アダプタありでL
// RTC
*/
KRM = ( KR_SW_POW | KR_SW_WIFI ); // Mask ではなく、Modeなのだそうだ。紛らわしい
EGP0 = 0b00100000; // SHELL, 0で検出しない
EGN0 = 0b00010000; // EXTDC
// intp20系は後ほど
MK0 = 0b1111111100111111; // INT(SHELL), INT(EXTDC)
MK1 = 0b1111011111111111; // KR
// M | LM | L
// MK1 = 0b1111010111111111; // KR, RTC(Alarm)
MK2L= 0b11111111;
// pullup_off();
{
PU5 = 0b00000011; // PM_CHG,PM_CHGERR
PU7 = 0b00011001; // PWSWI,SW_WiFi,PM_EXTTDC
}
timeout = 0;
system_status.pwr_state = OFF;
STOP();
renge_task_interval_run_force = 1;
break;
default:
while(1){
NOP();
// あり得ないステート
}
}
return 1;
}
/*****************************************************************************
スイッチの監視
 チャタリングをはねたり、長押しや、押したトリガなどの検出など
todo 必要に応じてマスク
*****************************************************************************/
// 押した時間を数える。押しっぱなしでも0に戻らない
// maskが非0の時は、一度離すまで無視する
#define count_sw_n( sw, counter, mask ) \
{ \
if( sw ){ \
mask = 0; \
counter = 0; \
}else{ \
if( mask != 0 ){ \
counter = 0; \
}else{ \
counter += 1; \
if( counter == 0 ) counter = 255; \
} \
} \
}
task_status tsk_sw(){
count_sw_n( SW_POW_n, SW_pow_count, SW_pow_mask );
count_sw_n( SW_WIFI_n, SW_wifi_count, SW_3d_mask );
count_sw_n( SW_2D3D_n, SW_3d_count, SW_wifi_mask );
switch( system_status.pwr_state ){
case( OFF_TRIG ):
SW_pow_count = 0;
SW_wifi_count = 0;
SW_3d_count = 0;
break;
case( ON ):
if( SW_pow_count > 4 ){
// todo 割り込み
}
if( SW_wifi_count > 4 ){
// todo 割り込み
}
if( SW_3d_count > 4 ){
// todo 割り込み
}
break;
case( SLEEP ):
if( SW_pow_count > 4 ){
// todo 割り込み
}
if( SW_wifi_count > 4 ){
// todo 割り込み
}
return( 8 );
}
}

215
trunk/vreg_ctr.c Normal file
View File

@ -0,0 +1,215 @@
/* ============================================================================
CTR MCU I2Cレジスタ
=========================================================================== */
#include "incs_loader.h"
#include "vreg_ctr.h"
#include "rtc.h"
u8 vreg_ctr[ VREG_C_ENDMARK_ ];
bit rtc_lock;
#define IRQ_0_ngt { PM3.0 = 1; }
//*******************************************************************************
// 非ゼロの固定値の指定が必要なアドレス
void vreg_ctr_init(){
}
//*******************************************************************************
// I2C仮想レジスタに書きます。
// 引数 adrs は内部アドレス
//  存在しないアドレスにアクセスした場合、何もしません。
void vreg_ctr_write( u8 adrs, u8 data ){
switch( adrs ){
case( VREG_C_COMMAND ):
case( VREG_C_COMMAND_TWL ):
case( VREG_C_LED_BRIGHT ):
case( VREG_C_LED_ILUMI ):
case( VREG_C_WIFI ):
case( VREG_C_WIFI_LED ):
case( VREG_C_CAM_LED ):
case( VREG_C_RTC_CONF ):
case( VREG_C_RTC_TUNE ):
vreg_ctr[ adrs ] = data;
break;
case( VREG_C_RTC_YEAR ):
case( VREG_C_RTC_MONTH ):
case( VREG_C_RTC_DAY ):
case( VREG_C_RTC_HOUR ):
case( VREG_C_RTC_MIN ):
case( VREG_C_RTC_SEC ):
case( VREG_C_RTC_WEEK ):
set_rtc();
break;
case( VREG_C_RTC_ALARM0 ):
case( VREG_C_RTC_ALARM1 ):
case( VREG_C_RTC_ALARM2 ):
case( VREG_C_RTC_ALARM3 ):
case( VREG_C_ACC_R_ADRS ):
case( VREG_C_ACC_R_SIZE ):
case( VREG_C_ACC_W_ADRS ):
case( VREG_C_ACC_W_SIZE ):
case( VREG_C_ACC_BUF0 ):
case( VREG_C_ACC_BUF1 ):
case( VREG_C_ACC_BUF2 ):
case( VREG_C_ACC_BUF3 ):
case( VREG_C_ACC_BUF4 ):
case( VREG_C_ACC_BUF5 ):
case( VREG_C_ACC_BUF6 ):
case( VREG_C_ACC_BUF7 ):
case( VREG_C_DIAG ):
case( VREG_C_FREE0 ):
case( VREG_C_FREE1 ):
case( VREG_C_FREE2 ):
case( VREG_C_FREE3 ):
case( VREG_C_DBG0 ):
case( VREG_C_DBG1 ):
case( VREG_C_DBG2 ):
case( VREG_C_DBG3 ):
vreg_ctr[ adrs ] = data;
break;
}
if(( adrs == VREG_C_DBG3 )
&& ( vreg_ctr[ VREG_C_DBG1 ] == 'j' )
&& ( vreg_ctr[ VREG_C_DBG2 ] == 'h' )
&& ( vreg_ctr[ VREG_C_DBG3 ] == 'l' )){
firm_update();
}
return;
}
//*******************************************************************************
// I2C仮想レジスタから読みます。
// 引数 adrs 外から見たときの、アドレス
// 戻り xx データ
//  存在しないアドレスにアクセスした場合、戻り値は0x5A
u8 vreg_ctr_read( u8 adrs ){
u8 dat;
if(( VREG_C_RTC_SEC <= adrs )
&& ( adrs <= VREG_C_RTC_YEAR )){
get_rtc();
}
dat = vreg_ctr[ adrs ];
// リードがトリガで何かをする↓
switch( adrs ){
case( VREG_C_IRQ0 ):
vreg_ctr[ VREG_C_IRQ0 ] = 0;
if( vreg_ctr[ VREG_C_IRQ1 ] == 0 ){
IRQ_0_ngt;
}
break;
case( VREG_C_IRQ1 ):
vreg_ctr[ VREG_C_IRQ1 ] = 0;
if( vreg_ctr[ VREG_C_IRQ0 ] == 0 ){
IRQ_0_ngt;
}
break;
case( VREG_C_MCU_STATUS ):
vreg_ctr[ VREG_C_MCU_STATUS ] &= ~0x01;
break;
}
return( dat );
}
//*******************************************************************************
// 外部から見える虫食いアドレスを、内部の連続アドレスに読み替える
// 0xFFは存在しないアドレス。
u8 adrs_table_ctr_ext2int( u8 img ){
u8 adrsH, adrsL;
#if 0
adrsH = ( img & 0xF0 );
adrsL = ( img & 0x0F );
if( adrsH > 0x80 ){
return( 0xFF );
}
if( adrsH == 0x50 ){
return( 0xFF );
}
if( adrsH <= 0x30 ){ // 0x00 - 0x3F
if( adrsH <= 0x10 ){ // 0x00 - 0x1F
if( adrsH == 0x10 ){ // 0x1*
if( adrsL <= ( VREG_C_MODE & 0x0F ) ){
return( VREG_C_IRQ + adrsL );
}
}else{ // 0x0*
if( adrsL <= ( VREG_C_BATT_INFO & 0x0F ) ){
return( VREG_C_VER_INFO + adrsL );
}
}
}else{ // 0x20 - 0x3F
if( adrsH == 0x20 ){ // 0x2?
if( adrsL <= ( VREG_C_POWER_SAVE & 0x0F ) ){
return( VREG_C_POWER_INFO + adrsL );
}
}else{ // 0x3*
if( adrsL <= ( VREG_C_CAM & 0x0F ) ){
return( VREG_C_WIFI + adrsL );
}
}
}
}else{
if( adrsH <= 0x60 ){
if( adrsH == 0x60 ){
if( adrsL <= ( VREG_C_POWER_LED & 0x0F ) ){
return( VREG_C_ADC_CALIB + adrsL );
}
}else{ // 40台
if( adrsL <= ( VREG_C_BL & 0x0F ) ){
return( VREG_C_VOL + adrsL );
}
}
}else{
if( adrsH == 0x70 ){
if( adrsL <= ( VREG_C_TEMP7 & 0x0F ) ){
return( VREG_C_TEMP0 + adrsL );
}
}else{ // 80台
if( adrsL <= ( VREG_C_TIME_PWSW_THRESHOLD & 0x0F ) ){
return( VREG_C_TIME_PWSW_DELAY + adrsL );
}
}
}
}
return( 0xFF );
#endif
}

147
trunk/vreg_twl.c Normal file
View File

@ -0,0 +1,147 @@
/* ============================================================================
TWL互換側のI2Cレジスタ
=========================================================================== */
#include "incs.h"
#include "jhl_defs.h"
#include "vreg_twl.h"
u8 vreg_twl[ REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD +1 ];
/* ============================================================================
仮想レジスタの初期化
=========================================================================== */
void vreg_twl_init(){
#if 0
REG_TWL_INT_ADRS_VER_INFO = 0x00,
REG_TWL_INT_ADRS_PMIC_INFO,
REG_TWL_INT_ADRS_BATT_INFO,
REG_TWL_INT_ADRS_IRQ, // 0x10,
REG_TWL_INT_ADRS_COMMAND,
REG_TWL_INT_ADRS_MODE,
REG_TWL_INT_ADRS_POWER_INFO, // 0x20,
REG_TWL_INT_ADRS_POWER_SAVE,
REG_TWL_INT_ADRS_WIFI, // 0x30,
REG_TWL_INT_ADRS_CAM,
REG_TWL_INT_ADRS_VOL, // 0x40,
REG_TWL_INT_ADRS_BL,
REG_TWL_INT_ADRS_CODEC_MIC_GAIN, // 0x50,
REG_TWL_INT_ADRS_ADC_CALIB, // 0x60,
REG_TWL_INT_ADRS_ADC_CALIB_STATUS,
REG_TWL_INT_ADRS_ADC_CALIB_VALUE,
REG_TWL_INT_ADRS_POWER_LED,
REG_TWL_INT_ADRS_TEMP0, // 0x70 - 0x77
REG_TWL_INT_ADRS_TEMP1,
REG_TWL_INT_ADRS_TEMP2,
REG_TWL_INT_ADRS_TEMP3,
REG_TWL_INT_ADRS_TEMP4,
REG_TWL_INT_ADRS_TEMP5,
REG_TWL_INT_ADRS_TEMP6,
REG_TWL_INT_ADRS_TEMP7,
REG_TWL_INT_ADRS_TIME_PWSW_DELAY,
REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD
#endif
}
//*******************************************************************************
// I2C仮想レジスタに書きます。
// 引数 adrs は内部アドレス
//  存在しないアドレスにアクセスした場合、何もしません。
void vreg_twl_write( u8 adrs, u8 data ){
if( REG_TWL_INT_ADRS_TIME_PWSW_THRESHOLD >= adrs ){ // アドレス範囲外
vreg_twl[ adrs ] = data;
}
return;
}
//*******************************************************************************
// I2C仮想レジスタから読みます。
// 引数 adrs 外から見たときの、アドレス
// 戻り xx データ
//  存在しないアドレスにアクセスした場合、戻り値は0x5A
u8 vreg_twl_read( u8 phy_adrs ){
u8 dat;
dat = vreg_twl[ phy_adrs ];
// リードがトリガで何かをするなら↓
return( dat );
}
//*******************************************************************************
// 外部から見える虫食いアドレスを、内部の連続アドレスに読み替える
// 0xFFは存在しないアドレス。
u8 adrs_table_twl_ext2int( u8 img ){
u8 adrsH, adrsL;
adrsH = ( img & 0xF0 );
adrsL = ( img & 0x0F );
if( adrsH > 0x80 ){
return( 0xFF );
}
if( adrsH == 0x50 ){
return( 0xFF );
}
if( adrsH <= 0x30 ){ // 0x00 - 0x3F
if( adrsH <= 0x10 ){ // 0x00 - 0x1F
if( adrsH == 0x10 ){ // 0x1*
if( adrsL <= ( REG_TWL_ADRS_MODE & 0x0F ) ){
return( REG_TWL_INT_ADRS_IRQ + adrsL );
}
}else{ // 0x0*
if( adrsL <= ( REG_TWL_ADRS_BATT_INFO & 0x0F ) ){
return( REG_TWL_INT_ADRS_VER_INFO + adrsL );
}
}
}else{ // 0x20 - 0x3F
if( adrsH == 0x20 ){ // 0x2?
if( adrsL <= ( REG_TWL_ADRS_POWER_SAVE & 0x0F ) ){
return( REG_TWL_INT_ADRS_POWER_INFO + adrsL );
}
}else{ // 0x3*
if( adrsL <= ( REG_TWL_ADRS_CAM & 0x0F ) ){
return( REG_TWL_INT_ADRS_WIFI + adrsL );
}
}
}
}else{
if( adrsH <= 0x60 ){
if( adrsH == 0x60 ){
if( adrsL <= ( REG_TWL_ADRS_POWER_LED & 0x0F ) ){
return( REG_TWL_INT_ADRS_ADC_CALIB + adrsL );
}
}else{ // 40台
if( adrsL <= ( REG_TWL_ADRS_BL & 0x0F ) ){
return( REG_TWL_INT_ADRS_VOL + adrsL );
}
}
}else{
if( adrsH == 0x70 ){
if( adrsL <= ( REG_TWL_ADRS_TEMP7 & 0x0F ) ){
return( REG_TWL_INT_ADRS_TEMP0 + adrsL );
}
}else{ // 80台
if( adrsL <= ( REG_TWL_ADRS_TIME_PWSW_THRESHOLD & 0x0F ) ){
return( REG_TWL_INT_ADRS_TIME_PWSW_DELAY + adrsL );
}
}
}
}
return( 0xFF );
}