概要
Arduinoで、ステートマシーンを使ってファンクションデコーダを設計中
12FXもあるので、OPPのクラスを使って設計中
なんとなく、仮想関数を使ってみた。
動作
・LEDのグループ
・常時点灯モード
・Forward/Reverseによる区別
・調光を実装
今後
Forward/Reverseによる調光で混乱中(^^;
シーケンス点灯を実装
StateMachine.cpp
# include "Arduino.h"
# include "StateMachine.h"
//#include "ini.h"
# include "define.h"
# include "NmraDcc.h"
extern uint8_t g_Direction;
extern uint8_t g_SpeedRef;
// コンストラクタ(初期化処理)
state_machine::state_machine(uint8_t fn, uint8_t og, uint8_t fc, uint8_t di, uint8_t st) // fn:gState_F1 og:gCV35_OL fc:gCV49_FC di:gCV112_FC st:gCV126_FC
{
FunctionCommand = fn;
FunctionGroup = og;
FunctionConfig = fc;
Dimm = di;
SpeedThreshold = st;
state = ST_IDLE;
}
void state_machine::StateCheck()
{
static l_Dir;
switch(state){
case ST_NONE:
break;
case ST_IDLE:
if(FunctionConfig & ALWAYS){ // 常に点灯ビットon?
state = ST_ALWAYSON;
break;
}
if(FunctionCommand > 0) { // F1 = ON?
if(FunctionConfig & DIRCON) { // For/Rev 有効フラグ?
if(FunctionConfig & FORREV) { // Reverse ?
if( g_Direction == REVERSE){ // Reverse 後進(DCS50Kで確認)
if(FunctionConfig & DIMCON) { // 調光あり?
state = ST_RUN_Lo;
} else {
state = ST_RUN_Hi;
}
}
} else {
if( g_Direction == FORWARD ){ // Forward 前進
state = ST_RUN;
}
}
}
state = ST_RUN;
}
break;
case ST_ALWAYSON: // 常に点灯処理
high();
state = ST_NONE;
break;
case ST_RUN_Lo:
l_Dir = g_Direction; // 現在のFor/Revを記録
dimming(Dimm & 0x0f);
state = ST_RUN_Lo_STAY;
break;
case ST_RUN_Lo_STAY: // 調光あり状態
if( g_SpeedRef > SpeedThreshold ){
state = ST_RUN_Hi;
break;
}
if(FunctionConfig & DIRCON) { // For/Rev 有効フラグ?
if(FunctionConfig & FORREV) { // Reverse ?
state = ST_RSTAY;
} else {
state = ST_FSTAY;
}
} else {
state = ST_STAY;
}
break;
case ST_RUN_Hi: // 今んところ点灯するだけ
high();
if(FunctionConfig & DIRCON) { // For/Rev 有効フラグ?
if(FunctionConfig & FORREV) { // Reverse ?
state = ST_RSTAY;
} else {
state = ST_FSTAY;
}
} else {
state = ST_STAY;
}
break;
case ST_FSTAY: // 前進点灯状態
if( g_Direction == 0 ){ // Reverse 後進(DCS50Kで確認)
state = ST_STOP;
}
if( FunctionCommand == 0 ) {
state = ST_STOP;
}
break;
case ST_RSTAY: // 後進点灯状態
if( g_Direction > 0){ // Forward 前進
state = ST_STOP;
}
if( FunctionCommand == 0 ) {
state = ST_STOP;
}
break;
case ST_STAY:
if( FunctionCommand == 0 ) {
state = ST_STOP;
}
break;
case ST_STOP:
low();
state = ST_IDLE;
break;
default:
break;
}
}
void state_machine::low(){};
void state_machine::high(){};
void state_machine::dimming(uint8_t){};
StateMachine.h
# ifndef _STATEMACHINE_H_
# define _STATEMACHINE_H_
// クラスの定義
class state_machine {
enum{
ST_NONE = 0,
ST_IDLE,
ST_ALWAYSON, // 常に点灯
ST_ALWATSON_STAY,
ST_RUN,
ST_RUN_Lo, // low点灯
ST_RUN_Lo_STAY,
ST_RUN_Hi, // high点灯
ST_RUN_Hi_STAY,
ST_STAY, // 点灯状態を保持
ST_FSTAY, // 前進保持
ST_RSTAY, // 後進保持
ST_STOP // 消灯
};
private:
uint8_t state;
uint8_t FunctionConfig;
uint8_t FunctionCommand;
uint8_t Direction;
uint8_t cnt;
uint8_t FuncPort;
uint8_t Dimm;
virtual void low();
virtual void high();
virtual void dimming(uint8_t);
public:
uint8_t FunctionGroup;
state_machine(uint8_t og, uint8_t fc, uint8_t fn, uint8_t di, uint8_t st,uint8_t dr );
void StateCheck();
};
# endif// _STATEMACHINE_H_
fnf-3.h
//
// Forward Headlight,Function 1,2,3 のグループ
// Bi1 PWM , Bi2 PWM , AUX1 PWM , AUX2 PWM , AUX3 PWM
// 速度のイベントが設定できるグループ
//
# ifndef _FNF3_H_
# define _FNF3_H_
# include "StateMachine.h"
# include "define.h"
//uint8_t dimm[16]={0, 17, 34, 51, 68, 85, 102, 119, 136, 153, 170, 187, 204, 221, 238, 255};
uint8_t DIMMx[16]={0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd , 0xee, 0xff};
class CFnf_3 : public state_machine{
private:
void low();
void high();
void dimming(uint8_t);
public:
CFnf_3(uint8_t og, uint8_t fc, uint8_t fn , uint8_t di, uint8_t dr ):state_machine(og,fc,fn,di,dr){};
};
void CFnf_3::low()
{
if(FunctionGroup & 0x01)
digitalWrite(Bi1,LOW);
if(FunctionGroup & 0x02)
digitalWrite(Bi2,LOW);
if(FunctionGroup & 0x04)
digitalWrite(AUX1,LOW);
if(FunctionGroup & 0x08)
digitalWrite(AUX2,LOW);
if(FunctionGroup & 0x10)
digitalWrite(AUX3,LOW);
if(FunctionGroup & 0x20)
digitalWrite(AUX4,LOW);
if(FunctionGroup & 0x40)
digitalWrite(AUX5,LOW);
if(FunctionGroup & 0x80)
digitalWrite(AUX6,LOW);
}
void CFnf_3::high()
{
if(FunctionGroup & 0x01)
digitalWrite(Bi1,HIGH);
if(FunctionGroup & 0x02)
digitalWrite(Bi2,HIGH);
if(FunctionGroup & 0x04)
digitalWrite(AUX1,HIGH);
if(FunctionGroup & 0x08)
digitalWrite(AUX2,HIGH);
if(FunctionGroup & 0x10)
digitalWrite(AUX3,HIGH);
if(FunctionGroup & 0x20)
digitalWrite(AUX4,HIGH);
if(FunctionGroup & 0x40)
digitalWrite(AUX5,HIGH);
if(FunctionGroup & 0x80)
digitalWrite(AUX6,HIGH);
}
void CFnf_3::dimming(uint8_t di)
{
if(FunctionGroup & 0x01)
analogWrite(Bi1,DIMMx[di]); // analog
if(FunctionGroup & 0x02)
analogWrite(Bi2,DIMMx[di]); // analog
if(FunctionGroup & 0x04)
analogWrite(AUX1,DIMMx[di]); // analog
if(FunctionGroup & 0x08)
analogWrite(AUX2,DIMMx[di]); // analog
if(FunctionGroup & 0x10)
analogWrite(AUX3,DIMMx[di]); // analog
if(FunctionGroup & 0x20)
analogWrite(AUX4,DIMMx[di]); // analog
if(FunctionGroup & 0x40)
digitalWrite(AUX5,DIMMx[di]); // digital
if(FunctionGroup & 0x80)
digitalWrite(AUX6,DIMMx[di]); // digital
}
# endif // _FNF3_H_
ini.h
//http://www.bitsavers.org/pdf/chromatics/CGC_7900_C_Programmers_Manual_Mar82.pdf
//https://www.nmra.org/sites/default/files/standards/sandrp/pdf/s-9.2.2_decoder_cvs_2012.07.pdf
//http://www.snjpn.com/ngdcc/docs/DF19x4bp_CVLIST.pdf
uint8_t gCV1_SAddr = 3;
uint8_t gCV7_ManVer = 0; // Manufacturer Version No.
uint8_t gCV8_ManId = 0x0d; // Manufactured ID : Public Domain & Do-It-Yourself Decoders
// +--------0:Mulifunction Decoder 1:Accessory Decoder
// |+-------0:
// ||+------0:2digit address 1:4digt address
// |||+-----0:speed table off 1:speed table on
// ||||+----
// |||||+---0:analog off 1:analog on
// ||||||+--0:14step 1:28/9128step
// |||||||+-0:normal 1:reversed
uint8_t gCV29 = 0b10000000;
// CV33-46 Output Location(グループ)
// (MSB)edcba987654321(LSB)
// 87654321
uint8_t gCV33_OL = 0b00000001; // Forward Headlinght FL(f)
uint8_t gCV34_OL = 0b00000010; // Reverse Headlinght FL(r)
uint8_t gCV35_OL = 0b00000100; // Function 1
uint8_t gCV36_OL = 0b00001000; // Function 2
uint8_t gCV37_OL = 0b00010000; // Function 3
// ba987654
uint8_t gCV38_OL = 0b00000100; // Function 4
uint8_t gCV39_OL = 0b00001000; // Function 5
uint8_t gCV40_OL = 0b00010000; // Function 6
uint8_t gCV41_OL = 0b00100000; // Function 7
uint8_t gCV42_OL = 0b01000000; // Function 8
// edcba987
uint8_t gCV43_OL = 0b00010000; // Function 9
uint8_t gCV44_OL = 0b00100000; // Function 10
uint8_t gCV45_OL = 0b01000000; // Function 11
uint8_t gCV46_OL = 0b10000000; // Function 12
// CV47- Function Config
//
// +--------0x80 0:fb3 1001:patern10 , 1010:patern11 , 1011:patern12 , 1100:patern13 , 1101:14 , 1110:15, 1111:patern16パンタスパーク
// |+-------0x40 0:fb2 0101:patern6 , 0110:patern7 , 0111:patern8 , 1000:patern9
// ||+------0x20 0:fb1 0001:patern2 , 0010:patern3 , 0011:patern4 , 0100:patern5
// |||+-----0x10 0:fb0 0000:patern1
// ||||+----0x08 0:Event調光無効 1:Event調光有効
// |||||+---0x04 0:Disable 1:enable (方向制御For/Rev)
// ||||||+--0x02 0:Forward 1:Reverse
// |||||||+-0x01 0:normal 1:常に点灯
// ||||||||
uint8_t gCV47_FC = 0b00000000; // Forward Headlinght FL(f)
uint8_t gCV48_FC = 0b00000000; // Reverse Headlinght FL(f)
uint8_t gCV49_FC = 0b00000000; // Function 1
uint8_t gCV50_FC = 0b00000000; // Function 2
uint8_t gCV51_FC = 0b00000000; // Function 3
uint8_t gCV52_FC = 0b00000000; // Function 4
uint8_t gCV53_FC = 0b00000000; // Function 5
uint8_t gCV54_FC = 0b00000000; // Function 6
uint8_t gCV55_FC = 0b00000000; // Function 7
uint8_t gCV56_FC = 0b00000000; // Function 8
uint8_t gCV57_FC = 0b00000000; // Function 9
uint8_t gCV58_FC = 0b00000000; // Function 10
uint8_t gCV59_FC = 0b00000000; // Function 11
uint8_t gCV60_FC = 0b00000000; // Function 12
// 0x80 PTNB3
// 0x40 PTNB2
// 0x20 PTNB1
// 0x10 PTNB0
// 0x08 DIMCON
// 0x04 DIRCON
// 0x02 FORREV
// 0x01 ALWAYS
// +--------0:Db3
// |+-------0:Db2
// ||+------0:Db1
// |||+-----0:Db0 Event側 調光 (0000-1111) 16段階
// ||||+----0:Db3
// |||||+---0:Db2
// ||||||+--0:Db1
// |||||||+-0:Db0 Normal側 調光 (0000-1111) 16段階
// ||||||||
uint8_t gCV112_FC = 0b00000000; // Forward Headlinght FL(f)
uint8_t gCV113_FC = 0b00000000; // Reverse Headlinght FL(f)
uint8_t gCV114_FC = 0b00000000; // Function 1
uint8_t gCV115_FC = 0b00000000; // Function 2
uint8_t gCV116_FC = 0b00000000; // Function 3
uint8_t gCV117_FC = 0b00000000; // Function 4
uint8_t gCV118_FC = 0b00000000; // Function 5
uint8_t gCV119_FC = 0b00000000; // Function 6
uint8_t gCV120_FC = 0b00000000; // Function 7
uint8_t gCV121_FC = 0b00000000; // Function 8
uint8_t gCV122_FC = 0b00000000; // Function 9
uint8_t gCV123_FC = 0b00000000; // Function 10
uint8_t gCV124_FC = 0b00000000; // Function 11
uint8_t gCV125_FC = 0b00000000; // Function 12
// +--------0:
// |+-------0:
// ||+------0:
// |||+-----0:
// ||||+----0:Sb3
// |||||+---0:Sb2
// ||||||+--0:Sb1
// |||||||+-0:Sb0 速度閾値 (0000-1111) 16段階 Threshold
// ||||||||
uint8_t gCV126_FC = 0b00000000; // Forward Headlinght FL(f)
uint8_t gCV127_FC = 0b00000000; // Reverse Headlinght FL(f)
uint8_t gCV128_FC = 0b00000000; // Function 1
uint8_t gCV129_FC = 0b00000000; // Function 2
uint8_t gCV130_FC = 0b00000000; // Function 3
uint8_t gCV131_FC = 0b00000000; // Function 4
uint8_t gCV132_FC = 0b00000000; // Function 5
uint8_t gCV133_FC = 0b00000000; // Function 6
uint8_t gCV134_FC = 0b00000000; // Function 7
uint8_t gCV135_FC = 0b00000000; // Function 8
uint8_t gCV136_FC = 0b00000000; // Function 9
uint8_t gCV137_FC = 0b00000000; // Function 10
uint8_t gCV138_FC = 0b00000000; // Function 11
uint8_t gCV139_FC = 0b00000000; // Function 12
//FX効果
//Cmd,Time,Val
//I:初期状態,O:出力,S:スイープ,L:ループ,E:終了
uint8_t ptn1[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn2[10][3]={{'I',0,5},{'S',100,255},{'E',0,255}}; //10ms もやっと点灯
uint8_t ptn3[10][3]={{'I',0,5},{'S',50,255},{'S',50,5},{'L',0,5}}; //10ms 三角波
uint8_t ptn4[10][3]={{'I',0,0},{'O',10,255},{'O',10,125},{'O',10,255},{'O',10,80},{'L',0,0}}; // ランダム
uint8_t ptn5[10][3]={{'I',0,0},{'S',50,255},{'S',50,0},{'S',50,128},{'S',50,0},{'L',0,0}};//マーズライト
uint8_t ptn6[10][3]={{'I',0,0},{'O',30,255},{'S',20,128},{'L',0,0}};//フラッシュライト
uint8_t ptn7[10][3]={{'I',0,0},{'O',20,255},{'O',80,0},{'L',0,0}}; //シングルパルスストロボ
uint8_t ptn8[10][3]={{'I',0,0},{'O',10,255},{'O',20,0},{'O',10,255},{'O',60,0},{'L',0,0}}; //ダブルパルスストロボ
uint8_t ptn9[10][3]={{'I',0,0},{'O',25,128},{'O',40,255},{'O',25,128},{'O',40,0},{'L',0,0}}; //ミディアムパルスストロボ
uint8_t ptn10[10][3]={{'I',0,0},{'O',1,255},{'O',1,0},{'O',1,255},{'O',30,0},{'O',10,50},{'O',100,255},{'E',0,0}}; //グロー管蛍光灯
uint8_t ptn11[10][3]={{'I',0,0},{'O',1,255},{'O',1,0},{'O',1,255},{'O',30,0},{'O',30,40},{'O',50,255},{'O',70,0},{'L',0,0}}; //グロー管蛍光灯切れそう
uint8_t ptn12[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn13[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn14[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t ptn15[10][3]={{'I',0,255},{'E',0,255}}; //10ms すぐ点灯
uint8_t (*ptn)[3];
//
// stateマシンを実行させるファンクッション
// b0:Head
// b1:Tail
// b2:Function 1
// :
// b13:Function 12
//
//uint16_t FunctionStateEna = 0b0000000000000011;
define.h
# ifndef _DEFINE_H_
# define _DEFINE_H_
//各種設定、宣言
# define DECODER_ADDRESS 3
# define DCC_ACK_PIN 2 // 32 PD2 INT0
# define AUX1 9 // 13 PB1 PWM_C OC1A
# define AUX2 10 // 14 PB2 PWM_D OC1B
# define AUX3 5 // 9 PD5 PWM_E OC0B
# define AUX4 6 // 10 PD6 PWM_F OSC1
//#define AUX5 A2 // 25 PC2
//#define AUX6 A3 // 26 PC3
//#define AUX7 A4 // 27 PC4
//#define AUX8 A5 // 28 PC5
# define AUX5 1 // 25 PC2
# define AUX6 2 // 26 PC3
# define AUX7 3 // 27 PC4
# define AUX8 4 // 28 PC5
# define Bi1 11 // 15 PB3 PWM_A OC2A
# define Bi2 3 // 1 PD3 PWM_B OC2B
# define PTNB3 0x80 //
# define PTNB2 0x40 //
# define PTNB1 0x20 //
# define PTNB0 0x10 //
# define DIMCON 0x08 // 0:Event調光無効 1:Event調光有効
# define DIRCON 0x04 // 0:Disable 1:enable (方向制御For/Rev)
# define FORREV 0x02 // 0:Forward 1:Reverse
# define ALWAYS 0x01 // 0:normal 1:常に点灯
# define FORWARD 1
# define REVERSE 0
# endif// _DEFINE_H_