source: asp3_tinet_ecnl_arm/trunk/app1_usb_watt_meter/src/echonet_main.c@ 374

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

mbed関連を更新
シリアルドライバをmbedのHALを使うよう変更
ファイルディスクリプタの処理を更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 27.3 KB
Line 
1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2016-2018 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#include "ff.h"
54#include "diskio.h"
55#include <tinet_defs.h>
56#include <tinet_config.h>
57#include <netinet/in.h>
58#include <netinet/in_var.h>
59#include <net/ethernet.h>
60#include <net/if_var.h>
61#include "gpio_api.h"
62#include "analogin_api.h"
63#include "rtc_api.h"
64#include "pinmap.h"
65#include "ntshell_main.h"
66#include "adafruit_st7735.h"
67#include "draw_font.h"
68#include "netcmd.h"
69
70extern uint8_t mac_addr[6];
71
72/* TODO: メーカーコードを設定 */
73#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
74
75/* ノードプロファイルオブジェクト */
76struct node_profile_object_t local_node_data = {
77 0x30, /* 動作状態 */
78 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
79 {
80 0xFE, /* 下位通信層IDフィールド */
81 { MAKER_CODE }, /* メーカーコード */
82 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
83 },
84 0,
85 { MAKER_CODE }, /* メーカーコード */
86};
87
88struct watt_hour_meter_t electric_energy_meter_data[6] = {
89 /* 電力量メータ1 */
90 {
91 0x30, /* 動作状態 */
92 0x00, /* 設置場所 */
93 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
94 0x41, /* 異常発生状態 */
95 { MAKER_CODE }, /* メーカーコード */
96 0x02, /* 積算電力量単位 */
97 0x00000000, /* 積算電力量計測値 */
98 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, }, /* 積算電力量計測値履歴1 */
99 },
100 /* 電力量メータ2 */
101 {
102 0x30, /* 動作状態 */
103 0x00, /* 設置場所 */
104 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
105 0x41, /* 異常発生状態 */
106 {MAKER_CODE}, /* メーカーコード */
107 0x02, /* 積算電力量単位 */
108 0x00000000, /* 積算電力量計測値 */
109 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}, /* 積算電力量計測値履歴1 */
110 },
111 /* 電力量メータ3 */
112 {
113 0x30, /* 動作状態 */
114 0x00, /* 設置場所 */
115 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
116 0x41, /* 異常発生状態 */
117 {MAKER_CODE}, /* メーカーコード */
118 0x02, /* 積算電力量単位 */
119 0x00000000, /* 積算電力量計測値 */
120 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}, /* 積算電力量計測値履歴1 */
121 },
122 /* 電力量メータ4 */
123 {
124 0x30, /* 動作状態 */
125 0x00, /* 設置場所 */
126 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
127 0x41, /* 異常発生状態 */
128 {MAKER_CODE}, /* メーカーコード */
129 0x02, /* 積算電力量単位 */
130 0x00000000, /* 積算電力量計測値 */
131 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}, /* 積算電力量計測値履歴1 */
132 },
133 /* 電力量メータ5 */
134 {
135 0x30, /* 動作状態 */
136 0x00, /* 設置場所 */
137 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
138 0x41, /* 異常発生状態 */
139 {MAKER_CODE}, /* メーカーコード */
140 0x02, /* 積算電力量単位 */
141 0x00000000, /* 積算電力量計測値 */
142 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}, /* 積算電力量計測値履歴1 */
143 },
144 /* 電力量メータ6 */
145 {
146 0x30, /* 動作状態 */
147 0x00, /* 設置場所 */
148 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
149 0x41, /* 異常発生状態 */
150 {MAKER_CODE}, /* メーカーコード */
151 0x02, /* 積算電力量単位 */
152 0x00000000, /* 積算電力量計測値 */
153 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000,}, /* 積算電力量計測値履歴1 */
154 }
155};
156
157/* 電源LED */
158gpio_t pow_led;
159
160/*
161 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
162 */
163int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
164{
165 /* サイズが1以外は受け付けない */
166 if (size != 1)
167 return 0;
168
169 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
170
171 switch (*(uint8_t *)src) {
172 /* ONの場合 */
173 case 0x30:
174 *((uint8_t *)item->exinf) = *((uint8_t *)src);
175 /* LEDをON */
176 gpio_write(&pow_led, 1);
177 break;
178 /* OFFの場合 */
179 case 0x31:
180 *((uint8_t *)item->exinf) = *((uint8_t *)src);
181 /* LEDをOFF */
182 gpio_write(&pow_led, 0);
183 break;
184 /* 0x30か0x31以外は受け付けない */
185 default:
186 return 0;
187 }
188
189 return 1;
190}
191
192/*
193 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
194 */
195int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
196{
197 /* サイズが1以外は受け付けない */
198 if (size != 1)
199 return 0;
200
201 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
202
203 switch (*(uint8_t *)src) {
204 /* 異常発生ありの場合 */
205 case 0x41:
206 /* 異常発生なしの場合 */
207 case 0x42:
208 *((uint8_t *)item->exinf) = *((uint8_t *)src);
209 break;
210 /* 0x41か0x42以外は受け付けない */
211 default:
212 return 0;
213 }
214
215 return 1;
216}
217
218/*
219 * 現在時刻設定関数
220 */
221int time_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
222{
223 uint8_t *p_src;
224 time_t temp;
225 struct tm _tm;
226
227 if (size != 2)
228 return 0;
229
230 temp = rtc_read();
231 gmtime_r(&temp, &_tm);
232
233 /* 時刻設定 */
234 p_src = (uint8_t *)src;
235 _tm.tm_hour = *p_src++;
236 _tm.tm_min = *p_src++;
237 _tm.tm_sec = 0x00;
238
239 temp = mktime(&_tm);
240 rtc_write(temp);
241
242 return (intptr_t)p_src - (intptr_t)src;
243}
244
245/*
246 * 現在時刻取得関数
247 */
248int time_prop_get(const EPRPINIB *item, void *dst, int size)
249{
250 uint8_t *p_dst;
251 time_t temp;
252 struct tm _tm;
253
254 if (size != 2)
255 return 0;
256
257 temp = rtc_read();
258 gmtime_r(&temp, &_tm);
259
260 /* 時刻設定 */
261 p_dst = (uint8_t *)dst;
262 *p_dst++ = _tm.tm_hour;
263 *p_dst++ = _tm.tm_min;
264
265 return (intptr_t)p_dst - (intptr_t)dst;
266}
267
268/*
269 * 現在年月日設定関数
270 */
271int date_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
272{
273 const uint8_t *p_src;
274 time_t temp;
275 struct tm _tm;
276
277 if (size != 4)
278 return 0;
279
280 temp = rtc_read();
281 gmtime_r(&temp, &_tm);
282
283 /* 年月日設定 */
284 p_src = (uint8_t *)src;
285 _tm.tm_year = (*p_src++ * 100) + *p_src++;
286 _tm.tm_mon = (*p_src++) - 1;
287 _tm.tm_mday = *p_src++;
288
289 temp = mktime(&_tm);
290 rtc_write(temp);
291
292 return (intptr_t)p_src - (intptr_t)src;
293}
294
295/*
296 * 現在年月日取得関数
297 */
298int date_prop_get(const EPRPINIB *item, void *dst, int size)
299{
300 uint8_t *p_dst;
301 time_t temp;
302 struct tm _tm;
303
304 if (size != 4)
305 return 0;
306
307 temp = rtc_read();
308 gmtime_r(&temp, &_tm);
309
310 p_dst = (uint8_t *)dst;
311 *p_dst++ = _tm.tm_year / 100;
312 *p_dst++ = _tm.tm_year % 100;
313 *p_dst++ = _tm.tm_mon + 1;
314 *p_dst++ = _tm.tm_mday;
315
316 return (intptr_t)p_dst - (intptr_t)dst;
317}
318
319/*
320 * 積算電力量計測値取得関数
321 */
322int watt_hour_meter_integral_electric_energy_measurement_value_get(const EPRPINIB *item, void *dst, int size)
323{
324 struct watt_hour_meter_t *meter = (struct watt_hour_meter_t *)(item->exinf - (intptr_t)&((struct watt_hour_meter_t *)0)->integral_electric_energy_measurement_value);
325
326 /* サイズが4以外は受け付けない */
327 if (size != 4)
328 return 0;
329
330 *((uint32_t *)dst) = meter->integral_electric_energy_measurement_value;
331
332 return 4;
333}
334
335int watt_hour_meter_integral_electric_energy_measurement_log_get(const EPRPINIB *item, void *dst, int size)
336{
337 struct watt_hour_meter_t *meter = (struct watt_hour_meter_t *)(item->exinf - (intptr_t)&((struct watt_hour_meter_t *)0)->integral_electric_energy_measurement_log);
338 int len;
339
340 /* サイズが192以外は受け付けない */
341 if (size != 192)
342 return 0;
343
344 wai_sem(MAIN_SEMAPHORE);
345
346 len = 48 - meter->current_pos;
347 if (len > 0)
348 memcpy(dst, &meter->integral_electric_energy_measurement_log[meter->current_pos], sizeof(uint32_t) * len);
349 dst = &((uint8_t *)dst)[len];
350 len = 48 - len;
351 if (len > 0)
352 memcpy(dst, &meter->integral_electric_energy_measurement_log[0], sizeof(uint32_t) * len);
353
354 sig_sem(MAIN_SEMAPHORE);
355
356 return 192;
357}
358
359static uint32_t whm_add_integral_value(struct watt_hour_meter_t *meter, uint32_t watt_hour)
360{
361 bool_t carry;
362 uint32_t value = watt_hour;
363 int current_pos = meter->current_pos;
364 current_pos++;
365 if (current_pos >= 48)
366 current_pos = 0;
367
368 carry = value >= 100000000;
369 if (carry)
370 value -= 100000000;
371
372 wai_sem(MAIN_SEMAPHORE);
373
374 meter->integral_electric_energy_measurement_value = value;
375 meter->integral_electric_energy_measurement_log[current_pos] = value;
376 meter->current_pos = current_pos;
377
378 sig_sem(MAIN_SEMAPHORE);
379
380 return carry ? 100000000 : 0;
381}
382
383static void main_initialize();
384static int main_get_timer();
385static void main_progress(int interval);
386static void main_recv_esv(T_EDATA *esv);
387static void main_break_wait(uint8_t *brkdat, int32_t len);
388static void main_timeout();
389
390/*
391 * メインタスク
392 */
393void echonet_main_task(intptr_t exinf)
394{
395 ER ret, ret2;
396 SYSTIM prev, now;
397 int timer;
398 T_EDATA *esv;
399 uint8_t brkdat[64];
400 int32_t len;
401
402 /* アプリケーションの初期化 */
403 main_initialize();
404
405 ret2 = get_tim(&now);
406 if (ret2 != E_OK) {
407 syslog(LOG_ERROR, "get_tim");
408 return;
409 }
410
411 for (;;) {
412 prev = now;
413
414 /* タイマー取得 */
415 timer = main_get_timer();
416
417 /* 応答電文待ち */
418 ret = ecn_trcv_esv(&esv, timer);
419 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
420 syslog(LOG_ERROR, "ecn_trcv_esv");
421 break;
422 }
423
424 ret2 = get_tim(&now);
425 if (ret2 != E_OK) {
426 syslog(LOG_ERROR, "get_tim");
427 break;
428 }
429
430 /* 時間経過 */
431 main_progress(now - prev);
432
433 /* Echonet電文受信の場合 */
434 if (ret == E_OK) {
435 /* Echonet電文受信処理 */
436 main_recv_esv(esv);
437
438 /* 領域解放 */
439 ret = ecn_rel_esv(esv);
440 if (ret != E_OK) {
441 syslog(LOG_ERROR, "ecn_rel_esv");
442 break;
443 }
444 }
445 /* 応答電文待ちの割り込みの場合 */
446 else if (ret == E_BRK) {
447 /* 応答電文待ちの割り込みデータ取得 */
448 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
449 if (ret != E_OK) {
450 syslog(LOG_ERROR, "ecn_get_brk_dat");
451 break;
452 }
453
454 /* 応答電文待ちの割り込み処理 */
455 main_break_wait(brkdat, len);
456
457 /* 領域解放 */
458 ret = ecn_rel_esv(esv);
459 if (ret != E_OK) {
460 syslog(LOG_ERROR, "ecn_rel_esv");
461 break;
462 }
463 }
464
465 /* タイムアウト処理 */
466 main_timeout();
467 }
468}
469
470void echonet_change_netif_link(uint8_t link_up, uint8_t up)
471{
472 ER ret;
473
474 if (link_up == 0)
475 return;
476
477 if (up) {
478 /* インスタンスリスト通知の送信 */
479 ret = ecn_ntf_inl();
480 if (ret != E_OK) {
481 syslog(LOG_ERROR, "ecn_ntf_inl");
482 }
483 }
484
485 /* メインタスクに通知 */
486 uint8_t data[2];
487 data[0] = 0x01;
488 data[1] = (up ? 0x01 : 0x02) | (link_up ? 0x10 : 0x20);
489 ret = ecn_brk_wai(data, sizeof(data));
490 if (ret != E_OK) {
491 syslog(LOG_ERROR, "ecn_brk_wai");
492 return;
493 }
494}
495
496enum main_state_t {
497 main_state_start,
498 main_state_idle,
499};
500
501int main_timer = TMO_FEVR;
502enum main_state_t main_state = main_state_start;
503int main_lcd_state = 0;
504int main_lcd_timer = TMO_FEVR;
505int main_adv_timer = TMO_FEVR;
506int main_whm_counter;
507
508analogin_t analogin[6];
509gpio_t user_btn;
510
511/* ジョイスティック種別 */
512#define BUTTON_NONE 0
513#define BUTTON_DOWN 1
514#define BUTTON_LEFT 2
515#define BUTTON_SELECT 3
516#define BUTTON_UP 4
517#define BUTTON_RIGHT 5
518
519analogin_t joystick;
520static uint8_t main_read_button(analogin_t *obj);
521
522bool_t main_btn1_state;
523int main_btn1_count = 0;
524bool_t main_btn2_state;
525int main_btn2_count = 0;
526
527LCD_Handler_t lcd;
528LCD_DrawProp_t drawProp;
529
530/*
531 * 初期化
532 */
533static void main_initialize()
534{
535 uint8_t btn;
536
537 /* LEDの初期化 */
538 gpio_init_out(&pow_led, LED_USER);
539
540 /* アナログ入力の初期化 */
541 analogin_init(&analogin[0], A0);
542 analogin_init(&analogin[1], A1);
543 analogin_init(&analogin[2], A2);
544 analogin_init(&analogin[3], A3);
545 analogin_init(&analogin[4], A4);
546 analogin_init(&analogin[5], A5);
547
548 /* ユーザーボタンの初期化 */
549 gpio_init_in(&user_btn, USER_BUTTON0);
550
551 /* ジョイスティックの初期化 */
552 analogin_init(&joystick, P1_12);
553
554 /* ECHONETミドルウェアを起動するのを待つ */
555 main_state = main_state_start;
556 main_timer = 1000 * 1000;
557
558 btn = main_read_button(&joystick);
559 main_btn1_state = btn == BUTTON_LEFT;
560 main_btn2_state = btn == BUTTON_RIGHT;
561
562 // 1.8" TFTの初期化
563 spi_init(&lcd.hspi, P10_14, P10_15, P10_12, NC);
564 spi_format(&lcd.hspi, 8, 0, 0);
565 spi_frequency(&lcd.hspi, 4000000);
566
567 gpio_init_out(&lcd.cs_pin, P10_13);
568 gpio_init_out(&lcd.rs_pin, P8_15);
569 gpio_init_out(&lcd.rst_pin, P8_14);
570 gpio_init_out(&lcd.cs2_pin, NC);
571
572 lcd_initR(&lcd, /*INITR_REDTAB?*/INITR_18BLACKTAB);
573
574 drawProp.hlcd = &lcd;
575 drawProp.TextColor = ST7735_BLACK;
576 drawProp.BackColor = ST7735_WHITE;
577 drawProp.pFont = NULL;
578 lcd_fillScreen(&drawProp);
579
580 /* 1秒後にLCD表示を更新 */
581 main_lcd_state = 10;
582 main_lcd_timer = 1000 * 1000;
583
584 /* 1秒後に表示を更新 */
585 main_adv_timer = 1000 * 1000;
586
587 /* メインタスクを起動 */
588 ER ret = act_tsk(MAIN_TASK);
589 if (ret != E_OK) {
590 syslog(LOG_ERROR, "act_tsk");
591 }
592}
593
594/*
595 * タイマー取得
596 */
597static int main_get_timer()
598{
599 int result = main_timer;
600
601 if ((result == TMO_FEVR)
602 || ((main_lcd_timer != TMO_FEVR) && (main_lcd_timer < result))) {
603 result = main_lcd_timer;
604 }
605
606 if ((result == TMO_FEVR)
607 || ((main_adv_timer != TMO_FEVR) && (main_adv_timer < result))) {
608 result = main_adv_timer;
609 }
610
611 return result;
612}
613
614/*
615 * 時間経過
616 */
617static void main_progress(int interval)
618{
619 if (main_timer != TMO_FEVR) {
620 main_timer -= interval;
621 if (main_timer < 0) {
622 main_timer = 0;
623 }
624 }
625
626 if (main_lcd_timer != TMO_FEVR) {
627 main_lcd_timer -= interval;
628 if (main_lcd_timer < 0) {
629 main_lcd_timer = 0;
630 }
631 }
632
633 if (main_adv_timer != TMO_FEVR) {
634 main_adv_timer -= interval;
635 if (main_adv_timer < 0) {
636 main_adv_timer = 0;
637 }
638 }
639}
640
641/*
642 * Echonet電文受信処理
643 */
644static void main_recv_esv(T_EDATA *esv)
645{
646 ER ret;
647 uint8_t epc;
648 uint8_t pdc;
649 uint8_t p_edt[256];
650 T_ENUM_EPC enm;
651
652 ret = ecn_itr_ini(&enm, esv);
653 if (ret != E_OK) {
654 syslog(LOG_ERROR, "ecn_itr_ini");
655 return;
656 }
657
658 for (;;) {
659 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
660 switch (epc) {
661 case 0x80:
662 break;
663 case 0x81:
664 break;
665 }
666 }
667 if (ret != E_BOVR) {
668 syslog(LOG_ERROR, "ecn_itr_nxt");
669 break;
670 }
671 if (enm.is_eof)
672 break;
673 }
674}
675
676/*
677 * 応答電文待ちの割り込み処理
678 */
679static void main_break_wait(uint8_t *brkdat, int32_t len)
680{
681 char mac_text[30] = "mac: ";
682 char ipaddr_text[30] = "ipadr: ";
683 const T_IN4_ADDR *ip4_addr;
684 int pos;
685
686 switch (main_state) {
687 case main_state_idle:
688 if (len == 0)
689 break;
690
691 switch (brkdat[0]) {
692 case 1:
693 switch (brkdat[1] >> 4) {
694 case 1:
695 break;
696 case 2:
697 break;
698 }
699
700 pos = str_macaddr(&mac_text[4], sizeof(mac_text) - 4, mac_addr, 0);
701 mac_text[pos + 4] = '\0';
702 lcd_drawString(&lcd, mac_text, X_LINE_TO_PIX(&lcd, 0), Y_ROW_TO_PIX(&lcd, 11), ST7735_BLACK, ST7735_WHITE);
703
704 ip4_addr = in4_get_ifaddr(0);
705 pos = str_ipv4addr(&ipaddr_text[6], sizeof(ipaddr_text) - 6, ip4_addr, 0);
706 ipaddr_text[pos + 6] = '\0';
707 lcd_drawString(&lcd, ipaddr_text, X_LINE_TO_PIX(&lcd, 0), Y_ROW_TO_PIX(&lcd, 12), ST7735_BLACK, ST7735_WHITE);
708 }
709 break;
710 }
711}
712
713static void main_ontimer();
714static void main_lcd_ontimer();
715static void main_adv_ontimer();
716
717/*
718 * タイムアウト処理
719 */
720static void main_timeout()
721{
722 if (main_timer == 0) {
723 main_ontimer();
724 }
725
726 if (main_lcd_timer == 0) {
727 main_lcd_ontimer();
728 }
729
730 if (main_adv_timer == 0) {
731 main_adv_ontimer();
732 }
733}
734
735#define main_7seg_count 4
736static uint8_t main_7seg[6][main_7seg_count];
737
738static void main_lcd_ontimer()
739{
740 char text[] = "No.0 電流:0.00A";
741 char *btn_texts[] = { "none ", "down ", "left ", "select", "up ", "right " };
742 int port_no, btn;
743
744 switch (main_lcd_state) {
745 case 0:
746 case 1:
747 case 2:
748 case 3:
749 case 4:
750 case 5:
751 port_no = main_lcd_state;
752 text[14] = '0' + main_7seg[port_no][1];
753 text[16] = '0' + main_7seg[port_no][2];
754 text[17] = '0' + main_7seg[port_no][3];
755 lcd_drawString(&lcd, &text[14], X_LINE_HALF_TO_PIX(&lcd, 11), Y_ROW_TO_PIX(&lcd, main_lcd_state + 2), ST7735_BLACK, ST7735_WHITE);
756 main_lcd_state++;
757 break;
758 case 6:
759 btn = main_read_button(&joystick);
760 lcd_drawString(&lcd, btn_texts[btn], X_LINE_TO_PIX(&lcd, 0), Y_ROW_TO_PIX(&lcd, 9), ST7735_BLACK, ST7735_WHITE);
761 main_lcd_state++;
762 break;
763 case 9:
764 main_lcd_state = 0;
765 break;
766 case 10:
767 lcd_drawString(&lcd, "USB電力計", X_LINE_TO_PIX(&lcd, 6), Y_ROW_TO_PIX(&lcd, 0), ST7735_BLACK, ST7735_WHITE);
768 for (port_no = 0; port_no < 6; port_no++) {
769 text[3] = '1' + port_no;
770 lcd_drawString(&lcd, text, X_LINE_TO_PIX(&lcd, 0), Y_ROW_TO_PIX(&lcd, port_no + 2), ST7735_BLACK, ST7735_WHITE);
771 }
772 main_lcd_state = 0;
773 break;
774 default:
775 main_lcd_state++;
776 break;
777 }
778
779 /* 100ms後にLCD表示を更新 */
780 main_lcd_timer = 100 * 1000;
781}
782
783#define main_ad_count 8
784#define main_ad_table_count 64
785static uint16_t main_ad_table[main_ad_count][main_ad_table_count];
786static int main_ad_pos = 0;
787static uint32_t main_ad_avelage[main_ad_count];
788static uint64_t main_ad_integral[main_ad_count];
789
790uint8_t main_port_no = 1;
791static void main_7seg_view(int port_no, int ad);
792static void main_btn1_change(bool_t push);
793static void main_btn2_change(bool_t push);
794
795/*
796 * タイムアウト処理
797 */
798static void main_ontimer()
799{
800 ER ret;
801 uint8_t btn;
802 uint16_t ad_value;
803
804 switch (main_state) {
805 case main_state_start:
806 /* ECHONETミドルウェアを起動 */
807 ret = ecn_sta_svc();
808 if (ret != E_OK) {
809 syslog(LOG_ERROR, "ecn_sta_svc");
810 }
811
812 /* 10ms後にボタン状態を確認 */
813 main_state = main_state_idle;
814 main_timer = 10 * 1000;
815 break;
816 case main_state_idle:
817 /* 10ms後にボタン状態を確認 */
818 main_timer = 10 * 1000;
819
820 /* ADCの変換結果取得 */
821 for (int i = 0; i < main_ad_count; i++) {
822 main_ad_avelage[i] -= main_ad_table[i][main_ad_pos];
823 ad_value = analogin_read_u16(&analogin[i]); // 16bit値取得
824 main_ad_integral[i] += 5/*[V]*/ * (ad_value >> 4)/*[A]*/; // 積算値
825 main_ad_table[i][main_ad_pos] = ad_value;
826 main_ad_avelage[i] += ad_value;
827 }
828
829 main_ad_pos++;
830 if (main_ad_pos >= main_ad_table_count) {
831 main_ad_pos = 0;
832 }
833
834 main_whm_counter += 10;
835 if (main_whm_counter >= 1250/* 180000=30分 */) {
836 main_whm_counter = 0;
837
838 for (int i = 0; i < 6; i++) {
839 uint64_t carry;
840 carry = whm_add_integral_value(&electric_energy_meter_data[i],
841 main_ad_integral[i] / ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/)));
842
843 main_ad_integral[i] -= carry * ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/));
844 }
845
846 if (electric_energy_meter_data[0].current_pos == 0) {
847 cmd_execute("logupload", NULL);
848 }
849 }
850
851 /* ボタン状態読み込み */
852 btn = main_read_button(&joystick);
853
854 /* ボタン1の処理 */
855 if ((btn == BUTTON_LEFT) && !main_btn1_state) {
856 main_btn1_count++;
857 if (main_btn1_count > 10) {
858 main_btn1_count = 0;
859 main_btn1_state = true;
860
861 main_btn1_change(true);
862 }
863 }
864 else if ((btn != BUTTON_LEFT) && main_btn1_state) {
865 main_btn1_count++;
866 if (main_btn1_count > 10) {
867 main_btn1_count = 0;
868 main_btn1_state = false;
869
870 main_btn1_change(false);
871 }
872 }
873
874 /* ボタン2の処理 */
875 if ((btn == BUTTON_RIGHT) && !main_btn2_state) {
876 main_btn2_count++;
877 if (main_btn2_count > 10) {
878 main_btn2_count = 0;
879 main_btn2_state = true;
880
881 main_btn2_change(true);
882 }
883 }
884 else if ((btn != BUTTON_RIGHT) && main_btn2_state) {
885 main_btn2_count++;
886 if (main_btn2_count > 10) {
887 main_btn2_count = 0;
888 main_btn2_state = false;
889
890 main_btn2_change(false);
891 }
892 }
893
894 main_7seg_view(1, false);
895 main_7seg_view(2, false);
896 main_7seg_view(3, false);
897 main_7seg_view(4, false);
898 main_7seg_view(5, false);
899 main_7seg_view(6, false);
900
901 break;
902 }
903}
904
905static uint8_t main_read_button(analogin_t *obj)
906{
907 int a = analogin_read_u16(obj);
908
909 a *= 5;
910
911 //printf("Button read analog = %f\r\n",a);
912 if (a < (int)(0.2 * 65536))
913 return BUTTON_DOWN;
914 if (a < (int)(1.0 * 65536))
915 return BUTTON_RIGHT;
916 if (a < (int)(1.7 * 65536))
917 return BUTTON_SELECT;
918 if (a < (int)(2.6 * 65536))
919 return BUTTON_UP;
920 if (a < (int)(4.6 * 65536))
921 return BUTTON_LEFT;
922 else
923 return BUTTON_NONE;
924}
925
926bool_t main_rev = false;
927
928/*
929 * ボタン1状態変化処理
930 */
931static void main_btn1_change(bool_t push)
932{
933 /* 押されて戻った時に処理する */
934 if (push)
935 return;
936
937 /* 表示ポート番号 */
938 if (!main_rev) {
939 main_port_no--;
940 if (main_port_no < 1) {
941 main_port_no = 1;
942 main_rev = true;
943 main_adv_timer = 2000 * 1000;
944 }
945 }
946 else {
947 main_port_no++;
948 if (main_port_no > main_ad_count) {
949 main_port_no = main_ad_count;
950 main_rev = false;
951 main_adv_timer = 2000 * 1000;
952 }
953 }
954}
955
956/*
957 * ボタン2状態変化処理
958 */
959static void main_btn2_change(bool_t push)
960{
961 /* 押されて戻った時に処理する */
962 if (push)
963 return;
964
965 int swt = gpio_read(&user_btn);
966 if (swt == 0) {
967 return;
968 }
969
970 /* 表示ポート番号 */
971 if (!main_rev) {
972 main_port_no++;
973 if (main_port_no > main_ad_count) {
974 main_port_no = main_ad_count;
975 main_rev = false;
976 main_adv_timer = 2000 * 1000;
977 }
978 }
979 else {
980 main_port_no--;
981 if (main_port_no < 1) {
982 main_port_no = 1;
983 main_rev = true;
984 main_adv_timer = 2000 * 1000;
985 }
986 }
987}
988
989static void main_adv_ontimer()
990{
991 int swt = gpio_read(&user_btn);
992 if (swt != 0) {
993 main_adv_timer = TMO_FEVR;
994 return;
995 }
996
997 main_port_no++;
998 if (main_port_no > main_ad_count)
999 main_port_no = 1;
1000
1001 main_adv_timer = 2000 * 1000;
1002}
1003
1004static void main_7seg_view(int port_no, int ad)
1005{
1006 if ((port_no < 1) || (port_no > main_ad_count))
1007 return;
1008
1009 port_no--;
1010
1011 uint32_t adv = (main_ad_avelage[port_no] / main_ad_table_count);
1012
1013 if (ad) {
1014 main_7seg[port_no][0] = port_no + 1;
1015 main_7seg[port_no][1] = (adv & 0xF000) >> 12;
1016 main_7seg[port_no][2] = (adv & 0x0F00) >> 8;
1017 main_7seg[port_no][3] = (adv & 0x00F0) >> 4;
1018 }
1019 else {
1020 uint32_t tmp = adv / 26214;
1021
1022 main_7seg[port_no][0] = port_no + 1;
1023 main_7seg[port_no][1] = tmp;
1024 adv = 10 * (adv - tmp * 26214);
1025 tmp = adv / 26214;
1026 main_7seg[port_no][2] = tmp;
1027 adv = 10 * (adv - tmp * 26214);
1028 tmp = adv / 26214;
1029 main_7seg[port_no][3] = tmp;
1030 }
1031}
Note: See TracBrowser for help on using the repository browser.