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

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

NTPクライアント処理を追加

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