Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
ライブラリについて
サンプルコード
パケット種別ごとの定義
基本クラス、関数
PALセンサー共通データ
struct PalBase {
uint32_t u32StoredMask;
};環境
TWELITE ARIA(ARIA)のセンサーデータ
動作センサーパル(MOT)のセンサーデータ
ライブラリの使用
パケット種別判定
開閉センサーパル(MAG)のセンサーデータ
環境センサーパル(AMB)のセンサーデータ
汎用クラス・関数
/* Copyright (C) 2020 Mono Wireless Inc. All Rights Reserved. *
* Released under MW-OSSLA-*J,*E (MONO WIRELESS OPEN SOURCE *
* SOFTWARE LICENSE AGREEMENT). */struct TweARIA : public PalBase {
static const uint8_t U8VARS_CT = ; // センサー数
static const uint32_t STORE_COMP_MASK = (1 << U8VARS_CT) - 1; // 電圧と開閉状況、ADC1、温湿度
uint16_t u16Volt; // 電源電圧
uint16_t u16Adc1; // ADC1電圧
uint8_t u8MagStat; // 開閉状況 (0:磁石が遠い, 1/2:磁石検出)
uint8_t bMagRegularTransmit; // 定期送信の時に 1, 磁石検出では 0
int16_t i16Temp; // 温度 (x100)
uint16_t u16Humd; // 湿度 (x100 %)
};struct DataAppUART {
/**
* 送信元のアドレス
*/
uint32_t u32addr_src;
/**
* 送信先のアドレス
*/
uint32_t u32addr_dst;
/**
* 送信元の論理ID
*/
uint8_t u8addr_src;
/**
* 宛先の論理ID
*/
uint8_t u8addr_dst;
/**
* LQI値
*/
uint8_t u8lqi;
/**
* 未使用
*/
uint8_t u8response_id;
/**
* データ部の長さ
*/
uint16_t u16paylen;
/**
* データ部配列
*/
TWEUTILS::SmplBuf_Byte payload;
};struct PalMot : public PalBase {
static const int MAX_SAMPLES = 16;
static const uint8_t U8VARS_CT = MAX_SAMPLES + 1; // センサー数
static const uint32_t STORE_COMP_MASK = 0b11; // 電圧と加速度サンプル1あればコンプとする
uint16_t u16Volt; // 電源電圧
uint8_t u8sample_rate_code; // サンプリング周波数 (0: 25Hz, 4:100Hz)
uint8_t u8samples; // 格納サンプル数
int16_t i16X[16]; // X軸 (ミリG)
int16_t i16Y[16]; // Y軸
int16_t i16Z[16]; // Z軸
};#include <mwm5.h>
#include <M5Stack.h>E_PKT identify_packet_type(uint8_t* p, uint8_t u8len)
E_PKT identify_packet_type(SmplBuf_Byte& sbuff)
E_PKT identify_packet_type(spTwePacket& sp)template <int N> using SmplBuf_WCharL =
SimpleBufferL<wchar_t, N, _SimpleBuffer_DummyStreamOut, 1>;struct PalMag : public PalBase {
const uint8_t U8VARS_CT = 2; // センサー数
const uint32_t STORE_COMP_MASK = (1 << U8VARS_CT) - 1; // 全コンプのマスク
uint16_t u16Volt; // 電源電圧
uint8_t u8MagStat; // 開閉状況 (0:磁石が遠い, 1/2:磁石検出)
uint8_t bRegularTransmit; // 定期送信の時に 1, 磁石検出では 0
};typedef SimpleBuffer<wchar_t, _SimpleBuffer_DummyStreamOut, 1> SmplBuf_WChar;struct PalAmb : public PalBase {
const uint8_t U8VARS_CT = 4; // センサー数
const uint32_t STORE_COMP_MASK = (1 << U8VARS_CT) - 1; // 全コンプマスク
uint16_t u16Volt; // 電源電圧
int16_t i16Temp; // 温度 (x100)
uint16_t u16Humd; // 湿度 (x100 %)
uint32_t u32Lumi; // 照度 (lux相当)
};PAL共通データ
struct DataPal {
uint8_t u8lqi; // LQI値
uint32_t u32addr_rpt; // 中継器のアドレス
uint32_t u32addr_src; // 送信元のアドレス
uint8_t u8addr_src; // 送信元の論理アドレス
uint16_t u16seq; // シーケンス番号
E_PAL_PCB u8palpcb; // PAL基板の種別
uint8_t u8pkt_type; // Packet タイプ (0:PalDataInfo付, 1:シンプル)
uint8_t u8sensors; // データに含まれるセンサーデータの数 (MSB=1はエラー)
uint8_t u8snsdatalen; // センサーデータ長(バイト数), MSB=1は動的確保
uint8_t au8snsdata[32]; // センサーデータ(解釈前の生データ)
std::unique_ptr<uint8_t[]> uptr_snsdata; // センサーデータ(動的確保)
};struct DataAppUART {
/**
* 送信元のアドレス
*/
uint32_t u32addr_src;
/**
* 送信先のアドレス
*/
uint32_t u32addr_dst;
/**
* 送信元の論理ID
*/
uint8_t u8addr_src;
/**
* 宛先の論理ID
*/
uint8_t u8addr_dst;
/**
* LQI値
*/
uint8_t u8lqi;
/**
* 未使用
*/
uint8_t u8response_id;
/**
* データ部の長さ
*/
uint16_t u16paylen;
/**
* データ部配列
*/
TWEUTILS::SmplBuf_Byte payload;
};spTwePacketオブジェクトの参照
TwePacket& refTwePacket(spTwePacket& p)
//例
auto&& pkt = newTwePacket(p, len); // パケットの生成
if (refTwePacket(pkt).get_type() == E_PKT::PKT_TWELITE) {
// App_Twelite の処理
}template <int N> using SmplBuf_ByteL =
SimpleBufferL<uint8_t, N, _SimpleBuffer_DummyStreamOut, 1>;template <int N> using SmplBuf_ByteSL =
SimpleBufferL<uint8_t, N, TWE::IStreamOut, 1>;SmplBuf_ByteSL<64> t;
t << "hello";
t << printfmt("-%d", 123);
t.clear();
t << L"こんにちわ"; // convert into UTF-8
t.clear();
t << SmplBuf_WChar(L"こんにちは"); struct PalEvent {
// uint8_t b_stored; // 格納されていたら true
uint8_t u8event_source; // 予備
uint8_t u8event_id; // イベントID
uint32_t u32event_param;// イベントパラメータ
};class TwePacketAppIO : public TwePacket, public DataAppIO { ... };TwePacketAppIO& refTwePacketAppIO(spTwePacket& p)TwePacketAppUARTclass TwePacketAppUART : public TwePacket, public DataAppUARTTwePacketAppUART& refTwePacketAppUART(spTwePacket& p)AsciiParser(size_t maxbuffsiz)
AsciiParser(SmplBuf_Byte& bobj)uint8_t AsciiParser::_u8Parse(char_t u8byte)void AsciiParser::_vOutput(TWEUTILS::SmplBuf_Byte& bobj, TWE::IStreamOut& p)static void vPutByte(uint8_t u8byte, uint8_t* pu8lrc, TWE::IStreamOut& p)
static void s_vOutput(TWEUTILS::SmplBuf_Byte& bobj, TWE::IStreamOut& p)if (parse_ascii) { // アスキー形式のパーサーの解釈完了
auto&& pkt = newTwePacket(parse_ascii.get_payload());
if (identify_packet_type(pkt) == E_PKT::PKT_APPIO) { // パケット解釈成功時
auto&& x = refTwePacketAppIO(pkt);
the_screen // LCDスクリーン上のターミナルに情報を表示
<< printfmt(":Lq=%d:Ad=%08X", x.u8lqi, x.u32addr_src)
<< printfmt(":ID=%02X", x.u8addr_src)
<< printfmt(":DI=%08b", x.DI_mask)
;
}
}if (parse_ascii) { // アスキー形式のパーサーの解釈完了
auto&& pkt = newTwePacket(parse_ascii.get_payload());
if (identify_packet_type(pkt) == E_PKT::PKT_APPUART) { // パケット解釈成功時
auto&& x = refTwePacketAppUART(pkt);
the_screen // LCDスクリーン上のターミナルに情報を表示
<< printfmt(":Lq=%d:Ad=%08X", x.u8lqi, x.u32addr_src)
<< printfmt(":ID=%02X", x.u8addr_src)
;
if (x.payload.length() > 0) {
auto p = act.payload.begin();
// HEXで表示
the_screen << ":DATA=";
for(; p != x.payload.end(); ++p) {
the_screen << printfmt("%02X", *p);
}
}
}
}
}パケット種別定義
パケット定義
PAL基板種別
TWELITE CUE(CUE)のセンサーデータ
ターミナル(コンソール)
[spTwePacket] ←(生成)- newTwePacket()
◆
|(shared_ptr)
|
[TwePacket] [DataPal]
↑ ↑
[TwePacketPal] -(生成)-> [PalAmb], [PalMot], ...struct TweCUE : public PalBase {
static const int MAX_SAMPLES = 10;
static const uint8_t U8VARS_CT = MAX_SAMPLES + 3; // センサー数
static const uint32_t STORE_COMP_MASK = 0b1111; // 電圧と開閉状況、ADC1、加速度サンプル1あればコンプとする
uint16_t u16Volt; // 電源電圧
uint16_t u16Adc1; // ADC1電圧
uint8_t u8MagStat; // 開閉状況 (0:磁石が遠い, 1/2:磁石検出)
uint8_t bMagRegularTransmit; // 定期送信の時に 1, 磁石検出では 0
uint8_t u8samples; // 格納サンプル数
uint8_t u8sample_rate_code; // サンプリング周波数 (0: 25Hz, 4:100Hz)
int16_t i16X[10]; // X軸 (ミリG)
int16_t i16Y[10]; // Y軸
int16_t i16Z[10]; // Z軸
};ターミナル(コンソール)
[IStreamOut]
↑
[ITerm]
↑
[TWETerm_M5_Console]書式パーサー
[IParser]
↑
[AsciiParser]TwePacketActStdspTwePacketTwePacketActStdclass TwePacketActStd : public TwePacketAppUARTTwePacketActStd& refTwePacketActStd(spTwePacket& p):80000000A8001C82012B1E01808103113008020D0C1130010203E40000000101EC6E
^^^^^^^1^2^^^3^^^^^^^4^5^6^7^8^9^a^b^c^^^d^e^f^g^h^^^i^j^k^l^m^n^o^pstruct _pkt_hist {
spTwePacket _pkt[16]; // パケットの履歴
int _i;
_pkt_hist() : _i(-1), _pkt{} {}
void add_entry(spTwePacket p) { _pkt[++_i & 0xF] = p; }
spTwePacket get_entry(int i) { return _pkt[(i + _i) & 0xF]; }
} pkt_hist;
void loop() {
spTwePacket pkt, pkt_last;
// 新たなパケットオブジェクト
pkt = newTwePacket(p, len);
pkt_hist.add_entry(pkt); // 履歴に保存する
// ひとつ前のパケットオブジェクト
pkt_last = pkt_hist.get_entry(-1);
}printfmt(const char*fmt, ...)
ISteramOut& operator << (IStreamOut& strm, printfmt f)
//例
the_screen << printfmt("%04X", 0x12ab) << crlf;int fPrintf(TWE::IStreamOut& fp, const char* format, ...)int snPrintf(char* buffer, size_t count, const char* format, ...)if (parse_ascii) { // アスキー形式のパーサーの解釈完了
auto&& pkt = newTwePacket(parse_ascii.get_payload());
if (identify_packet_type(pkt) == E_PKT::PKT_ACT_STD) { // パケット解釈成功時
auto&& x = refTwePacketActStd(pkt);
the_screen // LCDスクリーン上のターミナルに情報を表示
<< printfmt(":Lq=%d:Ad=%08X", x.u8lqi, x.u32addr_src)
<< printfmt(":ID=%02X", x.u8addr_src)
;
if (x.payload.length() > 5) {
auto p = act.payload.begin();
// 先頭4バイトはActコードで無線パケット先頭に設定した4文字アルファベット
the_screen << ":FOURCC=";
for(int i = 0; i < 4; ++i, ++p)
the_screen << printfmt("%c", *p);
// 残りはHEXで表示(Actコードごとによって違う)
the_screen << ":DATA=";
for(; p != x.payload.end(); ++p) {
the_screen << printfmt("%02X", *p);
}
}
}
}
}template <typename T>
class InputQueueprotected:
std::unique_ptr<TWEUTILS::FixedQueue<T>> _cue;InputQueue(size_type n)void setup(size_type n)void push(T c)T pop_front()
T read()bool is_full()int available()TWELITE PAL
TWELITE PALのパケット


