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

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

arm向けASP3版ECNLを追加

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 27.0 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 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
470bool_t started = false;
471
472void echonet_change_netif_link(uint8_t link_up, uint8_t up)
473{
474 ER ret;
475
476 if (link_up == 0)
477 return;
478
479 if (up && !started) {
480 started = true;
481
482 /* ECHONETミドルウェアを起動 */
483 ret = ecn_sta_svc();
484 if (ret != E_OK)
485 return;
486
487 /* ECHONETミドルウェアを起動するのを待つ */
488 dly_tsk(100);
489 }
490
491 /* メインタスクに通知 */
492 uint8_t data[2];
493 data[0] = 0x01;
494 data[1] = (up ? 0x01 : 0x02) | (link_up ? 0x10 : 0x20);
495 ret = ecn_brk_wai(data, sizeof(data));
496 if (ret != E_OK) {
497 syslog(LOG_ERROR, "ecn_brk_wai");
498 return;
499 }
500}
501
502enum main_state_t{
503 main_state_idle,
504};
505
506int main_timer = TMO_FEVR;
507enum main_state_t main_state = main_state_idle;
508int main_lcd_state = 0;
509int main_lcd_timer = TMO_FEVR;
510int main_adv_timer = TMO_FEVR;
511int main_whm_counter;
512
513analogin_t analogin[6];
514gpio_t user_btn;
515
516/* ジョイスティック種別 */
517#define BUTTON_NONE 0
518#define BUTTON_DOWN 1
519#define BUTTON_LEFT 2
520#define BUTTON_SELECT 3
521#define BUTTON_UP 4
522#define BUTTON_RIGHT 5
523
524analogin_t joystick;
525static uint8_t main_read_button(analogin_t *obj);
526
527bool_t main_btn1_state;
528int main_btn1_count = 0;
529bool_t main_btn2_state;
530int main_btn2_count = 0;
531
532LCD_Handler_t lcd;
533LCD_DrawProp_t drawProp;
534
535/*
536 * 初期化
537 */
538static void main_initialize()
539{
540 uint8_t btn;
541
542 /* LEDの初期化 */
543 gpio_init_out(&pow_led, LED_USER);
544
545 /* アナログ入力の初期化 */
546 analogin_init(&analogin[0], A0);
547 analogin_init(&analogin[1], A1);
548 analogin_init(&analogin[2], A2);
549 analogin_init(&analogin[3], A3);
550 analogin_init(&analogin[4], A4);
551 analogin_init(&analogin[5], A5);
552
553 /* ユーザーボタンの初期化 */
554 gpio_init_in(&user_btn, USER_BUTTON0);
555
556 /* ジョイスティックの初期化 */
557 analogin_init(&joystick, P1_12);
558
559 /* 10ms後にボタン状態を確認 */
560 main_timer = 10 * 1000;
561
562 /* ボタン状態読み込み */
563 btn = main_read_button(&joystick);
564 main_btn1_state = btn == BUTTON_LEFT;
565 main_btn2_state = btn == BUTTON_RIGHT;
566
567 // 1.8" TFTの初期化
568 spi_init(&lcd.hspi, P10_14, P10_15, P10_12, NC);
569 spi_format(&lcd.hspi, 8, 0, 0);
570 spi_frequency(&lcd.hspi, 1000000);
571
572 gpio_init_out(&lcd.cs_pin, P10_13);
573 gpio_init_out(&lcd.rs_pin, P8_15);
574 gpio_init_out(&lcd.rst_pin, P8_14);
575 gpio_init_out(&lcd.cs2_pin, NC);
576
577 lcd_initR(&lcd, /*INITR_REDTAB?*/INITR_18BLACKTAB);
578
579 drawProp.hlcd = &lcd;
580 drawProp.TextColor = ST7735_BLACK;
581 drawProp.BackColor = ST7735_WHITE;
582 drawProp.pFont = NULL;
583 lcd_fillScreen(&drawProp);
584
585 /* 1秒後にLCD表示を更新 */
586 main_lcd_state = 10;
587 main_lcd_timer = 1000 * 1000;
588
589 /* 1秒後に表示を更新 */
590 main_adv_timer = 1000 * 1000;
591
592 ER ret = act_tsk(MAIN_TASK);
593 if (ret != E_OK) {
594 syslog(LOG_ERROR, "act_tsk");
595 }
596}
597
598/*
599 * タイマー取得
600 */
601static int main_get_timer()
602{
603 int result = main_timer;
604
605 if((result == TMO_FEVR)
606 || ((main_lcd_timer != TMO_FEVR) && (main_lcd_timer < result))){
607 result = main_lcd_timer;
608 }
609
610 if ((result == TMO_FEVR)
611 || ((main_adv_timer != TMO_FEVR) && (main_adv_timer < result))) {
612 result = main_adv_timer;
613 }
614
615 return result;
616}
617
618/*
619 * 時間経過
620 */
621static void main_progress(int interval)
622{
623 if(main_timer != TMO_FEVR){
624 main_timer -= interval;
625 if(main_timer < 0){
626 main_timer = 0;
627 }
628 }
629
630 if(main_lcd_timer != TMO_FEVR){
631 main_lcd_timer -= interval;
632 if(main_lcd_timer < 0){
633 main_lcd_timer = 0;
634 }
635 }
636
637 if (main_adv_timer != TMO_FEVR) {
638 main_adv_timer -= interval;
639 if (main_adv_timer < 0) {
640 main_adv_timer = 0;
641 }
642 }
643}
644
645/*
646 * Echonet電文受信処理
647 */
648static void main_recv_esv(T_EDATA *esv)
649{
650 ER ret;
651 uint8_t epc;
652 uint8_t pdc;
653 uint8_t p_edt[256];
654 T_ENUM_EPC enm;
655
656 ret = ecn_itr_ini(&enm, esv);
657 if(ret != E_OK){
658 syslog(LOG_ERROR, "ecn_itr_ini");
659 return;
660 }
661
662 for(;;) {
663 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
664 switch (epc) {
665 case 0x80:
666 break;
667 case 0x81:
668 break;
669 }
670 }
671 if(ret != E_BOVR){
672 syslog(LOG_ERROR, "ecn_itr_nxt");
673 break;
674 }
675 if(enm.is_eof)
676 break;
677 }
678}
679
680/*
681 * 応答電文待ちの割り込み処理
682 */
683static void main_break_wait(uint8_t *brkdat, int32_t len)
684{
685 char mac_text[30] = "mac: ";
686 char ipaddr_text[30] = "ipaddr: ";
687 T_IN4_ADDR *ip4_addr;
688 int pos;
689
690 switch(main_state){
691 case main_state_idle:
692 if (len == 0)
693 break;
694
695 switch (brkdat[0]) {
696 case 1:
697 switch (brkdat[1] >> 4) {
698 case 1:
699 break;
700 case 2:
701 break;
702 }
703
704 pos = str_macaddr(&mac_text[4], sizeof(mac_text) - 4, mac_addr, 0);
705 mac_text[pos + 4] = '\0';
706 lcd_drawString(&lcd, mac_text, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 14) + 10, ST7735_BLACK, ST7735_WHITE);
707
708 ip4_addr = in4_get_ifaddr(0);
709 pos = str_ipv4addr(&ipaddr_text[7], sizeof(ipaddr_text) - 7, ip4_addr, 0);
710 ipaddr_text[pos + 7] = '\0';
711 lcd_drawString(&lcd, ipaddr_text, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 15) + 10, ST7735_BLACK, ST7735_WHITE);
712 }
713 break;
714 }
715}
716
717static void main_ontimer();
718static void main_lcd_ontimer();
719static void main_adv_ontimer();
720
721/*
722 * タイムアウト処理
723 */
724static void main_timeout()
725{
726 if(main_timer == 0){
727 main_ontimer();
728 }
729
730 if(main_lcd_timer == 0){
731 main_lcd_ontimer();
732 }
733
734 if (main_adv_timer == 0) {
735 main_adv_ontimer();
736 }
737}
738
739#define main_7seg_count 4
740static uint8_t main_7seg[6][main_7seg_count];
741
742static void main_lcd_ontimer()
743{
744 char text[] = "No.0 電流:0.00A";
745 char *btn_texts[] = { "none ", "down ", "left ", "select", "up ", "right " };
746 int port_no, btn;
747
748 switch(main_lcd_state) {
749 case 0:
750 case 1:
751 case 2:
752 case 3:
753 case 4:
754 case 5:
755 port_no = main_lcd_state;
756 text[14] = '0' + main_7seg[port_no][1];
757 text[16] = '0' + main_7seg[port_no][2];
758 text[17] = '0' + main_7seg[port_no][3];
759 lcd_drawString(&lcd, &text[14], X_LINE_HALF_TO_PIX(&lcd, 11) + 10, Y_ROW_TO_PIX(&lcd, main_lcd_state + 4) + 10, ST7735_BLACK, ST7735_WHITE);
760 main_lcd_state++;
761 break;
762 case 6:
763 btn = main_read_button(&joystick);
764 lcd_drawString(&lcd, btn_texts[btn], X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, 10) + 10, ST7735_BLACK, ST7735_WHITE);
765 main_lcd_state++;
766 break;
767 case 9:
768 main_lcd_state = 0;
769 break;
770 case 10:
771 lcd_drawString(&lcd, "USB電力計", X_LINE_TO_PIX(&lcd, 10) + 10, Y_ROW_TO_PIX(&lcd, 0) + 10, ST7735_BLACK, ST7735_WHITE);
772 for (port_no = 0; port_no < 6; port_no++) {
773 text[3] = '1' + port_no;
774 lcd_drawString(&lcd, text, X_LINE_TO_PIX(&lcd, 0) + 10, Y_ROW_TO_PIX(&lcd, port_no + 4) + 10, ST7735_BLACK, ST7735_WHITE);
775 }
776 main_lcd_state = 0;
777 break;
778 default:
779 main_lcd_state++;
780 break;
781 }
782
783 /* 100ms後にLCD表示を更新 */
784 main_lcd_timer = 100 * 1000;
785}
786
787#define main_ad_count 8
788#define main_ad_table_count 64
789static uint16_t main_ad_table[main_ad_count][main_ad_table_count];
790static int main_ad_pos = 0;
791static uint32_t main_ad_avelage[main_ad_count];
792static uint64_t main_ad_integral[main_ad_count];
793
794uint8_t main_port_no = 1;
795static void main_7seg_view(int port_no, int ad);
796static void main_btn1_change(bool_t push);
797static void main_btn2_change(bool_t push);
798
799/*
800 * タイムアウト処理
801 */
802static void main_ontimer()
803{
804 uint8_t btn;
805 uint16_t ad_value;
806
807 switch(main_state){
808 case main_state_idle:
809 /* 10ms後にボタン状態を確認 */
810 main_timer = 10 * 1000;
811
812 /* ADCの変換結果取得 */
813 for (int i = 0; i < main_ad_count; i++) {
814 main_ad_avelage[i] -= main_ad_table[i][main_ad_pos];
815 ad_value = analogin_read_u16(&analogin[i]); // 16bit値取得
816 main_ad_integral[i] += 5/*[V]*/ * (ad_value >> 4)/*[A]*/; // 積算値
817 main_ad_table[i][main_ad_pos] = ad_value;
818 main_ad_avelage[i] += ad_value;
819 }
820
821 main_ad_pos++;
822 if (main_ad_pos >= main_ad_table_count) {
823 main_ad_pos = 0;
824 }
825
826 main_whm_counter += 10;
827 if (main_whm_counter >= 1250/* 180000=30分 */) {
828 main_whm_counter = 0;
829
830 for (int i = 0; i < 6; i++) {
831 uint64_t carry;
832 carry = whm_add_integral_value(&electric_energy_meter_data[i],
833 main_ad_integral[i] / ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/)));
834
835 main_ad_integral[i] -= carry * ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/));
836 }
837
838 if (electric_energy_meter_data[0].current_pos == 0) {
839 cmd_execute("logupload", NULL);
840 }
841 }
842
843 /* ボタン状態読み込み */
844 btn = main_read_button(&joystick);
845
846 /* ボタン1の処理 */
847 if((btn == BUTTON_LEFT) && !main_btn1_state){
848 main_btn1_count++;
849 if(main_btn1_count > 10){
850 main_btn1_count = 0;
851 main_btn1_state = true;
852
853 main_btn1_change(true);
854 }
855 }
856 else if((btn != BUTTON_LEFT) && main_btn1_state){
857 main_btn1_count++;
858 if(main_btn1_count > 10){
859 main_btn1_count = 0;
860 main_btn1_state = false;
861
862 main_btn1_change(false);
863 }
864 }
865
866 /* ボタン2の処理 */
867 if((btn == BUTTON_RIGHT) && !main_btn2_state){
868 main_btn2_count++;
869 if(main_btn2_count > 10){
870 main_btn2_count = 0;
871 main_btn2_state = true;
872
873 main_btn2_change(true);
874 }
875 }
876 else if((btn != BUTTON_RIGHT) && main_btn2_state){
877 main_btn2_count++;
878 if(main_btn2_count > 10){
879 main_btn2_count = 0;
880 main_btn2_state = false;
881
882 main_btn2_change(false);
883 }
884 }
885
886 main_7seg_view(1, false);
887 main_7seg_view(2, false);
888 main_7seg_view(3, false);
889 main_7seg_view(4, false);
890 main_7seg_view(5, false);
891 main_7seg_view(6, false);
892
893 break;
894 }
895}
896
897static uint8_t main_read_button(analogin_t *obj)
898{
899 float a = analogin_read(obj);
900
901 a *= 5.0;
902
903 //printf("Button read analog = %f\r\n",a);
904 if (a < 0.2)
905 return BUTTON_DOWN;
906 if (a < 1.0)
907 return BUTTON_RIGHT;
908 if (a < 1.7)
909 return BUTTON_SELECT;
910 if (a < 2.6)
911 return BUTTON_UP;
912 if (a < 4.6)
913 return BUTTON_LEFT;
914 else
915 return BUTTON_NONE;
916}
917
918bool_t main_rev = false;
919
920/*
921 * ボタン1状態変化処理
922 */
923static void main_btn1_change(bool_t push)
924{
925 /* 押されて戻った時に処理する */
926 if(push)
927 return;
928
929 /* 表示ポート番号 */
930 if(!main_rev){
931 main_port_no--;
932 if(main_port_no < 1){
933 main_port_no = 1;
934 main_rev = true;
935 main_adv_timer = 2000 * 1000;
936 }
937 }
938 else{
939 main_port_no++;
940 if(main_port_no > main_ad_count){
941 main_port_no = main_ad_count;
942 main_rev = false;
943 main_adv_timer = 2000 * 1000;
944 }
945 }
946}
947
948/*
949 * ボタン2状態変化処理
950 */
951static void main_btn2_change(bool_t push)
952{
953 /* 押されて戻った時に処理する */
954 if(push)
955 return;
956
957 int swt = gpio_read(&user_btn);
958 if (swt == 0) {
959 return;
960 }
961
962 /* 表示ポート番号 */
963 if(!main_rev){
964 main_port_no++;
965 if(main_port_no > main_ad_count){
966 main_port_no = main_ad_count;
967 main_rev = false;
968 main_adv_timer = 2000 * 1000;
969 }
970 }
971 else{
972 main_port_no--;
973 if(main_port_no < 1){
974 main_port_no = 1;
975 main_rev = true;
976 main_adv_timer = 2000 * 1000;
977 }
978 }
979}
980
981static void main_adv_ontimer()
982{
983 int swt = gpio_read(&user_btn);
984 if (swt != 0) {
985 main_adv_timer = TMO_FEVR;
986 return;
987 }
988
989 main_port_no++;
990 if(main_port_no > main_ad_count)
991 main_port_no = 1;
992
993 main_adv_timer = 2000 * 1000;
994}
995
996static void main_7seg_view(int port_no, int ad)
997{
998 if ((port_no < 1) || (port_no > main_ad_count))
999 return;
1000
1001 port_no--;
1002
1003 uint32_t adv = (main_ad_avelage[port_no] / main_ad_table_count);
1004
1005 if (ad) {
1006 main_7seg[port_no][0] = port_no + 1;
1007 main_7seg[port_no][1] = (adv & 0xF000) >> 12;
1008 main_7seg[port_no][2] = (adv & 0x0F00) >> 8;
1009 main_7seg[port_no][3] = (adv & 0x00F0) >> 4;
1010 }
1011 else {
1012 uint32_t tmp = adv / 26214;
1013
1014 main_7seg[port_no][0] = port_no + 1;
1015 main_7seg[port_no][1] = tmp;
1016 adv = 10 * (adv - tmp * 26214);
1017 tmp = adv / 26214;
1018 main_7seg[port_no][2] = tmp;
1019 adv = 10 * (adv - tmp * 26214);
1020 tmp = adv / 26214;
1021 main_7seg[port_no][3] = tmp;
1022 }
1023}
Note: See TracBrowser for help on using the repository browser.