source: asp3_tinet_ecnl_rx/trunk/app1_usb_watt_meter/src/echonet_main.c@ 364

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

TINETとSocket APIなどを更新

  • Property svn:eol-style set to native
  • Property svn:mime-type set to text/x-csrc;charset=UTF-8
File size: 26.9 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 "ntshell_main.h"
62
63/* TODO: メーカーコードを設定 */
64#define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */
65
66/* ノードプロファイルオブジェクト */
67struct node_profile_object_t local_node_data = {
68 0x30, /* 動作状態 */
69 { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */
70 {
71 0xFE, /* 下位通信層IDフィールド */
72 { MAKER_CODE }, /* メーカーコード */
73 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
74 },
75 0,
76 { MAKER_CODE }, /* メーカーコード */
77};
78
79struct watt_hour_meter_t electric_energy_meter_data[6] = {
80 /* 電力量メータ1 */
81 {
82 0x30, /* 動作状態 */
83 0x00, /* 設置場所 */
84 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
85 0x41, /* 異常発生状態 */
86 { MAKER_CODE }, /* メーカーコード */
87 0x02, /* 積算電力量単位 */
88 0x00000000, /* 積算電力量計測値 */
89 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
90 },
91 /* 電力量メータ2 */
92 {
93 0x30, /* 動作状態 */
94 0x00, /* 設置場所 */
95 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
96 0x41, /* 異常発生状態 */
97 {MAKER_CODE}, /* メーカーコード */
98 0x02, /* 積算電力量単位 */
99 0x00000000, /* 積算電力量計測値 */
100 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
101 },
102 /* 電力量メータ3 */
103 {
104 0x30, /* 動作状態 */
105 0x00, /* 設置場所 */
106 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
107 0x41, /* 異常発生状態 */
108 {MAKER_CODE}, /* メーカーコード */
109 0x02, /* 積算電力量単位 */
110 0x00000000, /* 積算電力量計測値 */
111 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
112 },
113 /* 電力量メータ4 */
114 {
115 0x30, /* 動作状態 */
116 0x00, /* 設置場所 */
117 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
118 0x41, /* 異常発生状態 */
119 {MAKER_CODE}, /* メーカーコード */
120 0x02, /* 積算電力量単位 */
121 0x00000000, /* 積算電力量計測値 */
122 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
123 },
124 /* 電力量メータ5 */
125 {
126 0x30, /* 動作状態 */
127 0x00, /* 設置場所 */
128 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
129 0x41, /* 異常発生状態 */
130 {MAKER_CODE}, /* メーカーコード */
131 0x02, /* 積算電力量単位 */
132 0x00000000, /* 積算電力量計測値 */
133 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
134 },
135 /* 電力量メータ6 */
136 {
137 0x30, /* 動作状態 */
138 0x00, /* 設置場所 */
139 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
140 0x41, /* 異常発生状態 */
141 {MAKER_CODE}, /* メーカーコード */
142 0x02, /* 積算電力量単位 */
143 0x00000000, /* 積算電力量計測値 */
144 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
145 }
146};
147
148/*
149 * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け)
150 */
151int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
152{
153 /* サイズが1以外は受け付けない */
154 if (size != 1)
155 return 0;
156
157 *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src);
158
159 switch (*(uint8_t *)src) {
160 /* ONの場合 */
161 case 0x30:
162 *((uint8_t *)item->exinf) = *((uint8_t *)src);
163 /* LEDの"."をON */
164 sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) | 0x01);
165 break;
166 /* OFFの場合 */
167 case 0x31:
168 *((uint8_t *)item->exinf) = *((uint8_t *)src);
169 /* LEDの"."をOFF */
170 sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) & ~0x01);
171 break;
172 /* 0x30か0x31以外は受け付けない */
173 default:
174 return 0;
175 }
176
177 return 1;
178}
179
180/*
181 * 異常発生状態設定関数(0x41, 0x42のみ受け付け)
182 */
183int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
184{
185 /* サイズが1以外は受け付けない */
186 if (size != 1)
187 return 0;
188
189 *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src);
190
191 switch (*(uint8_t *)src) {
192 /* 異常発生ありの場合 */
193 case 0x41:
194 /* 異常発生なしの場合 */
195 case 0x42:
196 *((uint8_t *)item->exinf) = *((uint8_t *)src);
197 break;
198 /* 0x41か0x42以外は受け付けない */
199 default:
200 return 0;
201 }
202
203 return 1;
204}
205
206/*
207 * 現在時刻設定関数
208 */
209int time_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
210{
211 uint8_t *p_src;
212
213 if (size != 2)
214 return 0;
215
216 /* 時刻設定 */
217 p_src = (uint8_t *)src;
218 sil_wrb_mem((uint8_t *)RTC_RHRCNT_ADDR, *p_src++);
219 sil_wrb_mem((uint8_t *)RTC_RMINCNT_ADDR, *p_src++);
220 sil_wrb_mem((uint8_t *)RTC_RSECCNT_ADDR, 0x00);
221
222 return (intptr_t)p_src - (intptr_t)src;
223}
224
225/*
226 * 現在時刻取得関数
227 */
228int time_prop_get(const EPRPINIB *item, void *dst, int size)
229{
230 uint8_t *p_dst;
231
232 if (size != 2)
233 return 0;
234
235 /* 時刻設定 */
236 p_dst = (uint8_t *)dst;
237 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RHRCNT_ADDR);
238 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMINCNT_ADDR);
239
240 return (intptr_t)p_dst - (intptr_t)dst;
241}
242
243/*
244 * 現在年月日設定関数
245 */
246int date_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
247{
248 uint8_t *p_src;
249
250 if (size != 4)
251 return 0;
252
253 /* 年月日設定 */
254 p_src = (uint8_t *)src;
255 p_src++; /* 20XX */
256 sil_wrb_mem((uint8_t *)RTC_RYRCNT_ADDR, *p_src++);
257 sil_wrb_mem((uint8_t *)RTC_RMONCNT_ADDR, *p_src++);
258 sil_wrb_mem((uint8_t *)RTC_RDAYCNT_ADDR, *p_src++);
259
260 return (intptr_t)p_src - (intptr_t)src;
261}
262
263/*
264 * 現在年月日取得関数
265 */
266int date_prop_get(const EPRPINIB *item, void *dst, int size)
267{
268 uint8_t *p_dst;
269
270 if (size != 4)
271 return 0;
272
273 p_dst = (uint8_t *)dst;
274 *p_dst++ = 0x20;
275 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RYRCNT_ADDR);
276 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMONCNT_ADDR);
277 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RDAYCNT_ADDR);
278
279 return (intptr_t)p_dst - (intptr_t)dst;
280}
281
282/*
283 * 積算電力量計測値取得関数
284 */
285int watt_hour_meter_integral_electric_energy_measurement_value_get(const EPRPINIB *item, void *dst, int size)
286{
287 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);
288
289 /* サイズが4以外は受け付けない */
290 if (size != 4)
291 return 0;
292
293 *((uint32_t *)dst) = meter->integral_electric_energy_measurement_value;
294
295 return 4;
296}
297
298int watt_hour_meter_integral_electric_energy_measurement_log_get(const EPRPINIB *item, void *dst, int size)
299{
300 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);
301 int len;
302
303 /* サイズが192以外は受け付けない */
304 if (size != 192)
305 return 0;
306
307 wai_sem(MAIN_SEMAPHORE);
308
309 len = 48 - meter->current_pos;
310 if (len > 0)
311 memcpy(dst, &meter->integral_electric_energy_measurement_log[meter->current_pos], sizeof(uint32_t) * len);
312 dst = &((uint8_t *)dst)[len];
313 len = 48 - len;
314 if (len > 0)
315 memcpy(dst, &meter->integral_electric_energy_measurement_log[0], sizeof(uint32_t) * len);
316
317 sig_sem(MAIN_SEMAPHORE);
318
319 return 192;
320}
321
322static uint32_t whm_add_integral_value(struct watt_hour_meter_t *meter, uint32_t watt_hour)
323{
324 bool_t carry;
325 uint32_t value = watt_hour;
326 int current_pos = meter->current_pos;
327 current_pos++;
328 if (current_pos >= 48)
329 current_pos = 0;
330
331 carry = value >= 100000000;
332 if (carry)
333 value -= 100000000;
334
335 wai_sem(MAIN_SEMAPHORE);
336
337 meter->integral_electric_energy_measurement_value = value;
338 meter->integral_electric_energy_measurement_log[current_pos] = value;
339 meter->current_pos = current_pos;
340
341 sig_sem(MAIN_SEMAPHORE);
342
343 return carry ? 100000000 : 0;
344}
345
346static void main_initialize();
347static int main_get_timer();
348static void main_progress(int interval);
349static void main_recv_esv(T_EDATA *esv);
350static void main_break_wait(uint8_t *brkdat, int32_t len);
351static void main_timeout();
352
353/*
354 * メインタスク
355 */
356void echonet_main_task(intptr_t exinf)
357{
358 ER ret, ret2;
359 SYSTIM prev, now;
360 int timer;
361 T_EDATA *esv;
362 uint8_t brkdat[64];
363 int32_t len;
364
365 /* アプリケーションの初期化 */
366 main_initialize();
367
368 ret2 = get_tim(&now);
369 if (ret2 != E_OK) {
370 syslog(LOG_ERROR, "get_tim");
371 return;
372 }
373
374 for (;;) {
375 prev = now;
376
377 /* タイマー取得 */
378 timer = main_get_timer();
379
380 /* 応答電文待ち */
381 ret = ecn_trcv_esv(&esv, timer);
382 if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)) {
383 syslog(LOG_ERROR, "ecn_trcv_esv");
384 break;
385 }
386
387 ret2 = get_tim(&now);
388 if (ret2 != E_OK) {
389 syslog(LOG_ERROR, "get_tim");
390 break;
391 }
392
393 /* 時間経過 */
394 main_progress(now - prev);
395
396 /* Echonet電文受信の場合 */
397 if (ret == E_OK) {
398 /* Echonet電文受信処理 */
399 main_recv_esv(esv);
400
401 /* 領域解放 */
402 ret = ecn_rel_esv(esv);
403 if (ret != E_OK) {
404 syslog(LOG_ERROR, "ecn_rel_esv");
405 break;
406 }
407 }
408 /* 応答電文待ちの割り込みの場合 */
409 else if (ret == E_BRK) {
410 /* 応答電文待ちの割り込みデータ取得 */
411 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
412 if (ret != E_OK) {
413 syslog(LOG_ERROR, "ecn_get_brk_dat");
414 break;
415 }
416
417 /* 応答電文待ちの割り込み処理 */
418 main_break_wait(brkdat, len);
419
420 /* 領域解放 */
421 ret = ecn_rel_esv(esv);
422 if (ret != E_OK) {
423 syslog(LOG_ERROR, "ecn_rel_esv");
424 break;
425 }
426 }
427
428 /* タイムアウト処理 */
429 main_timeout();
430 }
431}
432
433void echonet_change_netif_link(uint8_t link_up, uint8_t up)
434{
435 ER ret;
436
437 if (link_up == 0)
438 return;
439
440 if (up) {
441 /* インスタンスリスト通知の送信 */
442 ret = ecn_ntf_inl();
443 if (ret != E_OK) {
444 syslog(LOG_ERROR, "ecn_ntf_inl");
445 }
446 }
447
448 /* メインタスクに通知 */
449 uint8_t data[2];
450 data[0] = 0x01;
451 data[1] = up ? 0x01 : 0x02;
452 ret = ecn_brk_wai(data, sizeof(data));
453 if (ret != E_OK) {
454 syslog(LOG_ERROR, "ecn_brk_wai");
455 return;
456 }
457}
458
459enum main_state_t {
460 main_state_start,
461 main_state_idle,
462};
463
464int main_timer = TMO_FEVR;
465enum main_state_t main_state = main_state_start;
466int main_lcd_timer = TMO_FEVR;
467int main_adv_timer = TMO_FEVR;
468int main_whm_counter;
469
470bool_t main_btn1_state;
471int main_btn1_count = 0;
472bool_t main_btn2_state;
473int main_btn2_count = 0;
474
475/*
476 * 初期化
477 */
478static void main_initialize()
479{
480 uint8_t btn;
481
482 /*
483 * モジュールストップ機能の設定(S12AD)
484 */
485 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */
486 sil_wrw_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR,
487 sil_rew_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR) & ~SYSTEM_MSTPCRA_MSTPA17_BIT);
488 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */
489
490 /* 7seg_1100用ポート出力設定 */
491 sil_wrb_mem((uint8_t *)PORT2_PDR_ADDR, sil_reb_mem((uint8_t *)PORT2_PDR_ADDR) | PORT_PDR_B4_BIT | PORT_PDR_B3_BIT);
492 /* 7seg_0010用ポート出力設定 */
493 sil_wrb_mem((uint8_t *)PORT5_PDR_ADDR, sil_reb_mem((uint8_t *)PORT5_PDR_ADDR) | PORT_PDR_B3_BIT);
494 /* 7seg_0001用ポート出力設定 */
495 sil_wrb_mem((uint8_t *)PORTC_PDR_ADDR, sil_reb_mem((uint8_t *)PORTC_PDR_ADDR) | PORT_PDR_B1_BIT);
496 /* 7seg_led用ポート出力設定 */
497 sil_wrb_mem((uint8_t *)PORTD_PDR_ADDR, 0xFF);
498 /* SWITCH用ポート入力、LED用ポート出力設定 */
499 sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F);
500
501 /* LEDを"0000"と表示 */
502 sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F);
503
504 /* 3ms後に7SEG表示を更新 */
505 main_lcd_timer = 3 * 1000;
506
507 /* ECHONETミドルウェアを起動するのを待つ */
508 main_state = main_state_start;
509 main_timer = 1000 * 1000;
510
511 /* 12bitADC初期化 */
512 sil_wrh_mem((uint16_t *)S12AD_ADEXICR_ADDR, 0x0000); /* 温度センサ出力、内部基準電圧非選択 */
513 sil_wrh_mem((uint16_t *)S12AD_ADANS0_ADDR, 0x00FF); /* 変換ポートAN000~AN007選択、AN008~AN015非選択 */
514 sil_wrh_mem((uint16_t *)S12AD_ADANS1_ADDR, 0x0000); /* 変換ポートAN016~AN020非選択 */
515
516 /* ボタン状態読み込み */
517 btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR);
518 main_btn1_state = (btn & 0x20) != 0;
519 main_btn2_state = (btn & 0x80) != 0;
520
521 /* 1秒後に表示を更新 */
522 main_adv_timer = 1000 * 1000;
523
524 /* メインタスクを起動 */
525 ER ret = act_tsk(MAIN_TASK);
526 if (ret != E_OK) {
527 syslog(LOG_ERROR, "act_tsk");
528 }
529}
530
531/*
532 * タイマー取得
533 */
534static int main_get_timer()
535{
536 int result = main_timer;
537
538 if ((result == TMO_FEVR)
539 || ((main_lcd_timer != TMO_FEVR) && (main_lcd_timer < result))) {
540 result = main_lcd_timer;
541 }
542
543 if ((result == TMO_FEVR)
544 || ((main_adv_timer != TMO_FEVR) && (main_adv_timer < result))) {
545 result = main_adv_timer;
546 }
547
548 return result;
549}
550
551/*
552 * 時間経過
553 */
554static void main_progress(int interval)
555{
556 if (main_timer != TMO_FEVR) {
557 main_timer -= interval;
558 if (main_timer < 0) {
559 main_timer = 0;
560 }
561 }
562
563 if (main_lcd_timer != TMO_FEVR) {
564 main_lcd_timer -= interval;
565 if (main_lcd_timer < 0) {
566 main_lcd_timer = 0;
567 }
568 }
569
570 if (main_adv_timer != TMO_FEVR) {
571 main_adv_timer -= interval;
572 if (main_adv_timer < 0) {
573 main_adv_timer = 0;
574 }
575 }
576}
577
578/*
579 * Echonet電文受信処理
580 */
581static void main_recv_esv(T_EDATA *esv)
582{
583 ER ret;
584 uint8_t epc;
585 uint8_t pdc;
586 uint8_t p_edt[256];
587 T_ENUM_EPC enm;
588
589 ret = ecn_itr_ini(&enm, esv);
590 if (ret != E_OK) {
591 syslog(LOG_ERROR, "ecn_itr_ini");
592 return;
593 }
594
595 for (;;) {
596 while ((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
597 switch (epc) {
598 case 0x80:
599 break;
600 case 0x81:
601 break;
602 }
603 }
604 if (ret != E_BOVR) {
605 syslog(LOG_ERROR, "ecn_itr_nxt");
606 break;
607 }
608 if (enm.is_eof)
609 break;
610 }
611}
612
613/*
614 * 応答電文待ちの割り込み処理
615 */
616static void main_break_wait(uint8_t *brkdat, int32_t len)
617{
618 switch (main_state) {
619 case main_state_idle:
620 if (len == 0)
621 break;
622
623 switch (brkdat[0]) {
624 case 1:
625 switch (brkdat[1]) {
626 case 1:
627 break;
628 case 2:
629 break;
630 }
631 }
632 break;
633 }
634}
635
636static void main_ontimer();
637static void main_lcd_ontimer();
638static void main_adv_ontimer();
639
640/*
641 * タイムアウト処理
642 */
643static void main_timeout()
644{
645 if (main_timer == 0) {
646 main_ontimer();
647 }
648
649 if (main_lcd_timer == 0) {
650 main_lcd_ontimer();
651 }
652
653 if (main_adv_timer == 0) {
654 main_adv_ontimer();
655 }
656}
657
658#define main_7seg_count 4
659static uint8_t main_7seg[main_7seg_count] = { 0xDA, 0xF2, 0xB6, 0xB6 };
660static int main_7seg_pos = 0;
661const uint8_t led_disp[] = { 0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE4, 0xFE, 0xF6, 0xEE, 0x3E, 0x1A, 0x7A, 0x9E, 0x8E };
662
663static void main_lcd_ontimer()
664{
665 /* 7Seg表示 */
666 sil_wrb_mem((uint8_t *)PORTD_PODR_ADDR, ~main_7seg[main_7seg_pos]);
667
668 if (main_7seg_pos == 0)
669 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
670 & ~PORT_PODR_B4_BIT);
671 else
672 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
673 | PORT_PODR_B4_BIT);
674 if (main_7seg_pos == 1)
675 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
676 & ~PORT_PODR_B3_BIT);
677 else
678 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
679 | PORT_PODR_B3_BIT);
680 if (main_7seg_pos == 2)
681 sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR)
682 & ~PORT_PODR_B3_BIT);
683 else
684 sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR)
685 | PORT_PODR_B3_BIT);
686 if (main_7seg_pos == 3)
687 sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR)
688 & ~PORT_PODR_B1_BIT);
689 else
690 sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR)
691 | PORT_PODR_B1_BIT);
692
693 main_7seg_pos = (main_7seg_pos + 1) & 0x3;
694
695 /* 3ms後に7SEG表示を更新 */
696 main_lcd_timer = 3 * 1000;
697}
698
699#define main_ad_count 8
700#define main_ad_table_count 64
701static uint16_t main_ad_table[main_ad_count][main_ad_table_count];
702static int main_ad_pos = 0;
703static uint32_t main_ad_avelage[main_ad_count];
704static uint64_t main_ad_integral[main_ad_count];
705volatile uint16_t *const main_ad_addr[main_ad_count] = {
706 (uint16_t *)S12AD_ADDR0_ADDR,
707 (uint16_t *)S12AD_ADDR1_ADDR,
708 (uint16_t *)S12AD_ADDR2_ADDR,
709 (uint16_t *)S12AD_ADDR3_ADDR,
710 (uint16_t *)S12AD_ADDR4_ADDR,
711 (uint16_t *)S12AD_ADDR5_ADDR,
712 (uint16_t *)S12AD_ADDR6_ADDR,
713 (uint16_t *)S12AD_ADDR7_ADDR,
714};
715
716uint8_t main_port_no = 1;
717static void main_7seg_view(int port_no);
718static void main_btn1_change(bool_t push);
719static void main_btn2_change(bool_t push);
720
721/*
722 * タイムアウト処理
723 */
724static void main_ontimer()
725{
726 ER ret;
727 uint8_t btn;
728 uint16_t ad_value;
729
730 switch (main_state) {
731 case main_state_start:
732 /* ECHONETミドルウェアを起動 */
733 ret = ecn_sta_svc();
734 if (ret != E_OK) {
735 syslog(LOG_ERROR, "ecn_sta_svc");
736 }
737
738 /* 10ms後にボタン状態を確認 */
739 main_state = main_state_idle;
740 main_timer = 10 * 1000;
741 break;
742 case main_state_idle:
743 /* 10ms後にボタン状態を確認 */
744 main_timer = 10 * 1000;
745
746 /* ADCの変換結果取得 */
747 if ((sil_reb_mem((uint8_t *)S12AD_ADCSR_ADDR) & S12AD_ADCSR_ADST_BIT) == 0) {
748 for (int i = 0; i < main_ad_count; i++) {
749 main_ad_avelage[i] -= main_ad_table[i][main_ad_pos];
750 ad_value = sil_reh_mem(main_ad_addr[i]); // 12bit値取得
751 main_ad_integral[i] += 5/*[V]*/ * ad_value/*[A]*/; // 12bit積算値
752 ad_value = (ad_value << 4) | (ad_value >> 12); // 16bit拡張
753 main_ad_table[i][main_ad_pos] = ad_value;
754 main_ad_avelage[i] += ad_value;
755 }
756
757 main_ad_pos++;
758 if (main_ad_pos >= main_ad_table_count) {
759 main_ad_pos = 0;
760 }
761
762 /* 変換開始(シングルスキャンモード) */
763 sil_wrb_mem((uint8_t *)S12AD_ADCSR_ADDR, S12AD_ADCSR_ADST_BIT);
764 }
765
766 main_whm_counter += 10;
767 if (main_whm_counter >= 1250/* 180000=30分 */) {
768 main_whm_counter = 0;
769
770 for (int i = 0; i < 6; i++) {
771 uint64_t carry;
772 carry = whm_add_integral_value(&electric_energy_meter_data[i],
773 main_ad_integral[i] / ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/)));
774
775 main_ad_integral[i] -= carry * ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/));
776 }
777
778 if (electric_energy_meter_data[0].current_pos == 0) {
779 cmd_execute("logupload", NULL);
780 }
781 }
782
783 /* ボタン状態読み込み */
784 btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR);
785
786 /* ボタン1の処理 */
787 if (((btn & 0x20) != 0) && !main_btn1_state) {
788 main_btn1_count++;
789 if (main_btn1_count > 10) {
790 main_btn1_count = 0;
791 main_btn1_state = true;
792
793 main_btn1_change(true);
794 }
795 }
796 else if (((btn & 0x20) == 0) && main_btn1_state) {
797 main_btn1_count++;
798 if (main_btn1_count > 10) {
799 main_btn1_count = 0;
800 main_btn1_state = false;
801
802 main_btn1_change(false);
803 }
804 }
805
806 /* ボタン2の処理 */
807 if (((btn & 0x80) != 0) && !main_btn2_state) {
808 main_btn2_count++;
809 if (main_btn2_count > 10) {
810 main_btn2_count = 0;
811 main_btn2_state = true;
812
813 main_btn2_change(true);
814 }
815 }
816 else if (((btn & 0x80) == 0) && main_btn2_state) {
817 main_btn2_count++;
818 if (main_btn2_count > 10) {
819 main_btn2_count = 0;
820 main_btn2_state = false;
821
822 main_btn2_change(false);
823 }
824 }
825
826 main_7seg_view(main_port_no);
827
828 break;
829 }
830}
831
832bool_t main_rev = false;
833
834/*
835 * ボタン1状態変化処理
836 */
837static void main_btn1_change(bool_t push)
838{
839 /* 押されて戻った時に処理する */
840 if (push)
841 return;
842
843 /* 表示ポート番号 */
844 if (!main_rev) {
845 main_port_no--;
846 if (main_port_no < 1) {
847 main_port_no = 1;
848 main_rev = true;
849 main_adv_timer = 2000 * 1000;
850 }
851 }
852 else {
853 main_port_no++;
854 if (main_port_no > main_ad_count) {
855 main_port_no = main_ad_count;
856 main_rev = false;
857 main_adv_timer = 2000 * 1000;
858 }
859 }
860}
861
862/*
863 * ボタン2状態変化処理
864 */
865static void main_btn2_change(bool_t push)
866{
867 /* 押されて戻った時に処理する */
868 if (push)
869 return;
870
871 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
872 if ((swt & 0x20) == 0) {
873 return;
874 }
875
876 /* 表示ポート番号 */
877 if (!main_rev) {
878 main_port_no++;
879 if (main_port_no > main_ad_count) {
880 main_port_no = main_ad_count;
881 main_rev = false;
882 main_adv_timer = 2000 * 1000;
883 }
884 }
885 else {
886 main_port_no--;
887 if (main_port_no < 1) {
888 main_port_no = 1;
889 main_rev = true;
890 main_adv_timer = 2000 * 1000;
891 }
892 }
893}
894
895static void main_adv_ontimer()
896{
897 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
898 if (swt & 0x20) {
899 main_adv_timer = TMO_FEVR;
900 return;
901 }
902
903 main_port_no++;
904 if (main_port_no > main_ad_count)
905 main_port_no = 1;
906
907 main_adv_timer = 2000 * 1000;
908}
909
910static void main_7seg_view(int port_no)
911{
912 if ((port_no < 1) || (port_no > main_ad_count))
913 return;
914
915 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
916
917 port_no--;
918
919 uint32_t adv = (main_ad_avelage[port_no] / main_ad_table_count);
920
921 if (swt & 0x10) {
922 main_7seg[0] = led_disp[port_no + 1] | 1;
923 main_7seg[1] = led_disp[(adv & 0xF000) >> 12];
924 main_7seg[2] = led_disp[(adv & 0x0F00) >> 8];
925 main_7seg[3] = led_disp[(adv & 0x00F0) >> 4];
926 }
927 else {
928 uint32_t tmp = adv / 26214;
929
930 main_7seg[0] = led_disp[port_no + 1] | 1;
931 main_7seg[1] = led_disp[tmp] | 1;
932 adv = 10 * (adv - tmp * 26214);
933 tmp = adv / 26214;
934 main_7seg[2] = led_disp[tmp];
935 adv = 10 * (adv - tmp * 26214);
936 tmp = adv / 26214;
937 main_7seg[3] = led_disp[tmp];
938 }
939}
Note: See TracBrowser for help on using the repository browser.