增加数据操作接口IDataPort,弥补数据位钩子函数复杂的问题,测试通过

This commit is contained in:
nnhy 2015-09-22 03:29:03 +00:00
parent 711d578e68
commit 4597004de1
4 changed files with 173 additions and 25 deletions

View File

@ -1,5 +1,12 @@
#include "Button_GrayLevel.h" #include "Button_GrayLevel.h"
#define BTN_DEBUG DEBUG
//#define BTN_DEBUG 0
#if BTN_DEBUG
#define btn_printf debug_printf
#else
#define btn_printf(format, ...)
#endif
InputPort* Button_GrayLevel::ACZero = NULL; InputPort* Button_GrayLevel::ACZero = NULL;
byte Button_GrayLevel::OnGrayLevel = 0xff; // 开灯时 led 灰度 byte Button_GrayLevel::OnGrayLevel = 0xff; // 开灯时 led 灰度
@ -8,15 +15,20 @@ int Button_GrayLevel::ACZeroAdjTime=2300;
Button_GrayLevel::Button_GrayLevel() Button_GrayLevel::Button_GrayLevel()
{ {
#if DEBUG
Name = NULL; Name = NULL;
#endif
Index = 0; Index = 0;
_Value = false; _Value = false;
_GrayLevelDrive = NULL; _GrayLevelDrive = NULL;
_PulseIndex = 0xff; _PulseIndex = 0xff;
_Handler = NULL; _Handler = NULL;
_Param = NULL; _Param = NULL;
_tid = 0;
Next = 0xFF;
} }
Button_GrayLevel::~Button_GrayLevel() Button_GrayLevel::~Button_GrayLevel()
@ -95,6 +107,95 @@ void Button_GrayLevel::Register(EventHandler handler, void* param)
} }
} }
int Button_GrayLevel::Size() const { return 1; }
int Button_GrayLevel::Write(byte* data)
{
byte cmd = *data;
if(cmd == 0xFF) return Read(data);
btn_printf("控制0x%02X ", cmd);
switch(cmd)
{
case 1:
btn_printf("打开");
SetValue(true);
break;
case 0:
btn_printf("关闭");
SetValue(false);
break;
case 2:
btn_printf("反转");
SetValue(!GetValue());
break;
default:
break;
}
switch(cmd>>4)
{
// 普通指令
case 0:
// 关闭所有带有延迟效果的指令
Next = 0xFF;
break;
// 开关闪烁
case 1:
btn_printf("闪烁%d", cmd - 0x10);
SetValue(!GetValue());
Next = cmd;
StartAsync(cmd - 0x10);
break;
// 打开,延迟一段时间后关闭
case 2:
case 3:
case 4:
case 5:
btn_printf("延迟%d关闭", cmd - 0x20);
SetValue(true);
Next = 0;
StartAsync(cmd - 0x20);
break;
// 关闭,延迟一段时间后打开
case 6:
case 7:
case 8:
case 9:
btn_printf("延迟%d打开", cmd - 0x60);
SetValue(false);
Next = 1;
StartAsync(cmd - 0x60);
break;
}
#if DEBUG
//Name.Show(true);
btn_printf(" %s\r\n", Name);
#endif
return Read(data);
}
int Button_GrayLevel::Read(byte* data)
{
*data = _Value ? 1 : 0;
return 1;
}
static void CommandTask(void* param)
{
Button_GrayLevel* btn = (Button_GrayLevel*)param;
byte cmd = btn->Next;
//btn_printf("Next=%d \r\n", cmd);
if(cmd != 0xFF) btn->Write(&cmd);
}
void Button_GrayLevel::StartAsync(int second)
{
if(!_tid) _tid = Sys.AddTask(CommandTask, this, -1, -1, "定时开关");
Sys.SetTask(_tid, true, second * 1000000);
}
bool Button_GrayLevel::GetValue() { return _Value; } bool Button_GrayLevel::GetValue() { return _Value; }
bool CheckZero(InputPort* port) bool CheckZero(InputPort* port)
@ -128,11 +229,11 @@ void Button_GrayLevel::SetValue(bool value)
// 故这里添加1ms延时 // 故这里添加1ms延时
// 这里有个不是问题的问题 一旦过零检测电路烧了 开关将不能正常工作 // 这里有个不是问题的问题 一旦过零检测电路烧了 开关将不能正常工作
} }
Relay = value; Relay = value;
_Value = value; _Value = value;
RenewGrayLevel(); RenewGrayLevel();
} }