[M5Stack 15P]
GPIO03
GPIO01
GPIO16 --- TWELITE DIO6/UART0 TX (TWELITE DIP #10)
GPIO17 --- TWELITE DIO7/UART0 RX (TWELITE DIP #3)
GPIO02
GPIO05
GPIO25
GPIO26
GPIO35
GPIO36
RST
BAT
3V3 --- TWELITE VCC (TWELITE DIP #28)
5V
GND --- TWELITE GND (TWELITE DIP #1,14)[M5Stack 15P]
GPIO03
GPIO01
GPIO16 --- TWELITE DIO6/UART0 TX (TWELITE DIP #10)
GPIO17 --- TWELITE DIO7/UART0 RX (TWELITE DIP #3)
GPIO02 --- TWELITE PGM (TWELITE DIP #7)
GPIO05 --- TWELITE DIO12 (TWELITE DIP #15)
GPIO25
GPIO26 --- TWELITE RESET (TWELITE DIP #21)
GPIO35
GPIO36
RST
BAT
3V3 --- TWELITE VCC (TWELITE DIP #28)
5V
GND --- TWELITE GND (TWELITE DIP #1,14) [TWELITE] [RaspberryPi]
GND ------------------ Gound (#6,#9,#14,#20,#25,#30,#34,#39のいずれか)
TXD(DIO6,DIP#10) ------ GPIO15/UART0 RXD (#10)
PRG(SPIMISO,DIP#7) ---- GPIO23 (#16)
RXD(DIO7,DIP#3) ------- GPIO14/UART0 TXD (#8)
RST(RESETN,DIP#21) ---- GPIO22 (#15)
VCC ------------------ 3V3 (#1,#17のいずれか)
SET(DIO12,DIP#15) ----- GPIO12 (#32)uint8_t get_width()
uint8_t get_width(uint16_t wc)uint8_t get_height()bool is_default()uint8_t get_font_code()int find_font_index(uint16_t c)// インデックス配列 M+10dotフォント
const uint16_t font_mplus_f10j_idx[FONT_MP10_DBL_CHARS] {
0x0391, // IDX=0 U+0391
0x0392, // IDX=1 U+0392
0x0393, // IDX=2 U+0392
...
0x5a2f, // IDX=892 U+5a2f (娯)
...
}
// データ配列
const uint8_t font_mplus_f10j_data[FONT_MP10_DBL_CHARS*FONT_MP10_DATA_ROWS*2] = {
...
0x00,0x00,0x47,0x80,0x54,0x80,0xf7,0x80,0x50,0x00,
0x5f,0x80,0xa0,0x80,0xff,0x80,0x45,0x00,0x58,0x80, // 3864/u5a2f idx=892
...
};
class TwePacketPal : public TwePacket, public DataPal { ... };TwePacketPal& refTwePacketPal(spTwePacket& p)if (parse_ascii) { // アスキー形式のパーサーの解釈完了
if (identify_packet_type(parse_ascii.get_payload()) == E_PKT::PKT_PAL) {
auto&& pkt = newTwePacket(parse_ascii.get_payload(), E_PKT::PKT_PAL);
if (pkt == E_PKT::PKT_PAL) { // パケット解釈成功時
auto&& pal = refTwePacketPal(pkt);
// 開閉センサーパル
if (pal.u8palpcb == E_PAL_PCB::MAG) {
PalMag mag = pal.get_PalMag();
if (mag.u8MagStat == 0) {
// OPEN
} else {
// CLOSE
}
}
}
}
}bool has_PalEvent()
bool is_PalEvent()E_PAL_DATA_TYPE get_PalDataType()bool has_data_info()bool is_data_source_timer()PalMag get_PalMag()PalAmb get_PalAmb()PalMot get_PalMot()PalEvent get_PalEvent()ターミナル(コンソール)クラスの利用例
// ターミナルオブジェクトの生成
TWETerm_M5_Console the_screen(
64, 20,
{ 0, 16, 320, 192 }, M5);void setup() {
...
// create font as #10 (東雲フォント16)
createFontShinonome16(10, 0, 0);エスケープシーケンス
標準アプリケーション
TWELITE DIP
-01:GND VCC:28-------M5 3V3
-02:D14 D3:27-
M5 GPIO16-------03:D7 D2:26-
-04:D5 D1:25-
-05:D18 A2:24-
-06:C D0:23-
-07:M A1:22-
-08:D19 RST:21-
-09:D4 D17:20-
M5 GPIO17-------10:D6 D15:19-
-11:D8 D16:18-
-12:D9 D11:17-
-13:D10 D13:16-
M5 GND----------14:GND D12:15-Serial2.setRxBufferSize(512);
Serial2.begin(115200, SERIAL_8N1, 16, 17);setup_screen();pkt_data.init_screen(fmt_title);check_for_serial();process_input();check_for_refresh();void init_screen(const char *fmt_status)
void reinit_screen()bool add_entry(spTwePacket spobj)void next_page()
void prev_page()
void set_page(int entry)void update_status()void update_term()
void update_term(spTwePacket pal_upd, bool update_all)#include <mwm5.h>
#include <Arduino.h>
#include <M5Stack.h>
// ターミナルオブジェクトの生成
TWETerm_M5_Console the_screen(
64, 20,
{ 0, 16, 320, 192 }, M5);
void setup() {
// begin M5
M5.begin(true, false, true, false); // LCD, SD, Serial, I2C
// create font as #10 (東雲フォント16)
createFontShinonome16(10, 0, 0);
the_screen.set_font(10); // set font #10
the_screen.set_color(ALMOST_WHITE, M5.Lcd.color565(90, 0, 50);
// set color (fg, bg)
the_screen.set_cursor(2); // 0: no 1: curosr 2: blink cursor
the_screen.force_refresh(); // repaint now.
// initial message
the_screen << "the_screen:" << crlf;
}
void loop() {
// refresh screen
static uint32_t t_last;
uint32_t t_now = millis();
if (t_now - t_last > 32) {
the_screen.refresh();
t_last = t_now;
}
// press A button
if (M5.BtnA.wasReleased()) {
the_screen << "hello world!" << crlf;
}
if (M5.BtnB.wasReleased()) {
// force clear with whole redraw.
the_screen.clear_screen();
}
if (M5.BtnC.wasReleased()) {
// clear screen and set cursor home.
the_screen << "\033[2J\[033H";
}
}template <typename T>
class FixedQueue public:
typedef uint16_t size_type;
typedef T value_type;
private:
std::unique_ptr<T[]> _p;
size_type _head;
size_type _tail;
size_type _ct;
size_type _size;void setup() {
...
the_screen.set_font(10); // set font #10
the_screen.set_color(ALMOST_WHITE, color565(90, 0, 50);
// set color (fg, bg)
the_screen.set_cursor(2); // 0: no 1: curosr 2: blink cursor
the_screen.force_refresh(); // repaint now.void loop() {
// refresh screen
static uint32_t t_last;
uint32_t t_now = millis();
if (t_now - t_last > 32) {
the_screen.refresh(); // 再描画!
t_last = t_now;
}void loop() {
...
// press A button
if (M5.BtnA.wasReleased()) {
the_screen << "hello world!" << crlf;
}
if (M5.BtnB.wasReleased()) {
// force clear with whole redraw.
the_screen.clear_screen();
}
if (M5.BtnC.wasReleased()) {
// clear screen and set cursor home.
the_screen << "\033[2J\[033H";
}IParser& Parse(uint8_t u8b)
IParser& operator << (char_t c)uint8_t state()operator bool()
bool is_complete()uint16_t length()uint8_t operator[](int i)SmplBuf_Byte& get_payload()template <typename T>
inline void set_payload(T& bobj)
inline void set_payload(uint8_t *b, uint8_t *e)
//例: buffに出力書式を格納する
AsciiParser format_ascii; // パーサー(出力用)
SmplBuf_ByteSL<256> buff; // 出力バッファ
uint8_t buff_raw[] = "ABCDE"; // データ列
format_ascii.set_payload(buff_raw, buff_raw + sizeof(buff_raw));
buff << format_ascii;
for(auto x : buff) putchar(x);
virtual void reinit()IStreamOut& operator << (TWE::IStreamOut& lhs, IParser& rhs)
IStreamOut& operator << (TWETERM::ITerm& lhs, IParser& rhs)virtual uint8_t _u8Parse(char_t u8b) = 0virtual inline void _vOutput(SmplBuf_Byte& bobj, IStreamOut& p) = 0TWETerm_M5_Console(
uint8_t u8c, uint8_t u8l,
Rect drawArea, M5Stack& _M5)
TWETerm_M5_Console(
uint8_t u8c, uint8_t u8l,
TWETERM::SimpBuf_GChar* pAryLines, TWETERM::GChar* pBuff,
Rect drawArea, M5Stack& _M5)TWETerm_M5_Console the_screen(64, 20, { 0, 16, 320, 192 }, M5);void loop() {
static uint32_t u32mills;
uint32_t u32now = millis();
if (u32now - u32mills > 32) {
the_screen.refresh();
u32mills = u32now;
}
}void set_font(uint8_t u8id, uint8_t u8col_request = 0, uint8_t u8row_request = 0)uint8_t font_id()
uint8_t font_width()
uint8_t font_height()void set_color(uint16_t color, uint16_t bgcolor = 0)uint16_t c = color565(255, 127, 0); // R:255, G:127, B:0void set_color_table(const uint16_t* ptbl)static const uint16_t COLTBL_MAIN[8] = {
BLACK,
RED,
GREEN,
YELLOW,
color565(127, 127, 255), // BLUE,
color565(255, 0, 142), // MAGENTA,
CYAN,
ALMOST_WHITE
};
the_screen.set_color_table(COLTBL_MAIN);constexpr uint16_t color565(uint8_t r, uint8_t g, uint8_t b)FixedQueue(size_type n)
void setup(size_type n)void setup(size_type n)void push(T&& c)
void push(const T& c)T* push_no_assign()void pop()T& front()T& back()T& operator[] (int i)T pop_front()bool empty()size_type size()size_type capacity()変更履歴、ダウンロード
void putmsg(ITerm& trm, const char *msg) {
trm << TermAttr(TERM_COLOR_FG_RED | TERM_BOLD);
trm << msg;
trm << TermAttr(TERM_ATTR_OFF);
}TermAttr(GChar::tAttr attr = 0) TWELITE DIP
-01:GND VCC:28-------M5 3V3
-02:D14(SCL) (M3 ) D3:27-
M5 GPIO16-------03:D7 (RX ) (M2 ) D2:26-
-04:D5 (Pw1) (AI4) D1:25----VCC
-05:D18(DO1) (AI3) A2:24----VCC
-06:C (Pw2) (AI2) D0:23----VCC
-07:M (Pw3) (AI1) A1:22----VCC
-08:D19(DO2) RST:21-
-09:D4 (DO3) (BPS)D17:20-
M5 GPIO17-------10:D6 (TX ) (SDA)D15:19-
-11:D8 (Pw4) (DI4)D16:18-
-12:D9 (DO4) (DI3)D11:17-
GND----13:D10(M1 ) (DI2)D13:16-
M5 GND----------14:GND (DI1)D12:15-Serial2.setRxBufferSize(512);
Serial2.begin(115200, SERIAL_8N1, 16, 17);setup_screen();check_for_serial();process_input();check_for_refresh(); trm << "\033[H"; // カーソルホーム
...
if (b) trm << "\033[1;1H" // カーソルを1行目に移動
"\033[1;30;45mタイムCT\033[0m" " " // ボールド、文字色、背景色設定
"\033[1;30;45mId#\033[0m" " "
"\033[1;30;45mシリアル番号\033[0m";
if (b) trm << "\033[3;1H" // カーソルを3行目に移動
"\033[1;30;45m D1 \033[0m"
" \033[1;30;45m D2 \033[0m"
" \033[1;30;45m D3 \033[0m"
" \033[1;30;45m D4 \033[0m"; TwePacketTwelite& x = refTwePacketTwelite(spLastPacket);
if (c) trm << "\033[2;1H"
<< printfmt("%5d %3d %8X",
x.u16timestamp, x.u8addr_src, x.u32addr_src);
if (c) trm << "\033[4;1H "
<< (x.DI1 ? "\033[31m" "●" : "\033[35m" "〇") << "\033[0m "
<< (x.DI2 ? "\033[32m" "●" : "\033[35m" "〇") << "\033[0m "
<< (x.DI3 ? "\033[33m" "●" : "\033[35m" "〇") << "\033[0m "
<< (x.DI4 ? "\033[34m" "●" : "\033[35m" "〇") << "\033[0m";virtual inline IStreamOut& operator ()(char_t c) = 0
virtual inline IStreamOut& write_w(wchar_t c)template <class T,
class SOUT=_SimpleBuffer_DummyStreamOut,
int is_string_type=0>
class SimpleBuffer : public SOUT_query_extra_device_info()を追加したTweCmdPipeInOut(twe_file.cpp, hpp)クラスの追加。コマンドの標準入出力を処理するsrc/gen/serial_???)シリアル電文パーサー

class ITerm : public TWE::IStreamOut {
// ... 各種定義
ITerm& write(char_t c) {
// ... 1バイト入力を受け付ける処理
}
// StreamOut::operator () の実装
TWE::IStreamOut& operator ()(char_t c) {
write(c);
return *this;
}
};inline IStreamOut& operator << (char_t c)
inline IStreamOut& operator << (wchar_t c)
inline IStreamOut& operator << (IStreamSpecial& sc)inline ITerm& operator << (ITerm& t, char_t c)
{ *static_cast<TWE::IStreamOut*>(&t) << c; return t; } class IStreamSpecial {
public:
virtual inline IStreamOut& operator ()(IStreamOut& of) = 0;
};class IStream_endl : public IStreamSpecial {
inline IStreamOut& operator ()(IStreamOut& of) {
// ... CR LF の出力
of ('\r');
of ('\n');
}
};
IStream_endl crlf;the_screen << "Hello World!" << crlf;SimpleBuffer()
SimpleBuffer(T* p, uint16_t u16len, uint16_t u16maxlen)
SimpleBuffer(uint16_t u16maxlen)SimpleBuffer(const SimpleBuffer<T>& ref)
SimpleBuffer<T>& operator = (const SimpleBuffer<T>& ref)void attach(T* p, uint16_t l, uint16_t lm)SimpleBuffer<uint8_t> buf(128), buf_sub;
buf_sub = buf;
buf_sub.attach(buf.begin() + 16, 0, buf.max_length() - 16);T* begin()
T* end()bool append(T c)
void push_back(T c) { append(c); }uint16_t length()
uint16_t size() { return length(); }
uint16_t length_max()
uint16_t capacity() { return length_max(); }bool redim(uint16_t len)
bool reserve(uint16_t len) { return redim(len); }inline T& operator [] (int i)フォントジェネレータ関数
App_Twelite データ
ITerm(uint8_t u8c, uint8_t u8l)
ITerm(uint8_t u8c, uint8_t u8l, SimpBuf_GChar* pAryLines, GChar* pBuff)// 静的メモリ確保例
const uint8_t U8COL = 64;
const uint8_t U8LINE = 20;
static TWETERM::GChar screen_buf[U8COL * U8LINE]; // pBuff
static TWETERM::SimpBuf_GChar screen_lines[U8LINE]; // pAryLinesvirtual ~ITerm()void clear()
void home()
void clear_screen()void clear_line(uint8_t line, bool fill_blank = false)virtual void refresh() = 0
void force_refresh()ITerm& write(wchar_t c)
ITerm& write(char_t c)uint8_t get_height() // 行数
uint8_t get_width() // カラム数ITerm& move_cursor(uint8_t cols, uint8_t lines)
ITerm& operator ()(int cols, int lines)
//例
the_screen(1, 3) << "HELLO"; // 2カラム目、4行目に移動して HELLO を出力ITerm& operator << (const char *s)
TWE::IStreamOut& operator << (TWE::IStreamSpecial& sc)
TWE::IStreamOut& operator << (ITerm& t, char_t c)
TWE::IStreamOut& operator << (ITerm& t, wchar_t c)
TWE::IStreamOut& operator << (ITerm& t, int i)
TWE::IStreamOut& operator << (ITerm& t, TermAttr a)
TWE::IStreamOut& operator << (TWE::IStreamOut& t, TermAttr a)
struct DataTwelite {
//送信元のシリアル#
uint32_t u32addr_src;
// 送信元の論理ID
uint8_t u8addr_src;
// 宛先の論理ID
uint8_t u8addr_dst;
// 送信時のタイムスタンプ
uint16_t u16timestamp;
// 低レイテンシ送信時のフラグ
bool b_lowlatency_tx;
// リピート中継回数
uint16_t u8rpt_cnt;
// LQI値
uint16_t u8lqi;
// DIの状態 (true がアクティブ Lo,GND)
bool DI1, DI2, DI3, DI4;
// DIの状態ビットマップ (LSBから順にDI1,2,3,4)
uint8_t DI_mask;
// DIアクティブならtrue (過去にアクティブになったことがある)
bool DI1_active, DI2_active, DI3_active, DI4_active;
// DIのアクティブビットマップ(LSBから順にDI1,2,3,4)
uint8_t DI_active_mask;
// モジュールの電源電圧[mV]
uint16_t u16Volt;
// AD値 [mV]
uint16_t u16Adc1, u16Adc2, u16Adc3, u16Adc4;
// ADがアクティブ(有効)なら 1 になるビットマップ (LSBから順にAD1,2,3,4)
uint8_t Adc_active_mask;
};バイト配列
typedef SimpleBuffer<uint8_t, _SimpleBuffer_DummyStreamOut, 1> SmplBuf_Byte;u32Optは、フォントのオプションを指定します。オプションはU32_OPT_FONT_TATEBAIとU32_OPT_FONT_YOKOBAIがあり、論理和で指定します。const FontDef& createFontShinonome16(
uint8_t id,
uint8_t line_space = 0,
uint8_t char_space = 0,
uint32_t u32Opt = 0);if (createFontShinonome16(11).is_default()) {
// フォント作成のエラー
}パケットデータの解釈とオブジェクト生成
class TwePacket;
typedef std::shared_ptr<TwePacket> spTwePacket;spTwePacket newTwePacket(
uint8_t* p,
uint8_t u8len,
E_PKT eType = E_PKT::PKT_ERROR)
spTwePacket newTwePacket(
TWEUTILS::SmplBuf_Byte& sbuff,
E_PKT eType = E_PKT::PKT_ERROR)// serial parser
AsciiParser parse_ascii(256);while (Serial.available()) {
int c = Serial.read();
parse_ascii << char_t(c);
if (parse_ascii) {
// completed!
}
}if (parse_ascii) {
auto&& p = parse_ascii.get_payload();
}auto&& p = parse_ascii.get_payload();
if (p[0] == 0x80) { ... } // 最初の要素
int len = p.length(); // 要素数
for (auto&& x : p) { // 各要素にアクセス
Serial.print(x, HEX);
Serial.print(" "); }inline void IParser::operator >> (TWE::IStreamOut& fo_putchar)
// パーサーオブジェクトの宣言
AsciiParser o_parser(128);
// コード例
auto&& b = o_parser.get_payload(); // SmplBuf_Byte&としてデータ列を参照
b.clear();
b << 0x00;
b << 0x11;
b << 0x22;
b << 0x33;
// ターミナルへ出力(ITerm)
o_parser >> the_screen; // the_screen はターミナル(ITerm)
// -> :001122339A[改行]
// バッファーへ出力
SmplBuf_ByteSL<128> b1;
o_parser >> b1;
// -> ":001122339A[CR][LF]"auto&& pkt = newTwePacket(parse_ascii.get_payload());
E_PKT pkt_typ = identify_packet_type(pkt);
if (pkt_typ == E_PKT::PKT_PAL) {
// TWELITE PAL (App_PAL)
} else {
// unknown packet type
}if (pkt == E_PKT::PKT_PAL) {
auto&& pal = refTwePacketPal(pkt);
PalEvent ev;
// acquire event data.
if (pal.has_PalEvent()) {
ev = pal.get_PalEvent();
}
switch(pal.get_PalDataType()) {
case E_PAL_DATA_TYPE::EVENT_ONLY:
break;
case E_PAL_DATA_TYPE::MAG_STD:
break;
case E_PAL_DATA_TYPE::AMB_STD:
break;
case E_PAL_DATA_TYPE::EX_CUE_STD:
break;
}case E_PAL_DATA_TYPE::MAG_STD:
{
// generate pal board specific data structure.
PalMag mag = pal.get_PalMag();
switch(mag.u8MagStat) {
case 0: /* no magnet */ break;
case 1: /* N Pole */ break;
case 2: /* S Pole */ break;
}
}
break;TWEFONT::createFontShinonome16(10, 0, 0,
TWEFONT::U32_OPT_FONT_TATEBAI | TWEFONT::U32_OPT_FONT_YOKOBAI);
TWEFONT::createFontShinonome16(11, 1, 0);●東雲フォントライセンス
2001
The Electronic Font Open Laboratory
http://openlab.ring.gr.jp/efont/
このアーカイブに含まれるすべてのフォントデータ、ドキュメント、スクリプ
ト類はすべて Public Domain で提供されています 。
但し、日本に於いては現時点で著作権を放棄することは法律上不可能であり、
AUTHORS に列挙されている作者がその権利を行使しないと宣言することで実質
的な Public Domain であるとします。
自由な改造、他フォーマットへの変換、組込み、再配布を行うことができます。
同時に、これらはすべて完全に無保証です。 M+ BITMAP FONTS Copyright 2002-2005 COZ <[email protected]>
-
LICENSE
These fonts are free softwares.
Unlimited permission is granted to use, copy, and distribute it, with
or without modification, either commercially and noncommercially.
THESE FONTS ARE PROVIDED "AS IS" WITHOUT WARRANTY.auto&& font = queryFont(10); // ID10のFontDefオブジェクトを参照
TWE::fPrintf(the_screen, "\nFont: %s\n ID=%d H:%d W:%d W_CHRs:%d",
font.font_name, // フォント名
font.get_font_code(), // フォントID (=10)
font.height, // フォントデータの高さ(行間は含まれない)
font.width, // フォントデータの幅(シングル幅、文字間スペースは含まれない)
font.font_wide_count // ダブル幅の登録文字数
);// ターミナル the_screen の宣言
TWETerm_M5_Console the_screen(64, 20, { 0, 16, 320, 192 }, M5);
void setup() {
// ... M5の初期化など
M5.begin(true, false, true, false);
// フォントの生成と登録
createFontMP12(13, 0, 0);
the_screen.set_font(13); // フォントIDの指定
the_screen.force_refresh(); // 再描画
}the_screen.set_font(11); // フォントの指定
the_screen.clear_screen(); // ターミナルを文字バッファをクリアする
the_screen.force_refresh(); // 完全再描画を行うTwePacket(E_PKT ptyp = E_PKT::PKT_ERROR)virtual ~TwePacket()E_PKT get_type()virtual E_PKT parse(uint8_t* p, uint8_t u8len)void loop() {
if (M5.BtnB.wasReleased()) {
static int idx = 0;
const char msg[3][16] = {
"ABCD1234", "あいうえ", "やあ世界" };
auto&& font = queryFont(10); // use font ID=10
drawChar(
font, // フォント指定
0, 240 - 30, // 左上座標 (X,Y)
msg[idx], // 文字列
RED, // 文字色
BLACK, // 背景色
0x01); // オプション 0x01:BOLD
idx++; if (idx >= 3) idx = 0;
}
}int16_t drawChar(const FontDef& font, int32_t x, int32_t y,
uint16_t c, uint32_t color, uint32_t bg, uint8_t opt);
int16_t drawChar(const FontDef& font, int32_t x, int32_t y,
const char *s, uint32_t color, uint32_t bg, uint8_t opt);
int16_t drawChar(const FontDef& font, int32_t x, int32_t y,
const uint16_t* s, uint32_t color, uint32_t bg, uint8_t opt);examples/glancer --- Makefile
msc/MSC_glancer_con --- VC++ Project 定義twe_fmt.cpp
twe_fmt_actstd.cpp
twe_fmt_appio.cpp
twe_fmt_apptag.cpp
twe_fmt_appuart.cpp
twe_fmt_common.cpp
twe_fmt_pal.cpp
twe_fmt_twelite.cpp
twe_sercmd.cpp
twe_sercmd_ascii.cpp
twe_utils_crc8.cpp
twe_common.hpp
twe_fmt.hpp
twe_fmt_actstd.hpp
twe_fmt_appio.hpp
twe_fmt_apptag.hpp
twe_fmt_appuart.hpp
twe_fmt_common.hpp
twe_fmt_pal.hpp
twe_fmt_twelite.hpp
twe_sercmd.hpp
twe_sercmd_ascii.hpp
twe_stream.hpp
twe_utils.hpp
twe_utils_crc8.hpp
twe_utils_fixedque.hpp
twe_utils_simplebuffer.hpp#if defined(_MSC_VER) || defined(__MINGW32__)
#include "windows.h"
# pragma comment(lib, "secur32.lib")
# pragma comment(lib, "winmm.lib")
# pragma comment(lib, "dmoguids.lib")
# pragma comment(lib, "wmcodecdspuuid.lib")
# pragma comment(lib, "msdmo.lib")
# pragma comment(lib, "Strmiids.lib")
#elif defined(__APPLE__) || defined(__linux)
#include <sys/time.h>
#endif
uint32_t millis() {
#if defined(_MSC_VER) || defined(__MINGW32__)
return (uint32_t)timeGetTime();
#elif defined(__APPLE__) || defined(__linux)
timeval time;
gettimeofday(&time, NULL);
long ms = (time.tv_sec * 1000) + (time.tv_usec / 1000);
return (uint32_t)ms;
#else
# warning "no millis() implementation."
return 0;
#endif
}:78811501C98201015A000391000C2E00810301FFFFFFFFFB
PKT:Typ=1:Lq=201:Ad=0x8201015a(0x78):Vmv=3118:Tms=2656:App_Twelite:DI1..4=LHHH:AI1..4=(0028,----,----,----)
:78A0028201015AFFFFFFFFA8000700112233AABBCCC6
PKT:Typ=4:Lq=168:Ad=0x8201015a(0x78):Vmv=0000:Tms=5430:App_UARTMSG=0x00112233aabbcc
:8000000084811F810EFF6D04808205113008020AEB11300102035A0501000209E3010200020E3A02030004000001BE6C00
PKT:Typ=2:Lq=132:Ad=0x810eff6d(0x04):Vmv=2795:Tms=3904:PAL_AMB:TEMP=25.31:HUMD=36:LUMI=446#include <iostream>
#include <iomanip>
#include <string>
#include "twe_common.hpp"
#include "twe_sercmd_ascii.hpp"
#include "twe_fmt.hpp"
using namespace TWE;
using namespace TWEUTILS;
using namespace TWESERCMD;
using namespace TWEFMT;
AsciiParser parse_ascii(256);int c;
while ((c = std::cin.get()) >= 0) {
if (c == '\r' || c == '\n') {
parse_ascii << char_t(0x0d); // always 0x0d (this parser does not check the following 0x0a)
}
else {
parse_ascii << char_t(c);
}
if (parse_ascii) {
std::cout << "PKT";
auto&& payl = parse_ascii.get_payload(); // payload data array
auto&& pkt = newTwePacket(payl); // packet object (contains minimum information)
auto&& typ = identify_packet_type(pkt); // packet type
std::cout << ":Typ=" << int(typ);
if (typ != E_PKT::PKT_ERROR) {
// ... display common packet info
}
// display each packet information
switch (typ) {
case E_PKT::PKT_PAL: print_pal(pkt); break;
case E_PKT::PKT_ACT_STD: print_act(pkt); break;
case E_PKT::PKT_TWELITE: print_app_twelite(pkt); break;
case E_PKT::PKT_APPIO: print_app_io(pkt); break;
case E_PKT::PKT_APPUART: print_app_uart(pkt); break;
case E_PKT::PKT_APPTAG: print_app_tag(pkt); break;
default: print_unknown(payl); // e.g. UART message of App_Twelite, App_UART(simple format), or corrupted.
}
}
} if (parse_ascii) {auto&& payl = parse_ascii.get_payload();
auto&& pkt = newTwePacket(payl);auto&& typ = identify_packet_type(pkt); // packet typevoid print_app_twelite(spTwePacket pkt) {
auto&& atw = refTwePacketTwelite(pkt);
std::cout << ":DI1..4="
<< char(atw.DI1 ? 'L' : 'H')
<< char(atw.DI2 ? 'L' : 'H')
<< char(atw.DI3 ? 'L' : 'H')
<< char(atw.DI4 ? 'L' : 'H');
...void print_pal(spTwePacket pkt) {
auto&& pal = refTwePacketPal(pkt);
PalEvent ev;
// acquire event data.
if (pal.has_PalEvent()) {
ev = pal.get_PalEvent();
}
switch(pal.get_PalDataType()) {
case E_PAL_DATA_TYPE::EVENT_ONLY:
/* イベントのみが含まれるパケットの場合 */ break;
case E_PAL_DATA_TYPE::MAG_STD:
/* MAG PAL の表示コード */ break;
case E_PAL_DATA_TYPE::MOT_STD:
/* MOT PAL の表示コード */ break;
case E_PAL_DATA_TYPE::AMB_STD:
/* AMB PAL の表示コード */ break;
case E_PAL_DATA_TYPE::EX_CUE_STD:
/* TWELITE CUE のメッセージ */ break;
}auto&& pal = refTwePacketPal(pkt);if (pal.is_PalEvent()) {switch(pal.get_PalDataType()) {case E_PAL_DATA_TYPE::MAG_STD:
{
PalMag mag = pal.get_PalMag();
std::cout << ":STAT=" << int(mag.u8MagStat);
...アプリ記述setup(),loop()の切り替え
cwdは、TWELITE STAGEの場合 MWSDKディレクトリを指定する。setup()loop()関連変数{
"name": "(lldb/mac) TWELITE_Stage",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/examples/TWELITE_Stage/build/TWELITE_Stage-debug.command",
"args": [],
"stopAtEntry": true,
// "cwd": "${workspaceFolder}",
"cwd": "${workspaceFolder}/../MWSDK",
"environment": [],
"externalConsole": false,
"MIMode": "lldb"
}#include <mwm5.h>
// サブアプリ1
class App_Foo : public class APP_DEF {
public:
void setup() { ... }
void loop() { ... }
}
// サブアプリ2
class App_Bar : public class APP_DEF {
public:
void setup() { ... }
void loop() { ... }
}
// サブアプリ切り替え関数
static int s_change_app(
TWE::APP_MGR& the_app, int n_appsel
, int prev_app, int exit_id) {
if (n_appsel == 1) the_app.new_app<App_Foo>();
else if (n_appsel == 2) the_app.new_app<App_Bar>();
else n_appsel = 0;
return n_appsel;
}
// setup
void setup() {
the_app.setup(s_change_app); // サブアプリ切り替え関数の登録
the_app.new_app<App_Foo>(); // 最初に起動するサブアプリ
}
// loop()
void loop() {
the_app.loop(); // 必須の呼び出し
}class App_Foo : public class APP_DEF {
public:
void setup() { ... }
void loop() { ... }
}// APP_MGR内のtypedef
typedef int (*PF_CHANGE_APP)(
THE_APP_MGR& the_app,
int n_appsel,
int prev_app,
int exit_id);
// 例: App_Foo と App_Bar で切り替える
int s_change_app(
TWE::APP_MGR& the_app, int n_appsel
, int prev_app, int exit_id) {
if (n_appsel == 1 || n_appsel == -1)
the_app.new_app<App_Foo>();
else if (n_appsel == 2)
the_app.new_app<App_Bar>();
else n_appsel = 0;
return n_appsel;
}template <class T, class... Args>
void APP_MGR::new_app(Args&&... args)
// setup 例
void setup() {
the_app.setup(s_change_app);
the_app.new_app<App_Foo>(); // 最初に起動するサブアプリ
}
// サブアプリ切り替え関数例
static int s_change_app(
TWE::APP_MGR& the_app, int n_appsel
, int prev_app, int exit_id) {
if (n_appsel == 1 || n_appsel == -1)
the_app.new_app<App_Bar>();
}
}void APP_MGR::exit(int exit_code, int next_app = NEXT_APP_DEFAULT)
// loop() の呼び出し階層
loop() // 大本のloop()
the_app.loop() // APP_MGRのloop()
App_Foo::loop() // サブアプリのloop()
...
if (..) { // 何かの条件でサブアプリを終了する
the_app.exit(0);
return; // 通常はここでreturn
}
// App_Foo::loop()が終了した
// exit がコールされていた場合は、
// サブアプリ切り替え関数を呼び出し、
// 次のサブアプリに切り替える。
}
}APP_DEF* APP_MGR::query_appobj() // the_app.qurery_appobj()
// サブアプリ定義クラス内で利用
void APPDEF::set_appobj(void* p)
void* APPDEF::get_appobj()
// サブアプリ例
class App_Foo {
TWETerm_M5_Console _scr;
public:
App_Foo : _scr(..) {
// 共通オブジェクトの登録
set_appobj((void*)static_cast<ITerm*>(&_scr));
}
void setup();
void loop();
};
// 大本のloop()
void loop() {
..
// APPDEFオブジェクトの取得
if (auto p = the_app.query_appobj()) {
// 登録されたvoid*をITerm*へ強制キャスト
if (ITerm* ptrm = reinterpret_cast<ITerm*>(p->get_appobj())) {
... // ptrm を用いた操作
}
}
}
class App_Foo : public APPDEF, public APP_HNDLR<App_Foo> {
// アプリハンドラ1
void hndr_scr_def(event_type ev, arg_type arg = 0) {
switch (ev) {
case EV_SETUP:
// setup()に相当、最初に1回だけ呼ばれる
break;
case EV_LOOP:
// loop()に相当
if (..) { // ある条件で次のアプリハンドラに遷移したい
// アプリハンドラ切り替え
APP_HNDLR::new_hndlr(&App_Foo::hndlr_scr_next);
return; // 通常はここでreturn
}
break;
case EV_EXIT;
// 終了時=アプリハンドラ切り替え時に呼び出される
break;
}
// ハンドラ2
void hndlr_scr_next(event_type ev, arg_type arg = 0) {
..
}
public:
~App_Foo() {
APP_HNDLR::on_close();
}
void setup() {
...
// 最初のアプリハンドラを登録する
APP_HNDLR::new_hndlr(&App_Commander::hndr_screen_simple);
}
void loop() {
// 必須呼び出し
APP_HNDLR::loop();
...
}
};// APP_HNDLR<T>内のtypedef
typedef void (T::* tpf_func_handler)(event_type ev, arg_type evarg)class App_Foo : public APP_DEF, public APP_HNDLR<App_Foo> {
..
void hndr_scr_def(event_type ev, arg_type arg = 0) {
switch (ev) {
case EV_SETUP:
// setup()に相当、最初に1回だけ呼ばれる
break;
case EV_LOOP:
// loop()に相当
if (..) { // ある条件で次のアプリハンドラに遷移したい
// アプリハンドラ切り替え
APP_HNDLR::new_hndlr(&App_Foo::hndlr_scr_next);
return; // 通常はここでreturn
}
break;
case EV_EXIT;
// 終了時=アプリハンドラ切り替え時に呼び出される
// 注: サブアプリのデストラクタで APPHNDLR::on_close() を
// 記述してください
break;
}
};void APP_HNDLR::new_hndlr(tpf_func_handler hnd_next, arg_type arg = 0)void APP_HNDLR::loop(arg_type arg = 0)void APP_HNDLR::on_close()/// APPHNDLR_DCを継承したデータ格納クラスの定義
// publicアクセスで良いのでclassではなくstructで定義しています
struct DC_MyAppHndlr : public APPHNDLR_DC {
static const int CLS_ID = 0;
int get_class_id() { return CLS_ID; }
MySubApp &app;
// メンバ変数と操作関数
int data1;
void incr() { data1++ }
// サブアプリ内のthe_screenに対する操作
void display() { app.the_screen << data1; }
// コンストラクタ
DC_MyAppHndlr(MySubApp& app_) :
app(app_) // サブアプリオブジェクトを保存
, APPHNDLR_DC(CLS_ID) // APPHNDLR_DCの初期化
, data1(0) // メンバ変数の初期化
{}
}struct DC_My_AppHndlr;
//サブアプリ定義
class MySubApp : public TWE::APP_DEF, public APP_HNDLR<MySubApp> {
..
void hndr_MyApp(event_type ev, arg_type arg = 0); // アプリハンドラ関数
frined struct DC_MyAppHndlr; // friend宣言
}void MySubApp::hndr_MyApp(event_type ev, arg_type arg) {
auto&& dc = APP_HNDLR::use<DC_My_AppHndlr>();
switch(ev) {
case EV_SETUP:
...
break;
case EV_LOOP:
if (..) dc.incr();
break;
case EV_EXIT:
break;
}
}ユーティリティ関数
if (parse_ascii) { // アスキー形式のパーサーの解釈完了
auto&& pkt = newTwePacket(parse_ascii.get_payload());
if (identify_packet_type(pkt) == E_PKT::PKT_TWELITE) { // パケット解釈成功時
auto&& x = refTwePacketTwelite(pkt);
the_screen // LCDスクリーン上のターミナルに情報を表示
<< printfmt(":Lq=%d:Ad=%08X", x.u8lqi, x.u32addr_src)
<< printfmt(":ID=%02X", x.u8addr_src)
<< printfmt(":DI=%04b", x.DI_mask)
;
}
}struct PalDataInfo {
E_SNSCD e_data_source;
E_CAUSE e_data_cause;
};struct DataAppIO {
//送信元のシリアル#
uint32_t u32addr_src;
// 送信元の論理ID
uint8_t u8addr_src;
// 宛先の論理ID
uint8_t u8addr_dst;
// 送信時のタイムスタンプ
uint16_t u16timestamp;
// 低レイテンシ送信時のフラグ
bool b_lowlatency_tx;
// リピート中継回数
uint16_t u8rpt_cnt;
// LQI値
uint16_t u8lqi;
// DIの状態ビットマップ (LSBから順にDI1,2,3,4,...)
uint8_t DI_mask;
// DIのアクティブ(使用なら1)ビットマップ(LSBから順にDI1,2,3,4,...)
uint8_t DI_active_mask;
// DIが割り込み由来かどうかのビットマップ(LSBから順にDI1,2,3,4,...)
uint16_t DI_int_mask;
};