source: UsbWattMeter/trunk/src/usb_watt_meter/main.c@ 167

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

MIMEにSJISを設定

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
  • Property svn:mime-type set to text/x-csrc; charset=SHIFT_JIS
File size: 27.8 KB
RevLine 
[164]1/*
2 * TOPPERS ECHONET Lite Communication Middleware
3 *
4 * Copyright (C) 2016 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: main.c 167 2016-03-08 11:37:45Z coas-nagasima $
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 "main.h"
51#include "echonet_cfg.h"
52#ifdef __RX
53#include "rx630_ccrx/rx630.h"
54#else
55#include "rx630_msvc/rx630.h"
56#endif
57#include "lwip/netif.h"
58#include "lwip/tcpip.h"
59#include "lwip/dhcp.h"
60#include "sntp/sntp.h"
61#include "ff.h"
62#include "diskio.h"
63#include "wolfssl/wolfcrypt/settings.h"
64#include "client.h"
65
66/* TODO: MACアドレスを設定 */
67uint8_t mac_addr[6] = { 0x00, 0x12, 0x34, 0x56, 0x78, 0x9A };
68
69struct lwip_task_t {
70 struct netif netif;
71 ID sem_rev; /* struct ethernetif */
72 uint32_t ethernetif[8];
73} lwiptsk = {{0},SEM_IF_RX62N_RBUF_READY};
74
75/* TODO: メーカーコードを設定 */
76#define MAKER_CODE 0x00, 0x00, 0xB3 /* TOPPERSプロジェクト */
77
78/* ノードプロファイルオブジェクト */
79struct node_profile_object_t local_node_data = {
80 0x30, /* 動作状態 */
81 { 0x01, 0x0A, 0x01, 0x00 }, /* Version情報 */
82 {
83 0xFE, /* 下位通信層IDフィールド */
84 { MAKER_CODE }, /* メーカーコード */
85 { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */
86 },
87 0,
88 { MAKER_CODE }, /* メーカーコード */
89};
90
91struct watt_hour_meter_t electric_energy_meter_data[6] = {
92 /* 電力量メータ1 */
93 {
94 0x30, /* 動作状態 */
95 0x00, /* 設置場所 */
96 { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */
97 0x41, /* 異常発生状態 */
98 { MAKER_CODE }, /* メーカーコード */
99 0x02, /* 積算電力量単位 */
100 0x00000000, /* 積算電力量計測値 */
101 { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
102 },
103 /* 電力量メータ2 */
104 {
105 0x30, /* 動作状態 */
106 0x00, /* 設置場所 */
107 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
108 0x41, /* 異常発生状態 */
109 {MAKER_CODE}, /* メーカーコード */
110 0x02, /* 積算電力量単位 */
111 0x00000000, /* 積算電力量計測値 */
112 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
113 },
114 /* 電力量メータ3 */
115 {
116 0x30, /* 動作状態 */
117 0x00, /* 設置場所 */
118 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
119 0x41, /* 異常発生状態 */
120 {MAKER_CODE}, /* メーカーコード */
121 0x02, /* 積算電力量単位 */
122 0x00000000, /* 積算電力量計測値 */
123 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
124 },
125 /* 電力量メータ4 */
126 {
127 0x30, /* 動作状態 */
128 0x00, /* 設置場所 */
129 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
130 0x41, /* 異常発生状態 */
131 {MAKER_CODE}, /* メーカーコード */
132 0x02, /* 積算電力量単位 */
133 0x00000000, /* 積算電力量計測値 */
134 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
135 },
136 /* 電力量メータ5 */
137 {
138 0x30, /* 動作状態 */
139 0x00, /* 設置場所 */
140 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
141 0x41, /* 異常発生状態 */
142 {MAKER_CODE}, /* メーカーコード */
143 0x02, /* 積算電力量単位 */
144 0x00000000, /* 積算電力量計測値 */
145 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
146 },
147 /* 電力量メータ6 */
148 {
149 0x30, /* 動作状態 */
150 0x00, /* 設置場所 */
151 {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */
152 0x41, /* 異常発生状態 */
153 {MAKER_CODE}, /* メーカーコード */
154 0x02, /* 積算電力量単位 */
155 0x00000000, /* 積算電力量計測値 */
156 {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */
157 }
158};
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 sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) | 0x01);
177 break;
178 /* OFFの場合 */
179 case 0x31:
180 *((uint8_t *)item->exinf) = *((uint8_t *)src);
181 /* LEDの"."をOFF */
182 sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) & ~0x01);
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
225 if (size != 2)
226 return 0;
227
228 /* 時刻設定 */
229 p_src = (uint8_t *)src;
230 sil_wrb_mem((uint8_t *)RTC_RHRCNT_ADDR, *p_src++);
231 sil_wrb_mem((uint8_t *)RTC_RMINCNT_ADDR, *p_src++);
232 sil_wrb_mem((uint8_t *)RTC_RSECCNT_ADDR, 0x00);
233
234 return (intptr_t)p_src - (intptr_t)src;
235}
236
237/*
238 * 現在時刻取得関数
239 */
240int time_prop_get(const EPRPINIB *item, void *dst, int size)
241{
242 uint8_t *p_dst;
243
244 if (size != 2)
245 return 0;
246
247 /* 時刻設定 */
248 p_dst = (uint8_t *)dst;
249 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RHRCNT_ADDR);
250 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMINCNT_ADDR);
251
252 return (intptr_t)p_dst - (intptr_t)dst;
253}
254
255/*
256 * 現在年月日設定関数
257 */
258int date_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno)
259{
260 uint8_t *p_src;
261
262 if (size != 4)
263 return 0;
264
265 /* 年月日設定 */
266 p_src = (uint8_t *)src;
267 p_src++; /* 20XX */
268 sil_wrb_mem((uint8_t *)RTC_RYRCNT_ADDR, *p_src++);
269 sil_wrb_mem((uint8_t *)RTC_RMONCNT_ADDR, *p_src++);
270 sil_wrb_mem((uint8_t *)RTC_RDAYCNT_ADDR, *p_src++);
271
272 return (intptr_t)p_src - (intptr_t)src;
273}
274
275/*
276 * 現在年月日取得関数
277 */
278int date_prop_get(const EPRPINIB *item, void *dst, int size)
279{
280 uint8_t *p_dst;
281
282 if (size != 4)
283 return 0;
284
285 p_dst = (uint8_t *)dst;
286 *p_dst++ = 0x20;
287 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RYRCNT_ADDR);
288 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMONCNT_ADDR);
289 *p_dst++ = sil_reb_mem((uint8_t *)RTC_RDAYCNT_ADDR);
290
291 return (intptr_t)p_dst - (intptr_t)dst;
292}
293
294/*
295 * 積算電力量計測値取得関数
296 */
297int watt_hour_meter_integral_electric_energy_measurement_value_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_value);
300
301 /* サイズが4以外は受け付けない */
302 if(size != 4)
303 return 0;
304
305 *((uint32_t *)dst) = meter->integral_electric_energy_measurement_value;
306
307 return 4;
308}
309
310int watt_hour_meter_integral_electric_energy_measurement_log_get(const EPRPINIB *item, void *dst, int size)
311{
312 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);
313 int len;
314
315 /* サイズが192以外は受け付けない */
316 if (size != 192)
317 return 0;
318
319 wai_sem(MAIN_SEMAPHORE);
320
321 len = 48 - meter->current_pos;
322 if(len > 0)
323 memcpy(dst, &meter->integral_electric_energy_measurement_log[meter->current_pos], sizeof(uint32_t) * len);
324 dst = &((uint8_t *)dst)[len];
325 len = 48 - len;
326 if (len > 0)
327 memcpy(dst, &meter->integral_electric_energy_measurement_log[0], sizeof(uint32_t) * len);
328
329 sig_sem(MAIN_SEMAPHORE);
330
331 return 192;
332}
333
334static uint32_t whm_add_integral_value(struct watt_hour_meter_t *meter, uint32_t watt_hour)
335{
336 bool_t carry;
337 uint32_t value = watt_hour;
338 int current_pos = meter->current_pos;
339 current_pos++;
340 if (current_pos >= 48)
341 current_pos = 0;
342
343 carry = value >= 100000000;
344 if (carry)
345 value -= 100000000;
346
347 wai_sem(MAIN_SEMAPHORE);
348
349 meter->integral_electric_energy_measurement_value = value;
350 meter->integral_electric_energy_measurement_log[current_pos] = value;
351 meter->current_pos = current_pos;
352
353 sig_sem(MAIN_SEMAPHORE);
354
355 return carry ? 100000000 : 0;
356}
357
358static void fatfs_initialize();
359static void netif_initialize();
360static void netif_status_callback(struct netif *netif);
361static void netif_link_callback(struct netif *netif);
362static void main_initialize();
363static TMO main_get_timer();
364static void main_progress(TMO interval);
365static void main_recv_esv(T_EDATA *esv);
366static void main_break_wait(uint8_t *brkdat, int32_t len);
367static void main_timeout();
368
369/*
370 * メインタスク
371 */
372void main_task(intptr_t exinf)
373{
374 ER ret, ret2;
375 SYSTIM prev, now;
376 TMO timer;
377 T_EDATA *esv;
378 uint8_t brkdat[64];
379 int32_t len;
380
381 /* ファイルシステムの初期化 */
382 fatfs_initialize();
383
384 /* プロトコルスタックの初期化 */
385 netif_initialize();
386
387 /* アプリケーションの初期化 */
388 main_initialize();
389
390 ret2 = get_tim(&now);
391 if (ret2 != E_OK){
392 syslog(LOG_ERROR, "get_tim");
393 return;
394 }
395
396 for(;;){
397 prev = now;
398
399 /* タイマー取得 */
400 timer = main_get_timer();
401
402 /* 応答電文待ち */
403 ret = ecn_trcv_esv(&esv, timer);
404 if ((ret != E_OK) && (ret != E_WBLK) && (ret != E_TMOUT)){
405 syslog(LOG_ERROR, "ecn_trcv_esv");
406 break;
407 }
408
409 ret2 = get_tim(&now);
410 if (ret2 != E_OK){
411 syslog(LOG_ERROR, "get_tim");
412 break;
413 }
414
415 /* 時間経過 */
416 main_progress(now - prev);
417
418 /* Echonet電文受信の場合 */
419 if (ret == E_OK) {
420 /* Echonet電文受信処理 */
421 main_recv_esv(esv);
422
423 /* 領域解放 */
424 ret = ecn_rel_esv(esv);
425 if (ret != E_OK){
426 syslog(LOG_ERROR, "ecn_rel_esv");
427 break;
428 }
429 }
430 /* 応答電文待ちの割り込みの場合 */
431 else if (ret == E_WBLK) {
432 /* 応答電文待ちの割り込みデータ取得 */
433 ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len);
434 if (ret != E_OK){
435 syslog(LOG_ERROR, "ecn_get_brk_dat");
436 break;
437 }
438
439 /* 応答電文待ちの割り込み処理 */
440 main_break_wait(brkdat, len);
441
442 /* 領域解放 */
443 ret = ecn_rel_esv(esv);
444 if (ret != E_OK){
445 syslog(LOG_ERROR, "ecn_rel_esv");
446 break;
447 }
448 }
449
450 /* タイムアウト処理 */
451 main_timeout();
452 }
453}
454
455FATFS FatFs[_VOLUMES]; /* File system object for logical drive */
456
457static void fatfs_initialize()
458{
459 DSTATUS dst;
460 FRESULT res;
461 BYTE pdrv = 0, type;
462
463 if ((dst = disk_initialize(pdrv)) != RES_OK) {
464 syslog(LOG_ERROR, "disk_initialize %d", dst);
465 return;
466 }
467
468 if ((dst = disk_ioctl(pdrv, MMC_GET_TYPE, &type)) != RES_OK) {
469 syslog(LOG_ERROR, "disk_ioctl MMC_GET_TYPE NG %d", dst);
470 }
471 else {
472 switch(type){
473 case CT_MMC:
474 syslog(LOG_NOTICE, "MMC ver 3");
475 break;
476 case CT_SD1:
477 syslog(LOG_NOTICE, "SD ver 1");
478 break;
479 case CT_SD2:
480 syslog(LOG_NOTICE, "SD ver 2");
481 break;
482 case CT_SDC:
483 syslog(LOG_NOTICE, "SD");
484 break;
485 case CT_SD2 | CT_BLOCK:
486 syslog(LOG_NOTICE, "SD ver 2 (Block addressing)");
487 break;
488 default:
489 syslog(LOG_NOTICE, "???(%x)", type);
490 break;
491 }
492 }
493
494 if ((res = f_mount(&FatFs[0], "", 1)) != FR_OK) {
495 syslog(LOG_ERROR, "f_mount %d", res);
496 return;
497 }
498}
499
500bool_t started = false;
501struct dhcp dhcp;
502bool_t dhcp_enable = true;
503
504static void netif_initialize()
505{
506 extern err_t ethernetif_init(struct netif *netif);
507 ER ret;
508 struct ip_addr xIpAddr, xNetMast, xGateway;
509 uint8_t data[32], c;
510 int i, j;
511
512 for (i = 0, j = 0; i < sizeof(mac_addr); i++) {
513 c = mac_addr[i] >> 4;
514 data[j++] = (c < 10) ? ('0' + c) : ('A' - 10 + c);
515 c = mac_addr[i] & 0xF;
516 data[j++] = (c < 10) ? ('0' + c) : ('A' - 10 + c);
517 data[j++] = ':';
518 }
519 data[--j] = '\0';
520
521 syslog(LOG_NOTICE, "mac_addr %s %s", data, dhcp_enable ? "dhcp" : "static");
522
523 /* libcurlとWolfSSLとlwIPの初期化 */
524 client_init();
525
526 IP4_ADDR(&xIpAddr, 192, 168, 2, 110);
527 IP4_ADDR(&xNetMast, 255, 255, 255, 0);
528 IP4_ADDR(&xGateway, 192, 168, 2, 1);
529
530 /* Create and configure the EMAC interface. */
531 netif_add(&lwiptsk.netif, &xIpAddr, &xNetMast,
532 &xGateway, NULL, ethernetif_init, tcpip_input);
533
534 netif_set_link_callback(&lwiptsk.netif, netif_link_callback);
535 netif_set_status_callback(&lwiptsk.netif, netif_status_callback);
536
537 dhcp_set_struct(&lwiptsk.netif, &dhcp);
538
539 /* make it the default interface */
540 netif_set_default(&lwiptsk.netif);
541
542 ret = act_tsk(LWIP_TASK);
543 if (ret != E_OK)
544 return;
545}
546
547static void netif_link_callback(struct netif *netif)
548{
549 if ((lwiptsk.netif.flags & NETIF_FLAG_LINK_UP) == 0)
550 return;
551
552 dhcp_start(&lwiptsk.netif);
553}
554
555static void netif_status_callback(struct netif *netif)
556{
557 ER ret;
558 bool_t up;
559
560 up = (lwiptsk.netif.flags & NETIF_FLAG_UP) != 0;
561 if (up && !started) {
562 started = true;
563
564 /* ECHONETミドルウェアを起動 */
565 ret = ecn_sta_svc();
566 if (ret != E_OK)
567 return;
568
569 /* SNTPを開始 */
570 sntp_init();
571 }
572
573 /* メインタスクに通知 */
574 uint8_t data[2];
575 data[0] = 0x01;
576 data[1] = up ? 0x01 : 0x02;
577 ret = ecn_brk_wai(data, sizeof(data));
578 if (ret != E_OK) {
579 syslog(LOG_ERROR, "ecn_brk_wai");
580 return;
581 }
582}
583
584enum main_state_t{
585 main_state_idle,
586};
587
588TMO main_timer = TMO_FEVR;
589enum main_state_t main_state = main_state_idle;
590TMO main_led_timer = TMO_FEVR;
591TMO main_adv_timer = TMO_FEVR;
592int main_whm_counter;
593
594bool_t main_btn1_state;
595int main_btn1_count = 0;
596bool_t main_btn2_state;
597int main_btn2_count = 0;
598
599/*
600 * 初期化
601 */
602static void main_initialize()
603{
604 uint8_t btn;
605
606 /*
607 * モジュールストップ機能の設定(S12AD)
608 */
609 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */
610 sil_wrw_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR,
611 sil_rew_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR) & ~SYSTEM_MSTPCRA_MSTPA17_BIT);
612 sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */
613
614 /* 7seg_1100用ポート出力設定 */
615 sil_wrb_mem((uint8_t *)PORT2_PDR_ADDR, sil_reb_mem((uint8_t *)PORT2_PDR_ADDR) | PORT_PDR_B4_BIT | PORT_PDR_B3_BIT);
616 /* 7seg_0010用ポート出力設定 */
617 sil_wrb_mem((uint8_t *)PORT5_PDR_ADDR, sil_reb_mem((uint8_t *)PORT5_PDR_ADDR) | PORT_PDR_B3_BIT);
618 /* 7seg_0001用ポート出力設定 */
619 sil_wrb_mem((uint8_t *)PORTC_PDR_ADDR, sil_reb_mem((uint8_t *)PORTC_PDR_ADDR) | PORT_PDR_B1_BIT);
620 /* 7seg_led用ポート出力設定 */
621 sil_wrb_mem((uint8_t *)PORTD_PDR_ADDR, 0xFF);
622 /* SWITCH用ポート入力、LED用ポート出力設定 */
623 sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F);
624
625 /* LEDを"0000"と表示 */
626 sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F);
627
628 /* 3ms後に7SEG表示を更新 */
629 main_led_timer = 3;
630
631 /* 10ms後にボタン状態を確認 */
632 main_timer = 10;
633
634 /* 12bitADC初期化 */
635 sil_wrh_mem((uint16_t *)S12AD_ADEXICR_ADDR, 0x0000); /* 温度センサ出力、内部基準電圧非選択 */
636 sil_wrh_mem((uint16_t *)S12AD_ADANS0_ADDR, 0x00FF); /* 変換ポートAN000〜AN007選択、AN008〜AN015非選択 */
637 sil_wrh_mem((uint16_t *)S12AD_ADANS1_ADDR, 0x0000); /* 変換ポートAN016〜AN020非選択 */
638
639 /* ボタン状態読み込み */
640 btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR);
641 main_btn1_state = (btn & 0x20) != 0;
642 main_btn2_state = (btn & 0x80) != 0;
643
644 /* 1秒後に表示を更新 */
645 main_adv_timer = 1000;
646}
647
648/*
649 * タイマー取得
650 */
651static TMO main_get_timer()
652{
653 TMO result = main_timer;
654
655 if((result == TMO_FEVR)
656 || ((main_led_timer != TMO_FEVR) && (main_led_timer < result))){
657 result = main_led_timer;
658 }
659
660 if ((result == TMO_FEVR)
661 || ((main_adv_timer != TMO_FEVR) && (main_adv_timer < result))) {
662 result = main_adv_timer;
663 }
664
665 return result;
666}
667
668/*
669 * 時間経過
670 */
671static void main_progress(TMO interval)
672{
673 if(main_timer != TMO_FEVR){
674 main_timer -= interval;
675 if(main_timer < 0){
676 main_timer = 0;
677 }
678 }
679
680 if(main_led_timer != TMO_FEVR){
681 main_led_timer -= interval;
682 if(main_led_timer < 0){
683 main_led_timer = 0;
684 }
685 }
686
687 if (main_adv_timer != TMO_FEVR) {
688 main_adv_timer -= interval;
689 if (main_adv_timer < 0) {
690 main_adv_timer = 0;
691 }
692 }
693}
694
695/*
696 * Echonet電文受信処理
697 */
698static void main_recv_esv(T_EDATA *esv)
699{
700 ER ret;
701 uint8_t epc;
702 uint8_t pdc;
703 uint8_t p_edt[256];
704 T_ENUM_EPC enm;
705
706 ret = ecn_itr_ini(&enm, esv);
707 if(ret != E_OK){
708 syslog(LOG_ERROR, "ecn_itr_ini");
709 return;
710 }
711
712 for(;;) {
713 while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) {
714 switch (epc) {
715 case 0x80:
716 break;
717 case 0x81:
718 break;
719 }
720 }
721 if(ret != E_BOVR){
722 syslog(LOG_ERROR, "ecn_itr_nxt");
723 break;
724 }
725 if(enm.is_eof)
726 break;
727 }
728}
729
730/*
731 * 応答電文待ちの割り込み処理
732 */
733static void main_break_wait(uint8_t *brkdat, int32_t len)
734{
735 char ip_addr[16], netmask[16], gateway[16];
736
737 switch(main_state){
738 case main_state_idle:
739 if (len == 0)
740 break;
741
742 switch (brkdat[0]) {
743 case 1:
744 switch (brkdat[0]) {
745 case 1:
746 ipaddr_ntoa_r(&lwiptsk.netif.ip_addr, ip_addr, sizeof(ip_addr));
747 ipaddr_ntoa_r(&lwiptsk.netif.netmask, netmask, sizeof(netmask));
748 ipaddr_ntoa_r(&lwiptsk.netif.gw, gateway, sizeof(gateway));
749
750 syslog(LOG_NOTICE, "ip_addr %s, netmask %s, gateway %s", ip_addr, netmask, gateway);
751 tslp_tsk(100); /* ログが出力されるまでちょっと待つ */
752 break;
753 case 2:
754 syslog(LOG_NOTICE, "netif down");
755 break;
756 }
757 break;
758 }
759 break;
760 }
761}
762
763static void main_ontimer();
764static void main_led_ontimer();
765static void main_adv_ontimer();
766
767/*
768 * タイムアウト処理
769 */
770static void main_timeout()
771{
772 if(main_timer == 0){
773 main_ontimer();
774 }
775
776 if(main_led_timer == 0){
777 main_led_ontimer();
778 }
779
780 if (main_adv_timer == 0) {
781 main_adv_ontimer();
782 }
783}
784
785#define main_7seg_count 4
786static uint8_t main_7seg[main_7seg_count] = { 0xDA, 0xF2, 0xB6, 0xB6 };
787static int main_7seg_pos = 0;
788const uint8_t led_disp[] = { 0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE4, 0xFE, 0xF6, 0xEE, 0x3E, 0x1A, 0x7A, 0x9E, 0x8E };
789
790static void main_led_ontimer()
791{
792 /* 7Seg表示 */
793 sil_wrb_mem((uint8_t *)PORTD_PODR_ADDR, ~main_7seg[main_7seg_pos]);
794
795 if (main_7seg_pos == 0)
796 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
797 & ~PORT_PODR_B4_BIT);
798 else
799 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
800 | PORT_PODR_B4_BIT);
801 if (main_7seg_pos == 1)
802 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
803 & ~PORT_PODR_B3_BIT);
804 else
805 sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR)
806 | PORT_PODR_B3_BIT);
807 if (main_7seg_pos == 2)
808 sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR)
809 & ~PORT_PODR_B3_BIT);
810 else
811 sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR)
812 | PORT_PODR_B3_BIT);
813 if (main_7seg_pos == 3)
814 sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR)
815 & ~PORT_PODR_B1_BIT);
816 else
817 sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR)
818 | PORT_PODR_B1_BIT);
819
820 main_7seg_pos = (main_7seg_pos + 1) & 0x3;
821
822 /* 3ms後に7SEG表示を更新 */
823 main_led_timer = 3;
824}
825
826#define main_ad_count 8
827#define main_ad_table_count 64
828static uint16_t main_ad_table[main_ad_count][main_ad_table_count];
829static int main_ad_pos = 0;
830static uint32_t main_ad_avelage[main_ad_count];
831static uint64_t main_ad_integral[main_ad_count];
832volatile uint16_t *const main_ad_addr[main_ad_count] = {
833 (uint16_t *)S12AD_ADDR0_ADDR,
834 (uint16_t *)S12AD_ADDR1_ADDR,
835 (uint16_t *)S12AD_ADDR2_ADDR,
836 (uint16_t *)S12AD_ADDR3_ADDR,
837 (uint16_t *)S12AD_ADDR4_ADDR,
838 (uint16_t *)S12AD_ADDR5_ADDR,
839 (uint16_t *)S12AD_ADDR6_ADDR,
840 (uint16_t *)S12AD_ADDR7_ADDR,
841};
842
843uint8_t main_port_no = 1;
844static void main_7seg_view(int port_no);
845static void main_btn1_change(bool_t push);
846static void main_btn2_change(bool_t push);
847
848/*
849 * タイムアウト処理
850 */
851static void main_ontimer()
852{
853 uint8_t btn;
854 uint16_t ad_value;
855
856 switch(main_state){
857 case main_state_idle:
858 /* 10ms後にボタン状態を確認 */
859 main_timer = 10;
860
861 /* ADCの変換結果取得 */
862 if((sil_reb_mem((uint8_t *)S12AD_ADCSR_ADDR) & S12AD_ADCSR_ADST_BIT) == 0){
863 for (int i = 0; i < main_ad_count; i++) {
864 main_ad_avelage[i] -= main_ad_table[i][main_ad_pos];
865 ad_value = sil_reh_mem(main_ad_addr[i]); // 12bit値取得
866 main_ad_integral[i] += 5/*[V]*/ * ad_value/*[A]*/; // 12bit積算値
867 ad_value = (ad_value << 4) | (ad_value >> 12); // 16bit拡張
868 main_ad_table[i][main_ad_pos] = ad_value;
869 main_ad_avelage[i] += ad_value;
870 }
871
872 main_ad_pos++;
873 if (main_ad_pos >= main_ad_table_count) {
874 main_ad_pos = 0;
875 }
876
877 /* 変換開始(シングルスキャンモード) */
878 sil_wrb_mem((uint8_t *)S12AD_ADCSR_ADDR, S12AD_ADCSR_ADST_BIT);
879 }
880
881 main_whm_counter += 10;
882 if (main_whm_counter >= 1250/* 180000=30分 */) {
883 main_whm_counter = 0;
884
885 for (int i = 0; i < 6; i++) {
886 uint64_t carry;
887 carry = whm_add_integral_value(&electric_energy_meter_data[i],
888 main_ad_integral[i] / ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/)));
889
890 main_ad_integral[i] -= carry * ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/));
891 }
892
893 if (electric_energy_meter_data[0].current_pos == 0) {
894 act_tsk(CLIENT_TASK);
895 }
896 }
897
898 /* ボタン状態読み込み */
899 btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR);
900
901 /* ボタン1の処理 */
902 if(((btn & 0x20) != 0) && !main_btn1_state){
903 main_btn1_count++;
904 if(main_btn1_count > 10){
905 main_btn1_count = 0;
906 main_btn1_state = true;
907
908 main_btn1_change(true);
909 }
910 }
911 else if(((btn & 0x20) == 0) && main_btn1_state){
912 main_btn1_count++;
913 if(main_btn1_count > 10){
914 main_btn1_count = 0;
915 main_btn1_state = false;
916
917 main_btn1_change(false);
918 }
919 }
920
921 /* ボタン2の処理 */
922 if(((btn & 0x80) != 0) && !main_btn2_state){
923 main_btn2_count++;
924 if(main_btn2_count > 10){
925 main_btn2_count = 0;
926 main_btn2_state = true;
927
928 main_btn2_change(true);
929 }
930 }
931 else if(((btn & 0x80) == 0) && main_btn2_state){
932 main_btn2_count++;
933 if(main_btn2_count > 10){
934 main_btn2_count = 0;
935 main_btn2_state = false;
936
937 main_btn2_change(false);
938 }
939 }
940
941 main_7seg_view(main_port_no);
942
943 break;
944 }
945}
946
947bool_t main_rev = false;
948
949/*
950 * ボタン1状態変化処理
951 */
952static void main_btn1_change(bool_t push)
953{
954 /* 押されて戻った時に処理する */
955 if(push)
956 return;
957
958 /* 表示ポート番号 */
959 if(!main_rev){
960 main_port_no--;
961 if(main_port_no < 1){
962 main_port_no = 1;
963 main_rev = true;
964 main_adv_timer = 2000;
965 }
966 }
967 else{
968 main_port_no++;
969 if(main_port_no > main_ad_count){
970 main_port_no = main_ad_count;
971 main_rev = false;
972 main_adv_timer = 2000;
973 }
974 }
975}
976
977/*
978 * ボタン2状態変化処理
979 */
980static void main_btn2_change(bool_t push)
981{
982 /* 押されて戻った時に処理する */
983 if(push)
984 return;
985
986 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
987 if ((swt & 0x20) == 0) {
988 return;
989 }
990
991 /* 表示ポート番号 */
992 if(!main_rev){
993 main_port_no++;
994 if(main_port_no > main_ad_count){
995 main_port_no = main_ad_count;
996 main_rev = false;
997 main_adv_timer = 2000;
998 }
999 }
1000 else{
1001 main_port_no--;
1002 if(main_port_no < 1){
1003 main_port_no = 1;
1004 main_rev = true;
1005 main_adv_timer = 2000;
1006 }
1007 }
1008}
1009
1010static void main_adv_ontimer()
1011{
1012 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
1013 if (swt & 0x20)
1014 return;
1015
1016 main_port_no++;
1017 if(main_port_no > main_ad_count)
1018 main_port_no = 1;
1019
1020 main_adv_timer = 2000;
1021}
1022
1023static void main_7seg_view(int port_no)
1024{
1025 if ((port_no < 1) || (port_no > main_ad_count))
1026 return;
1027
1028 int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR);
1029
1030 port_no--;
1031
1032 uint32_t adv = (main_ad_avelage[port_no] / main_ad_table_count);
1033
1034 if (swt & 0x10) {
1035 main_7seg[0] = led_disp[port_no + 1] | 1;
1036 main_7seg[1] = led_disp[(adv & 0xF000) >> 12];
1037 main_7seg[2] = led_disp[(adv & 0x0F00) >> 8];
1038 main_7seg[3] = led_disp[(adv & 0x00F0) >> 4];
1039 }
1040 else {
1041 uint32_t tmp = adv / 26214;
1042
1043 main_7seg[0] = led_disp[port_no + 1] | 1;
1044 main_7seg[1] = led_disp[tmp] | 1;
1045 adv = 10 * (adv - tmp * 26214);
1046 tmp = adv / 26214;
1047 main_7seg[2] = led_disp[tmp];
1048 adv = 10 * (adv - tmp * 26214);
1049 tmp = adv / 26214;
1050 main_7seg[3] = led_disp[tmp];
1051 }
1052}
1053
1054#ifdef __RX
1055void abort()
1056{
1057 TOPPERS_assert_abort();
1058}
1059#endif
Note: See TracBrowser for help on using the repository browser.