View File

@ -1,14 +1,16 @@
#ifndef __BUTTON_GRAY_LEVEL_H__ #ifndef __BUTTON_GRAY_LEVEL_H__
#define __BUTTON_GRAY_LEVEL_H__ #define __BUTTON_GRAY_LEVEL_H__
#include "Sys.h" #include "Sys.h"
#include "Port.h" #include "Port.h"
#include "Timer.h" #include "Timer.h"
#include "Message\DataStore.h"
// 面板按钮 // 面板按钮
// 这里必须使用_packed关键字生成对齐的代码否则_Value只占一个字节导致后面的成员进行内存操作时错乱 // 这里必须使用_packed关键字生成对齐的代码否则_Value只占一个字节导致后面的成员进行内存操作时错乱
//__packed class Button //__packed class Button
// 干脆把_Value挪到最后解决问题 // 干脆把_Value挪到最后解决问题
class Button_GrayLevel class Button_GrayLevel : public IDataPort
{ {
private: private:
static void OnPress(Pin pin, bool down, void* param); static void OnPress(Pin pin, bool down, void* param);
@ -18,15 +20,17 @@ private:
void* _Param; void* _Param;
// 指示灯灰度驱动器 PWM; // 指示灯灰度驱动器 PWM;
PWM* _GrayLevelDrive; PWM* _GrayLevelDrive;
byte _PulseIndex; byte _PulseIndex;
private: private:
bool _Value; // 状态 bool _Value; // 状态
ushort Reserved; // 补足对齐问题 ushort Reserved; // 补足对齐问题
public: public:
int Index; // 索引号,方便在众多按钮中标识按钮 int Index; // 索引号,方便在众多按钮中标识按钮
#if DEBUG
string Name; // 按钮名称 string Name; // 按钮名称
#endif
InputPort Key; // 输入按键 InputPort Key; // 输入按键
OutputPort Relay; // 继电器 OutputPort Relay; // 继电器
@ -37,7 +41,7 @@ public:
// 构造函数。指示灯和继电器一般开漏输出,需要倒置 // 构造函数。指示灯和继电器一般开漏输出,需要倒置
Button_GrayLevel(); Button_GrayLevel();
~Button_GrayLevel(); ~Button_GrayLevel();
void Set(Pin key, Pin relay = P0, bool relayInvert = true); void Set(Pin key, Pin relay = P0, bool relayInvert = true);
void Set(Pin key, Pin relay); void Set(Pin key, Pin relay);
// led 驱动器设置 // led 驱动器设置
@ -47,6 +51,14 @@ public:
void RenewGrayLevel(); void RenewGrayLevel();
void Register(EventHandler handler, void* param = NULL); void Register(EventHandler handler, void* param = NULL);
virtual int Size() const;
virtual int Write(byte* data);
virtual int Read(byte* data);
byte Next; // 开关延迟后的下一个状态
uint _tid;
void StartAsync(int second);
// 过零检测 // 过零检测
private: private:
static int ACZeroAdjTime; // 过零检测时间补偿 默认 2300 static int ACZeroAdjTime; // 过零检测时间补偿 默认 2300
@ -56,7 +68,6 @@ public:
static bool SetACZeroPin(Pin aczero); // 设置过零检测引脚 static bool SetACZeroPin(Pin aczero); // 设置过零检测引脚
static void SetACZeroAdjTime(int us){ ACZeroAdjTime = us; }; // 设置 过零检测补偿时间 static void SetACZeroAdjTime(int us){ ACZeroAdjTime = us; }; // 设置 过零检测补偿时间
}; };
#endif #endif

View File

