source: asp3_tinet_ecnl_rx/trunk/app3_human_detec/src/echonet_main.c@ 400

Last change on this file since 400 was 400, checked in by coas-nagasima, 5 years ago

ファイルヘッダーの更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 16.0 KB
Line 
1/*
2 * TOPPERS PROJECT Home Network Working Group Software
3 *
4 * Copyright (C) 2014-2019 Cores Co., Ltd. Japan
5 *
6 * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ
7 * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改
8 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する.
9 * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作
10 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー
11 * スコード中に含まれていること.
12 * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使
13 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用
14 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記
15 * の無保証規定を掲載すること.
16 * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使
17 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ
18 * と.
19 * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著
20 * 作権表示,この利用条件および下記の無保証規定を掲載すること.
21 * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに
22 * 報告すること.
23 * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損
24 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること.
25 * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理
26 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを
27 * 免責すること.
28 *
29 * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お
30 * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的
31 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ
32 * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ
33 * の責任を負わない.
34 *
35 * @(#) $Id$
36 */
37
38/*
39 * サンプルプログラム(1)の本体
40 */
41
42#include <kernel.h>
43#include <t_syslog.h>
44#include <t_stdlib.h>
45#include <sil.h>
46#include <string.h>
47#include "syssvc/serial.h"
48#include "syssvc/syslog.h"
49#include "kernel_cfg.h"
50#include "echonet_main.h"
51#include "echonet_cfg.h"
52#include "target_kernel_impl.h"
53
54/* TODO: メーカーコードを設定 */
55#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
56
57/* ノードプロファイルオブジェクト */
58struct ecn_cls0EF0_t node_profile_data = {
59 0x30, /* 動作状態 */
60 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
61 {
62 0xFE, /* 下位通信層IDフィールド */
63 { MAKER_CODE }, /* メーカーコード */
64 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
65 },
66 0x0000, /* 異常内容 */
67 { MAKER_CODE }, /* メーカーコード */
68};
69
70/* 人体検知センサクラス */
71struct ecn_cls0007_t human_detection_sensor_data = {
72 0x30, /* 動作状態 */
73 0x35, /* 検知閾値レベル設定(初期値として1~4が未検出、初期値として4~8が検出) */
74 0x31, /* 検知レベル状態(人体検知状態用)*/
75 0x00, /* 設置場所 */
76 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
77 0x42, /* 異常発生状態 */
78 { MAKER_CODE }, /* メーカーコード */
79};
80
81/*
82 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
83 */
84int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
85{
86 /* サイズが1以外は受け付けない */
87 if (size != 1)
88 return 0;
89
90 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
91
92 switch (*(uint8_t *)src) {
93 /* ONの場合 */
94 case 0x30:
95 *((uint8_t *)item->exinf) = *((uint8_t *)src);
96 /* LEDの"."をON */
97 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) | 0x40);
98 break;
99 /* OFFの場合 */
100 case 0x31:
101 *((uint8_t *)item->exinf) = *((uint8_t *)src);
102 /* LEDの"."をOFF */
103 sil_wrb_mem((uint8_t *)0x0008C02A, sil_reb_mem((uint8_t *)0x0008C02A) & ~0x40);
104 break;
105 /* 0x30か0x31以外は受け付けない */
106 default:
107 return 0;
108 }
109
110 return 1;
111}
112
113/*
114 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
115 */
116int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
117{
118 /* サイズが1以外は受け付けない */
119 if (size != 1)
120 return 0;
121
122 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
123
124 switch (*(uint8_t *)src) {
125 /* 異常発生ありの場合 */
126 case 0x41:
127 /* 異常発生なしの場合 */
128 case 0x42:
129 *((uint8_t *)item->exinf) = *((uint8_t *)src);
130 break;
131 /* 0x41か0x42以外は受け付けない */
132 default:
133 return 0;
134 }
135
136 return 1;
137}
138
139/*
140 * 検知閾値レベル設定設定関数
141 */
142int detection_threshold_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
143{
144 /* サイズが1以外は受け付けない */
145 if (size != 1)
146 return 0;
147
148 if ((*(uint8_t *)src >= 0x31) && (*(uint8_t *)src <= 0x38)) {
149 *((uint8_t *)item->exinf) = *((uint8_t *)src);
150 }
151 /* 上記以外は受け付けない */
152 else {
153 return 0;
154 }
155
156 return 1;
157}
158
159uint8_t led_disp[] = { 0x00, 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07 };
160
161/*
162 * 検知レベル設定関数
163 */
164int detection_state_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
165{
166 struct ecn_cls0007_t *eobj = (struct ecn_cls0007_t *)item->exinf;
167 ER ret;
168 T_EDATA *esv;
169 uint8_t prev_state;
170 uint8_t sseg = sil_reb_mem((uint8_t *)0x0008C02A) & ~0x07;
171
172 /* サイズが1以外は受け付けない */
173 if (size != 1)
174 return 0;
175
176 *anno = false;
177
178 if ((*(uint8_t *)src >= 0x31) && (*(uint8_t *)src <= 0x38)) {
179 /* 以前の検知レベルを保存 */
180 prev_state = eobj->state;
181 /* 検知レベル設定 */
182 eobj->state = *((uint8_t *)src);
183 /* LEDに検知レベルを表示 */
184 sil_wrb_mem((uint8_t *)0x0008C02A, sseg | led_disp[eobj->state - 0x30]);
185
186 /* 人体検知状態に変化があった場合 */
187 if ((prev_state < eobj->threshold) != (eobj->state < eobj->threshold)) {
188 /* プロパティ通知 */
189 *anno = true;
190 }
191 }
192 /* 上記以外は受け付けない */
193 else {
194 return 0;
195 }
196
197 return 1;
198}
199
200/*
201 * 人体検知状態取得関数
202 */
203int detection_state_get(const EPRPINIB *item, void *dst, int size)
204{
205 struct ecn_cls0007_t *eobj = (struct ecn_cls0007_t *)item->exinf;
206
207 /* 閾値より検知レベルが低い場合 */
208 if (eobj->state < eobj->threshold) {
209 /* 人体検知なし */
210 ((uint8_t *)dst)[0] = 0x42;
211 }
212 /* 閾値より検知レベルが高い場合 */
213 else {
214 /* 人体検知あり */
215 ((uint8_t *)dst)[0] = 0x41;
216 }
217
218 return 1;
219}
220
221static void main_initialize();
222static int main_get_timer();
223static void main_progress(int interval);
224static void main_recv_esv(T_EDATA *esv);
225static void main_break_wait(uint8_t *brkdat, int32_t len);
226static void main_timeout();
227
228/*
229 * メインタスク
230 */
231void echonet_main_task(intptr_t exinf)
232{
233 ER ret, ret2;
234 SYSTIM prev, now;
235 int timer;
236 T_EDATA *esv;
237 uint8_t brkdat[64];
238 int32_t len;
239
240 /* アプリケーションの初期化 */
241 main_initialize();
242
243 ret2 = get_tim(&now);
244 if (ret2 != E_OK) {
245 syslog(LOG_ERROR, "get_tim");
246 return;
247 }
248
249 for (;;) {
250 prev = now;
251
252 /* タイマー取得 */
253 timer = main_get_timer();
254
255 /* 応答電文待ち */
256 ret = ecn_trcv_esv(&esv, timer);
257 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
258 syslog(LOG_ERROR, "ecn_trcv_esv");
259 break;
260 }
261
262 ret2 = get_tim(&now);
263 if (ret2 != E_OK) {
264 syslog(LOG_ERROR, "get_tim");
265 break;
266 }
267
268 /* 時間経過 */
269 main_progress(now - prev);
270
271 /* Echonet電文受信の場合 */
272 if (ret == E_OK) {
273 /* Echonet電文受信処理 */
274 main_recv_esv(esv);
275
276 /* 領域解放 */
277 ret = ecn_rel_esv(esv);
278 if (ret != E_OK) {
279 syslog(LOG_ERROR, "ecn_rel_esv");
280 break;
281 }
282 }
283 /* 応答電文待ちの割り込みの場合 */
284 else if (ret == E_BRK) {
285 /* 応答電文待ちの割り込みデータ取得 */
286 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
287 if (ret != E_OK) {
288 syslog(LOG_ERROR, "ecn_get_brk_dat");
289 break;
290 }
291
292 /* 応答電文待ちの割り込み処理 */
293 main_break_wait(brkdat, len);
294
295 /* 領域解放 */
296 ret = ecn_rel_esv(esv);
297 if (ret != E_OK) {
298 syslog(LOG_ERROR, "ecn_rel_esv");
299 break;
300 }
301 }
302
303 /* タイムアウト処理 */
304 main_timeout();
305 }
306}
307
308void echonet_change_netif_link(uint8_t link_up, uint8_t up)
309{
310 ER ret;
311
312 if (link_up == 0)
313 return;
314
315 if (up) {
316 /* インスタンスリスト通知の送信 */
317 ret = ecn_ntf_inl();
318 if (ret != E_OK) {
319 syslog(LOG_ERROR, "ecn_ntf_inl");
320 }
321 }
322
323 /* メインタスクに通知 */
324 uint8_t data[2];
325 data[0] = 0x01;
326 data[1] = up ? 0x01 : 0x02;
327 ret = ecn_brk_wai(data, sizeof(data));
328 if (ret != E_OK) {
329 syslog(LOG_ERROR, "ecn_brk_wai");
330 return;
331 }
332}
333
334enum main_state_t {
335 main_state_start,
336 main_state_idle,
337};
338
339int main_timer = TMO_FEVR;
340enum main_state_t main_state = main_state_start;
341bool_t main_btn1_state;
342int main_btn1_count = 0;
343bool_t main_btn2_state;
344int main_btn2_count = 0;
345
346/*
347 * 初期化
348 */
349static void main_initialize()
350{
351 uint8_t btn1, btn2;
352
353 /*
354 * モジュールストップ機能の設定(S12AD)
355 */
356 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */
357 sil_wrw_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR,
358 sil_rew_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR) & ~SYSTEM_MSTPCRA_MSTPA17_BIT);
359 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */
360
361 /* LEDを"0000"と表示 */
362 sil_wrb_mem((uint8_t *)0x0008C02A, 0x00);
363
364 /* ECHONETミドルウェアを起動するのを待つ */
365 main_state = main_state_start;
366 main_timer = 1000 * 1000;
367
368 /* 12bitADC初期化 */
369 sil_wrh_mem((uint16_t *)S12AD_ADEXICR_ADDR, 0x0000); /* 温度センサ出力、内部基準電圧非選択 */
370 sil_wrh_mem((uint16_t *)S12AD_ADANS0_ADDR, 0x0001); /* 変換ポートAN000選択、AN001~AN015非選択 */
371 sil_wrh_mem((uint16_t *)S12AD_ADANS1_ADDR, 0x0000); /* 変換ポートAN016~AN020非選択 */
372
373 /* ボタン状態読み込み */
374 btn1 = sil_reb_mem((uint8_t *)0x0008C04A);
375 btn2 = sil_reb_mem((uint8_t *)0x0008C040);
376 main_btn1_state = (btn1 & 0x80) != 0;
377 main_btn2_state = (btn2 & 0x80) != 0;
378
379 /* メインタスクを起動 */
380 ER ret = act_tsk(MAIN_TASK);
381 if (ret != E_OK) {
382 syslog(LOG_ERROR, "act_tsk");
383 }
384}
385
386/*
387 * タイマー取得
388 */
389static int main_get_timer()
390{
391 return main_timer;
392}
393
394/*
395 * 時間経過
396 */
397static void main_progress(int interval)
398{
399 if (main_timer == TMO_FEVR)
400 return;
401
402 main_timer -= interval;
403 if (main_timer < 0) {
404 main_timer = 0;
405 }
406}
407
408/*
409 * Echonet電文受信処理
410 */
411static void main_recv_esv(T_EDATA *esv)
412{
413 ER ret;
414 uint8_t epc;
415 uint8_t pdc;
416 uint8_t p_edt[256];
417 T_ENUM_EPC enm;
418
419 ret = ecn_itr_ini(&enm, esv);
420 if (ret != E_OK) {
421 syslog(LOG_ERROR, "ecn_itr_ini");
422 return;
423 }
424
425 for (;;) {
426 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
427 switch (epc) {
428 case 0x80:
429 break;
430 case 0x81:
431 break;
432 }
433 }
434 if (ret != E_BOVR) {
435 syslog(LOG_ERROR, "ecn_itr_nxt");
436 break;
437 }
438 if (enm.is_eof)
439 break;
440 }
441}
442
443/*
444 * 応答電文待ちの割り込み処理
445 */
446static void main_break_wait(uint8_t *brkdat, int32_t len)
447{
448 switch (main_state) {
449 case main_state_idle:
450 break;
451 }
452}
453
454static uint8_t main_ad_level = 1;
455static uint16_t main_ad_table[64];
456#define main_ad_table_count (sizeof(main_ad_table) / sizeof(main_ad_table[0]))
457static int main_ad_pos = 0;
458static uint32_t main_ad_avelage;
459static int main_count;
460
461static void main_ad_change();
462static void main_btn1_change(bool_t push);
463static void main_btn2_change(bool_t push);
464
465/*
466 * タイムアウト処理
467 */
468static void main_timeout()
469{
470 ER ret;
471 uint8_t btn1, btn2;
472 uint16_t ad_value;
473 uint8_t ad_level;
474
475 if (main_timer != 0)
476 return;
477
478 switch (main_state) {
479 case main_state_start:
480 /* ECHONETミドルウェアを起動 */
481 ret = ecn_sta_svc();
482 if (ret != E_OK) {
483 syslog(LOG_ERROR, "ecn_sta_svc");
484 }
485
486 /* 10ms後にボタン状態を確認 */
487 main_state = main_state_idle;
488 main_timer = 10 * 1000;
489 break;
490 case main_state_idle:
491 /* 10ms後にボタン状態を確認 */
492 main_timer = 10 * 1000;
493
494 /* ADCの変換結果取得 */
495 if ((sil_reb_mem((uint8_t *)S12AD_ADCSR_ADDR) & S12AD_ADCSR_ADST_BIT) == 0) {
496 main_ad_avelage -= main_ad_table[main_ad_pos];
497 ad_value = sil_reh_mem((uint16_t *)S12AD_ADDR0_ADDR);
498 main_ad_table[main_ad_pos] = ad_value;
499 main_ad_avelage += ad_value;
500
501 main_ad_pos++;
502 if (main_ad_pos >= main_ad_table_count) {
503 main_ad_pos = 0;
504 }
505
506 ad_level = (((main_ad_avelage / main_ad_table_count) >> 9) & 0x7) + 1;
507 if (main_ad_level != ad_level) {
508 /* 1秒変化が続いたら */
509 if (main_count < 100) {
510 main_count++;
511 }
512 else {
513 main_ad_level = ad_level;
514
515 /* ADC状態変化処理 */
516 main_ad_change();
517 }
518 }
519 else {
520 main_count = 0;
521 }
522
523 /* 変換開始(シングルスキャンモード) */
524 sil_wrb_mem((uint8_t *)S12AD_ADCSR_ADDR, S12AD_ADCSR_ADST_BIT);
525 }
526
527 /* ボタン状態読み込み */
528 btn1 = sil_reb_mem((uint8_t *)0x0008C04A);
529 btn2 = sil_reb_mem((uint8_t *)0x0008C040);
530
531 /* ボタン1の処理 */
532 if (((btn1 & 0x80) != 0) && !main_btn1_state) {
533 main_btn1_count++;
534 if (main_btn1_count > 10) {
535 main_btn1_count = 0;
536 main_btn1_state = true;
537
538 main_btn1_change(true);
539 }
540 }
541 else if (((btn1 & 0x80) == 0) && main_btn1_state) {
542 main_btn1_count++;
543 if (main_btn1_count > 10) {
544 main_btn1_count = 0;
545 main_btn1_state = false;
546
547 main_btn1_change(false);
548 }
549 }
550
551 /* ボタン2の処理 */
552 if (((btn2 & 0x80) != 0) && !main_btn2_state) {
553 main_btn2_count++;
554 if (main_btn2_count > 10) {
555 main_btn2_count = 0;
556 main_btn2_state = true;
557
558 main_btn2_change(true);
559 }
560 }
561 else if (((btn2 & 0x80) == 0) && main_btn2_state) {
562 main_btn2_count++;
563 if (main_btn2_count > 10) {
564 main_btn2_count = 0;
565 main_btn2_state = false;
566
567 main_btn2_change(false);
568 }
569 }
570 break;
571 }
572}
573
574/*
575 * ADC状態変化処理
576 */
577static void main_ad_change()
578{
579 ER ret;
580 T_EDATA *esv;
581 uint8_t p_edt[1];
582
583 p_edt[0] = 0x30 + main_ad_level;
584
585 /* プロパティ設定電文作成 */
586 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
587 if (ret != E_OK) {
588 syslog(LOG_ERROR, "ecn_esv_setc");
589 return;
590 }
591
592 /* 電文送信 */
593 ecn_snd_esv(esv);
594}
595
596uint8_t main_level = 1;
597bool_t main_rev = false;
598
599/*
600 * ボタン1状態変化処理
601 */
602static void main_btn1_change(bool_t push)
603{
604 ER ret;
605 T_EDATA *esv;
606 uint8_t p_edt[1];
607
608 /* 押されて戻った時に処理する */
609 if (push)
610 return;
611
612 /* 人体検知状態 */
613 if (!main_rev) {
614 main_level--;
615 if (main_level < 1) {
616 main_level = 1;
617 main_rev = true;
618 }
619 }
620 else {
621 main_level++;
622 if (main_level > 8) {
623 main_level = 8;
624 main_rev = false;
625 }
626 }
627
628 p_edt[0] = 0x30 + main_level;
629
630 /* プロパティ設定電文作成 */
631 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
632 if (ret != E_OK) {
633 syslog(LOG_ERROR, "ecn_esv_setc");
634 return;
635 }
636
637 /* 電文送信 */
638 ecn_snd_esv(esv);
639}
640
641/*
642 * ボタン2状態変化処理
643 */
644static void main_btn2_change(bool_t push)
645{
646 ER ret;
647 T_EDATA *esv;
648 uint8_t p_edt[1];
649
650 /* 押されて戻った時に処理する */
651 if (push)
652 return;
653
654 /* 人体検知状態 */
655 if (!main_rev) {
656 main_level++;
657 if (main_level > 8) {
658 main_level = 8;
659 main_rev = false;
660 }
661 }
662 else {
663 main_level--;
664 if (main_level < 1) {
665 main_level = 1;
666 main_rev = true;
667 }
668 }
669
670 p_edt[0] = 0x30 + main_level;
671
672 /* プロパティ設定電文作成 */
673 ret = ecn_esv_setc(&esv, HUMAN_DETECTION_SENSOR_EOBJ, 0xB1, 1, p_edt);
674 if (ret != E_OK) {
675 syslog(LOG_ERROR, "ecn_esv_setc");
676 return;
677 }
678
679 /* 電文送信 */
680 ecn_snd_esv(esv);
681}
Note: See TracBrowser for help on using the repository browser.