ctr_mcu/trunk/accero.c

272 lines
8.6 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

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.

/* ========================================================
 加速度センサ関係
・データ更新完了でデータを吸い上げ手レジスタを更新、CPUに割り込み
・フラグが立っていれば歩数カウント
・加速度センサ割り込みからタスクを登録して下さい。I2Cの競合回避などがあるので
======================================================== */
#pragma SFR
#pragma NOP
#pragma HALT
#pragma STOP
#pragma ROT
// rorb, rolb, rorw, rolw
#pragma MUL
#include "incs.h"
#include <math.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
#define VREG_BITMASK_ACC_CONF_HOSU ( 1 << 1 )
#define VREG_BITMASK_ACC_CONF_ACQ ( 1 << 0 )
// ========================================================
extern u8 pool[];
u16* hyst_pedometer;
// ========================================================
task_interval tsk_soft_int( );
/* ========================================================
 ・割り込みを確認してデータを吸い上げ、レジスタに書き出します
・本当であればコールバック関数を登録しておけばいいじゃんとなるのですが、
I2Cが使用中だったらとか考えると私ではそこまでできないのです。
・自動歩数計とかでも結局
======================================================== */
task_status_immed tsk_cbk_accero( )
{ // 疑似isrから登録されます
if( system_status.pwr_state == ON )
{
// 加速度センサデータレジスタへの反映
iic_mcu_read( IIC_SLA_ACCEL, ( ACC_REG_X | 0x80 ), 6, &vreg_ctr[VREG_C_ACC_XL] );
if( ( vreg_ctr[VREG_C_ACC_CONFIG] &
( VREG_BITMASK_ACC_CONF_ACQ | VREG_BITMASK_ACC_CONF_HOSU ) ) != 0 )
{
set_irq( VREG_C_IRQ1, REG_BIT_ACC_DAT_RDY );
}
}
// 歩数計 /////////////////////////////////////////////
// offでなければ、電源off中でも計測
// if( ( vreg_ctr[VREG_C_ACC_CONFIG] & VREG_BITMASK_ACC_CONF_HOSU ) != 0x00 )
if( 1 )
{
static s16 th_H = 0x3500; // 閾値。暫定。動的変更とかしたい…
static s16 th_L = 0x2A00;
static u16 acc_norm[3]; // 加速度の大きさのヒストリ。数字が大きい方が古い
static u8 direction; // (0)極大を待つか (1)極小を待つか
static u16 interval; // 山と谷の間の時間。短すぎても長すぎてもはじく。
u16 sx16 = abs( (u16)vreg_ctr[VREG_C_ACC_XH] * 256 + vreg_ctr[VREG_C_ACC_XL] );
u16 sy16 = abs( (u16)vreg_ctr[VREG_C_ACC_YH] * 256 + vreg_ctr[VREG_C_ACC_YL] );
u16 sz16 = abs( (u16)vreg_ctr[VREG_C_ACC_ZH] * 256 + vreg_ctr[VREG_C_ACC_ZL] );
acc_norm[2] = acc_norm[1];
acc_norm[1] = acc_norm[0];
// そのうちローコストな方法を考える、かも
acc_norm[0] = sqrt( (long)sx16 * ( sx16 / 2 ) +
(long)sy16 * ( sy16 / 2 ) +
(long)sz16 * ( sz16 / 2 ) );
if( direction == 0 ) // 前回は谷
{
if( acc_norm[2] <= acc_norm[1] && acc_norm[1] > acc_norm[0]
&& acc_norm[0] > th_H ) // 極大で、閾値を超えていた
{
direction = 1; // 極小を待つ
interval = 0; // 極小までの時間を計る
}
}
else
{
if( acc_norm[2] >= acc_norm[1] && acc_norm[1] < acc_norm[0]
&& acc_norm[0] < th_L )
{
direction = 0;
if( 2 < interval && interval < 20 ) // 早すぎず、遅すぎず
{
// 一歩加算。 いろいろ失敗した
if( ++vreg_ctr[ VREG_C_ACC_HOSU_L ] == 0 )
{
if( ++vreg_ctr[ VREG_C_ACC_HOSU_M ] == 0 )
{
++vreg_ctr[ VREG_C_ACC_HOSU_H ];
}
}
if( ++*hyst_pedometer == 0 )
{
*hyst_pedometer = 65535;
}
}
interval = 0;
}
interval += 1;
}
}
return ( ERR_SUCCESS );
}
/*=========================================================
 加速度センサ透過アクセス リード
========================================================*/
task_status_immed acc_read( )
{
vreg_ctr[VREG_C_ACC_W_BUF] = iic_mcu_read_a_byte( IIC_SLA_ACCEL, vreg_ctr[VREG_C_ACC_R_ADRS] );
// vreg_ctr[ VREG_C_ACC_R_BUF ] = iic_mcu_read_a_byte( IIC_SLA_ACCEL, vreg_ctr[VREG_C_ACC_R_ADRS] );
vreg_ctr[VREG_C_IRQ1] |= REG_BIT_ACC_ACK;
if( ( vreg_ctr[VREG_C_IRQ_MASK1] & REG_BIT_ACC_ACK ) == 0 )
{
IRQ0_ast;
}
return ( ERR_SUCCESS );
}
/*=========================================================
 加速度センサ透過アクセス ライト
========================================================*/
task_status_immed acc_write( )
{
iic_mcu_write_a_byte( IIC_SLA_ACCEL, vreg_ctr[VREG_C_ACC_W_ADRS], vreg_ctr[VREG_C_ACC_W_BUF] );
vreg_ctr[VREG_C_IRQ1] |= REG_BIT_ACC_ACK;
if( ( vreg_ctr[VREG_C_IRQ_MASK1] & REG_BIT_ACC_ACK ) == 0 )
{
IRQ0_ast;
}
return ( ERR_SUCCESS );
}
/*=========================================================
 自動歩数カウントモードにセット
todo 他のモードだったら止めたり、復帰させたり
割り込みルーチンなどでカウント判定が必要
========================================================*/
task_status_immed acc_hosu_set( )
{
u8 str_send_buf[4];
iic_mcu_read_a_byte( IIC_SLA_ACCEL, ACC_REG_WHOAMI );
if( iic_mcu_bus_status == ERR_NOSLAVE )
{
vreg_ctr[ VREG_C_STATUS_1 ] |= 0x02;
#ifdef _MCU_BSR_
// PMK23 = 1;
#endif
return ( ERR_SUCCESS ); // とりあえず、タスクは削除しなくてはならない
}else{
vreg_ctr[ VREG_C_STATUS_1 ] &= ~0x02;
}
str_send_buf[1] = 0x00; // ctrl2 HPF:normal, filterd, HPF for IRQ : dis/dis, HPF coeff:norm
#ifdef _MODEL_WM0_
str_send_buf[2] = 0x10; // 3 IRQ pol :Active HI, Drive:Pushpull,
/// IRQ2flg latch: auto clear after read, IRQ2 conf: IRQ( fall,shock,...)
/// 1 : auto clear after read, conf: data ready
#else
str_send_buf[2] = 0x02; // 3 IRQ pol :Active HI, Drive:Pushpull,
/// IRQ2flg latch: auto clear after read, IRQ2 conf: IRQ( fall,shock,...)
/// 1 : auto clear after read, conf: data ready
#endif
str_send_buf[3] = 0x80; // ctrl3 block update:enable, MSB first, scale: +-2G(default), selftest: dis
if( ( vreg_ctr[VREG_C_ACC_CONFIG] &
( VREG_BITMASK_ACC_CONF_HOSU | VREG_BITMASK_ACC_CONF_ACQ ) ) == 0 )
{
#ifdef _MCU_BSR_
PMK23 = 1;
#endif
// 完全停止
str_send_buf[0] =
( ACC_BITS_PM_PDN << ACC_bP_PM0 | 0 << ACC_bP_DR0 | ACC_BITS_ALL_AXIS_ON );
hyst_pedometer = (u16*)pool; // 止めるとヒストリが無効になります(暫定)
}
else
{
#ifdef _MCU_BSR_
PMK23 = 0;
#endif
// 100Hz 自動取り込み
str_send_buf[0] =
( ACC_BITS_PM_NORM << ACC_bP_PM0
| ACC_BITS_DR_100Hz << ACC_bP_DR0
| ACC_BITS_ALL_AXIS_ON );
}
iic_mcu_write( IIC_SLA_ACCEL, ( ACC_REG_CTRL1 | 0x80 ), 4, str_send_buf );
// カラ読み
if( ACC_VALID == 1 )
{
if( system_status.pwr_state == ON )
{
renge_task_immed_add( tsk_cbk_accero );
}
}
return ( ERR_SUCCESS );
}
/* ========================================================
加速度センサ割り込み
I2Cが使用中かもしれないので、読み出しタスクの登録を行うのみ
======================================================== */
__interrupt void intp23_ACC_ready( )
{
if( ( vreg_ctr[VREG_C_ACC_CONFIG] & 0x03 ) != 0x00 )
{
if( ( system_status.pwr_state == ON ) || ( system_status.pwr_state == SLEEP ) )
{
if( ACC_VALID )
{
renge_task_immed_add( tsk_cbk_accero );
}
}
}
}