@ -1,7 +1,7 @@
#include "DataStore.h" #include "DataStore.h"
// 初始化 // 初始化
DataStore::DataStore() DataStore::DataStore() : Areas(0)
{ {
Strict = true; Strict = true;
} }
@ -45,20 +45,32 @@ int DataStore::Read(uint offset, ByteArray& bs)
bool DataStore::OnHook(uint offset, uint size, int mode) bool DataStore::OnHook(uint offset, uint size, int mode)
{ {
for(int i=0; i<ArrayLength(Areas); i++) for(int i=0; i<Areas.Length(); i++)
{ {
Area& ar = Areas[i]; Area& ar = Areas[i];
if(ar.Offset == 0 && ar.Size == 0) break; if(ar.Size == 0) break;
// 数据操作口只认可完整的当前区域
if(ar.Port && offset <= ar.Offset && offset + size >= ar.Offset + ar.Size)
{
if(mode == 1)
{
if(ar.Port->Write(&Data[ar.Offset]) <= 0) return false;
}
else if(mode == 0 || mode == 2)
{
if(ar.Port->Read(&Data[ar.Offset]) <= 0) return false;
}
}
if(ar.Hook && ar.Contain(offset, size)) if(ar.Hook && ar.Contain(offset, size))
{ {
if(!ar.Hook(offset, size, mode)) return false; if(!ar.Hook(offset, size, mode)) return false;
// 只命中第一个钩子,缩短时间 // 只命中第一个钩子,缩短时间
break; break;
} }
} }
return true; return true;
} }
@ -66,20 +78,31 @@ bool DataStore::OnHook(uint offset, uint size, int mode)
void DataStore::Register(uint offset, uint size, Handler hook) void DataStore::Register(uint offset, uint size, Handler hook)
{ {
// 找一个空位 // 找一个空位
int i=0; /*int i=0;
for(i=0; i<ArrayLength(Areas); i++) for(i=0; i<ArrayLength(Areas); i++)
{ {
if(Areas[i].Offset == 0 && Areas[i].Size == 0) break; if(Areas[i].Size == 0) break;
} }
if(i >= ArrayLength(Areas)) if(i >= ArrayLength(Areas))
{ {
debug_printf("数据存储区的读写钩子函数已满\r\n"); debug_printf("数据存储区的读写钩子函数已满\r\n");
return; return;
} }*/
Areas[i].Offset = offset; Area& ar = Areas.Push();
Areas[i].Size = size;
Areas[i].Hook = hook; ar.Offset = offset;
ar.Size = size;
ar.Hook = hook;
}
void DataStore::Register(uint offset, IDataPort& port)
{
Area& ar = Areas.Push();
ar.Offset = offset;
ar.Size = port.Size();
ar.Port = &port;
} }
DataStore::Area::Area() DataStore::Area::Area()

View File

@ -4,6 +4,8 @@
#include "Sys.h" #include "Sys.h"
#include "Stream.h" #include "Stream.h"
class IDataPort;
// 数据存储适配器 // 数据存储适配器
class DataStore class DataStore
{ {
@ -22,7 +24,8 @@ public:
typedef bool (*Handler)(uint offset, uint size, int mode); typedef bool (*Handler)(uint offset, uint size, int mode);
// 注册某一块区域的读写钩子函数 // 注册某一块区域的读写钩子函数
void Register(uint offset, uint size, Handler hook); void Register(uint offset, uint size, Handler hook);
void Register(uint offset, IDataPort& port);
private: private:
class Area class Area
{ {
@ -31,14 +34,24 @@ private:
uint Size; uint Size;
Handler Hook; Handler Hook;
IDataPort* Port;
Area(); Area();
bool Contain(uint offset, uint size); bool Contain(uint offset, uint size);
}; };
Area Areas[0x10]; Array<Area, 0x08> Areas;
bool OnHook(uint offset, uint size, int mode); bool OnHook(uint offset, uint size, int mode);
}; };
// 数据操作接口。提供字节数据的读写能力
class IDataPort
{
public:
virtual int Size() const = 0;
virtual int Write(byte* data) = 0;
virtual int Read(byte* data) = 0;
};
#endif #endif