/* * TOPPERS ECHONET Lite Communication Middleware * * Copyright (C) 2016-2018 Cores Co., Ltd. Japan * * 上記著作権者は,以下の(1)~(4)の条件を満たす場合に限り,本ソフトウェ * ア(本ソフトウェアを改変したものを含む.以下同じ)を使用・複製・改 * 変・再配布(以下,利用と呼ぶ)することを無償で許諾する. * (1) 本ソフトウェアをソースコードの形で利用する場合には,上記の著作 * 権表示,この利用条件および下記の無保証規定が,そのままの形でソー * スコード中に含まれていること. * (2) 本ソフトウェアを,ライブラリ形式など,他のソフトウェア開発に使 * 用できる形で再配布する場合には,再配布に伴うドキュメント(利用 * 者マニュアルなど)に,上記の著作権表示,この利用条件および下記 * の無保証規定を掲載すること. * (3) 本ソフトウェアを,機器に組み込むなど,他のソフトウェア開発に使 * 用できない形で再配布する場合には,次のいずれかの条件を満たすこ * と. * (a) 再配布に伴うドキュメント(利用者マニュアルなど)に,上記の著 * 作権表示,この利用条件および下記の無保証規定を掲載すること. * (b) 再配布の形態を,別に定める方法によって,TOPPERSプロジェクトに * 報告すること. * (4) 本ソフトウェアの利用により直接的または間接的に生じるいかなる損 * 害からも,上記著作権者およびTOPPERSプロジェクトを免責すること. * また,本ソフトウェアのユーザまたはエンドユーザからのいかなる理 * 由に基づく請求からも,上記著作権者およびTOPPERSプロジェクトを * 免責すること. * * 本ソフトウェアは,無保証で提供されているものである.上記著作権者お * よびTOPPERSプロジェクトは,本ソフトウェアに関して,特定の使用目的 * に対する適合性も含めて,いかなる保証も行わない.また,本ソフトウェ * アの利用により直接的または間接的に生じたいかなる損害に関しても,そ * の責任を負わない. * * @(#) $Id$ */ /* * サンプルプログラム(1)の本体 */ #include #include #include #include #include #include "syssvc/serial.h" #include "syssvc/syslog.h" #include "kernel_cfg.h" #include "echonet_main.h" #include "echonet_cfg.h" #include "target_kernel_impl.h" #include "ff.h" #include "diskio.h" #include #include #include #include #include #include #include "ntshell_main.h" /* TODO: メーカーコードを設定 */ #define MAKER_CODE { 0x00, 0x00, 0xB3 } /* TOPPERSプロジェクト */ /* ノードプロファイルオブジェクト */ struct node_profile_object_t local_node_data = { 0x30, /* 動作状態 */ { 0x01, 0x0A, { 0x01, 0x00 } }, /* Version情報 */ { 0xFE, /* 下位通信層IDフィールド */ { MAKER_CODE }, /* メーカーコード */ { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }, /* ユニークID部(メーカー独自) */ }, 0, { MAKER_CODE }, /* メーカーコード */ }; struct watt_hour_meter_t electric_energy_meter_data[6] = { /* 電力量メータ1 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ { 0x00, 0x00, 'C', 0x00 }, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ { MAKER_CODE }, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ { 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ }, /* 電力量メータ2 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ {MAKER_CODE}, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ }, /* 電力量メータ3 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ {MAKER_CODE}, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ }, /* 電力量メータ4 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ {MAKER_CODE}, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ }, /* 電力量メータ5 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ {MAKER_CODE}, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ }, /* 電力量メータ6 */ { 0x30, /* 動作状態 */ 0x00, /* 設置場所 */ {0x00, 0x00, 'C', 0x00}, /* 規格Version情報 */ 0x41, /* 異常発生状態 */ {MAKER_CODE}, /* メーカーコード */ 0x02, /* 積算電力量単位 */ 0x00000000, /* 積算電力量計測値 */ {0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 0x00000000, 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 */ } }; /* * 動作状態ON/OFF設定関数(0x30, 0x31のみ受け付け) */ int onoff_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno) { /* サイズが1以外は受け付けない */ if(size != 1) return 0; *anno = *((uint8_t*)item->exinf) != *((uint8_t*)src); switch(*(uint8_t *)src){ /* ONの場合 */ case 0x30: *((uint8_t *)item->exinf) = *((uint8_t *)src); /* LEDの"."をON */ sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) | 0x01); break; /* OFFの場合 */ case 0x31: *((uint8_t *)item->exinf) = *((uint8_t *)src); /* LEDの"."をOFF */ sil_wrb_mem((uint8_t *)PORTE_PODR_ADDR, sil_reb_mem((uint8_t *)PORTE_PODR_ADDR) & ~0x01); break; /* 0x30か0x31以外は受け付けない */ default: return 0; } return 1; } /* * 異常発生状態設定関数(0x41, 0x42のみ受け付け) */ int alarm_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno) { /* サイズが1以外は受け付けない */ if(size != 1) return 0; *anno = *((uint8_t *)item->exinf) != *((uint8_t *)src); switch(*(uint8_t *)src){ /* 異常発生ありの場合 */ case 0x41: /* 異常発生なしの場合 */ case 0x42: *((uint8_t *)item->exinf) = *((uint8_t *)src); break; /* 0x41か0x42以外は受け付けない */ default: return 0; } return 1; } /* * 現在時刻設定関数 */ int time_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno) { uint8_t *p_src; if (size != 2) return 0; /* 時刻設定 */ p_src = (uint8_t *)src; sil_wrb_mem((uint8_t *)RTC_RHRCNT_ADDR, *p_src++); sil_wrb_mem((uint8_t *)RTC_RMINCNT_ADDR, *p_src++); sil_wrb_mem((uint8_t *)RTC_RSECCNT_ADDR, 0x00); return (intptr_t)p_src - (intptr_t)src; } /* * 現在時刻取得関数 */ int time_prop_get(const EPRPINIB *item, void *dst, int size) { uint8_t *p_dst; if (size != 2) return 0; /* 時刻設定 */ p_dst = (uint8_t *)dst; *p_dst++ = sil_reb_mem((uint8_t *)RTC_RHRCNT_ADDR); *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMINCNT_ADDR); return (intptr_t)p_dst - (intptr_t)dst; } /* * 現在年月日設定関数 */ int date_prop_set(const EPRPINIB *item, const void *src, int size, bool_t *anno) { uint8_t *p_src; if (size != 4) return 0; /* 年月日設定 */ p_src = (uint8_t *)src; p_src++; /* 20XX */ sil_wrb_mem((uint8_t *)RTC_RYRCNT_ADDR, *p_src++); sil_wrb_mem((uint8_t *)RTC_RMONCNT_ADDR, *p_src++); sil_wrb_mem((uint8_t *)RTC_RDAYCNT_ADDR, *p_src++); return (intptr_t)p_src - (intptr_t)src; } /* * 現在年月日取得関数 */ int date_prop_get(const EPRPINIB *item, void *dst, int size) { uint8_t *p_dst; if (size != 4) return 0; p_dst = (uint8_t *)dst; *p_dst++ = 0x20; *p_dst++ = sil_reb_mem((uint8_t *)RTC_RYRCNT_ADDR); *p_dst++ = sil_reb_mem((uint8_t *)RTC_RMONCNT_ADDR); *p_dst++ = sil_reb_mem((uint8_t *)RTC_RDAYCNT_ADDR); return (intptr_t)p_dst - (intptr_t)dst; } /* * 積算電力量計測値取得関数 */ int watt_hour_meter_integral_electric_energy_measurement_value_get(const EPRPINIB *item, void *dst, int size) { 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); /* サイズが4以外は受け付けない */ if(size != 4) return 0; *((uint32_t *)dst) = meter->integral_electric_energy_measurement_value; return 4; } int watt_hour_meter_integral_electric_energy_measurement_log_get(const EPRPINIB *item, void *dst, int size) { 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); int len; /* サイズが192以外は受け付けない */ if (size != 192) return 0; wai_sem(MAIN_SEMAPHORE); len = 48 - meter->current_pos; if(len > 0) memcpy(dst, &meter->integral_electric_energy_measurement_log[meter->current_pos], sizeof(uint32_t) * len); dst = &((uint8_t *)dst)[len]; len = 48 - len; if (len > 0) memcpy(dst, &meter->integral_electric_energy_measurement_log[0], sizeof(uint32_t) * len); sig_sem(MAIN_SEMAPHORE); return 192; } static uint32_t whm_add_integral_value(struct watt_hour_meter_t *meter, uint32_t watt_hour) { bool_t carry; uint32_t value = watt_hour; int current_pos = meter->current_pos; current_pos++; if (current_pos >= 48) current_pos = 0; carry = value >= 100000000; if (carry) value -= 100000000; wai_sem(MAIN_SEMAPHORE); meter->integral_electric_energy_measurement_value = value; meter->integral_electric_energy_measurement_log[current_pos] = value; meter->current_pos = current_pos; sig_sem(MAIN_SEMAPHORE); return carry ? 100000000 : 0; } static void main_initialize(); static int main_get_timer(); static void main_progress(int interval); static void main_recv_esv(T_EDATA *esv); static void main_break_wait(uint8_t *brkdat, int32_t len); static void main_timeout(); /* * メインタスク */ void echonet_main_task(intptr_t exinf) { ER ret, ret2; SYSTIM prev, now; int timer; T_EDATA *esv; uint8_t brkdat[64]; int32_t len; /* アプリケーションの初期化 */ main_initialize(); ret2 = get_tim(&now); if (ret2 != E_OK){ syslog(LOG_ERROR, "get_tim"); return; } for(;;){ prev = now; /* タイマー取得 */ timer = main_get_timer(); /* 応答電文待ち */ ret = ecn_trcv_esv(&esv, timer); if ((ret != E_OK) && (ret != E_BRK) && (ret != E_TMOUT)){ syslog(LOG_ERROR, "ecn_trcv_esv"); break; } ret2 = get_tim(&now); if (ret2 != E_OK){ syslog(LOG_ERROR, "get_tim"); break; } /* 時間経過 */ main_progress(now - prev); /* Echonet電文受信の場合 */ if (ret == E_OK) { /* Echonet電文受信処理 */ main_recv_esv(esv); /* 領域解放 */ ret = ecn_rel_esv(esv); if (ret != E_OK){ syslog(LOG_ERROR, "ecn_rel_esv"); break; } } /* 応答電文待ちの割り込みの場合 */ else if (ret == E_BRK) { /* 応答電文待ちの割り込みデータ取得 */ ret = ecn_get_brk_dat(esv, brkdat, sizeof(brkdat), &len); if (ret != E_OK){ syslog(LOG_ERROR, "ecn_get_brk_dat"); break; } /* 応答電文待ちの割り込み処理 */ main_break_wait(brkdat, len); /* 領域解放 */ ret = ecn_rel_esv(esv); if (ret != E_OK){ syslog(LOG_ERROR, "ecn_rel_esv"); break; } } /* タイムアウト処理 */ main_timeout(); } } bool_t started = false; void echonet_change_netif_link(uint8_t link_up, uint8_t up) { ER ret; if (link_up == 0) return; if (up && !started) { started = true; /* ECHONETミドルウェアを起動 */ ret = ecn_sta_svc(); if (ret != E_OK) return; } /* メインタスクに通知 */ uint8_t data[2]; data[0] = 0x01; data[1] = up ? 0x01 : 0x02; ret = ecn_brk_wai(data, sizeof(data)); if (ret != E_OK) { syslog(LOG_ERROR, "ecn_brk_wai"); return; } } enum main_state_t{ main_state_idle, }; int main_timer = TMO_FEVR; enum main_state_t main_state = main_state_idle; int main_led_timer = TMO_FEVR; int main_adv_timer = TMO_FEVR; int main_whm_counter; bool_t main_btn1_state; int main_btn1_count = 0; bool_t main_btn2_state; int main_btn2_count = 0; /* * 初期化 */ static void main_initialize() { uint8_t btn; /* * モジュールストップ機能の設定(S12AD) */ sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA502); /* 書込み許可 */ sil_wrw_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR, sil_rew_mem((uint32_t *)SYSTEM_MSTPCRA_ADDR) & ~SYSTEM_MSTPCRA_MSTPA17_BIT); sil_wrh_mem((uint16_t *)SYSTEM_PRCR_ADDR, (uint16_t)0xA500); /* 書込み禁止 */ /* 7seg_1100用ポート出力設定 */ sil_wrb_mem((uint8_t *)PORT2_PDR_ADDR, sil_reb_mem((uint8_t *)PORT2_PDR_ADDR) | PORT_PDR_B4_BIT | PORT_PDR_B3_BIT); /* 7seg_0010用ポート出力設定 */ sil_wrb_mem((uint8_t *)PORT5_PDR_ADDR, sil_reb_mem((uint8_t *)PORT5_PDR_ADDR) | PORT_PDR_B3_BIT); /* 7seg_0001用ポート出力設定 */ sil_wrb_mem((uint8_t *)PORTC_PDR_ADDR, sil_reb_mem((uint8_t *)PORTC_PDR_ADDR) | PORT_PDR_B1_BIT); /* 7seg_led用ポート出力設定 */ sil_wrb_mem((uint8_t *)PORTD_PDR_ADDR, 0xFF); /* SWITCH用ポート入力、LED用ポート出力設定 */ sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F); /* LEDを"0000"と表示 */ sil_wrb_mem((uint8_t *)PORTE_PDR_ADDR, 0x0F); /* 3ms後に7SEG表示を更新 */ main_led_timer = 3 * 1000; /* 10ms後にボタン状態を確認 */ main_timer = 10 * 1000; /* 12bitADC初期化 */ sil_wrh_mem((uint16_t *)S12AD_ADEXICR_ADDR, 0x0000); /* 温度センサ出力、内部基準電圧非選択 */ sil_wrh_mem((uint16_t *)S12AD_ADANS0_ADDR, 0x00FF); /* 変換ポートAN000~AN007選択、AN008~AN015非選択 */ sil_wrh_mem((uint16_t *)S12AD_ADANS1_ADDR, 0x0000); /* 変換ポートAN016~AN020非選択 */ /* ボタン状態読み込み */ btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR); main_btn1_state = (btn & 0x20) != 0; main_btn2_state = (btn & 0x80) != 0; /* 1秒後に表示を更新 */ main_adv_timer = 1000 * 1000; ER ret = act_tsk(MAIN_TASK); if (ret != E_OK) { syslog(LOG_ERROR, "act_tsk"); } } /* * タイマー取得 */ static int main_get_timer() { int result = main_timer; if((result == TMO_FEVR) || ((main_led_timer != TMO_FEVR) && (main_led_timer < result))){ result = main_led_timer; } if ((result == TMO_FEVR) || ((main_adv_timer != TMO_FEVR) && (main_adv_timer < result))) { result = main_adv_timer; } return result; } /* * 時間経過 */ static void main_progress(int interval) { if(main_timer != TMO_FEVR){ main_timer -= interval; if(main_timer < 0){ main_timer = 0; } } if(main_led_timer != TMO_FEVR){ main_led_timer -= interval; if(main_led_timer < 0){ main_led_timer = 0; } } if (main_adv_timer != TMO_FEVR) { main_adv_timer -= interval; if (main_adv_timer < 0) { main_adv_timer = 0; } } } /* * Echonet電文受信処理 */ static void main_recv_esv(T_EDATA *esv) { ER ret; uint8_t epc; uint8_t pdc; uint8_t p_edt[256]; T_ENUM_EPC enm; ret = ecn_itr_ini(&enm, esv); if(ret != E_OK){ syslog(LOG_ERROR, "ecn_itr_ini"); return; } for(;;) { while((ret = ecn_itr_nxt(&enm, &epc, &pdc, p_edt)) == E_OK) { switch (epc) { case 0x80: break; case 0x81: break; } } if(ret != E_BOVR){ syslog(LOG_ERROR, "ecn_itr_nxt"); break; } if(enm.is_eof) break; } } /* * 応答電文待ちの割り込み処理 */ static void main_break_wait(uint8_t *brkdat, int32_t len) { switch(main_state){ case main_state_idle: if (len == 0) break; switch (brkdat[0]) { case 1: switch (brkdat[1]) { case 1: break; case 2: break; } } break; } } static void main_ontimer(); static void main_led_ontimer(); static void main_adv_ontimer(); /* * タイムアウト処理 */ static void main_timeout() { if(main_timer == 0){ main_ontimer(); } if(main_led_timer == 0){ main_led_ontimer(); } if (main_adv_timer == 0) { main_adv_ontimer(); } } #define main_7seg_count 4 static uint8_t main_7seg[main_7seg_count] = { 0xDA, 0xF2, 0xB6, 0xB6 }; static int main_7seg_pos = 0; const uint8_t led_disp[] = { 0xFC, 0x60, 0xDA, 0xF2, 0x66, 0xB6, 0xBE, 0xE4, 0xFE, 0xF6, 0xEE, 0x3E, 0x1A, 0x7A, 0x9E, 0x8E }; static void main_led_ontimer() { /* 7Seg表示 */ sil_wrb_mem((uint8_t *)PORTD_PODR_ADDR, ~main_7seg[main_7seg_pos]); if (main_7seg_pos == 0) sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR) & ~PORT_PODR_B4_BIT); else sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR) | PORT_PODR_B4_BIT); if (main_7seg_pos == 1) sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR) & ~PORT_PODR_B3_BIT); else sil_wrb_mem((uint8_t *)PORT2_PODR_ADDR, sil_reb_mem((uint8_t *)PORT2_PODR_ADDR) | PORT_PODR_B3_BIT); if (main_7seg_pos == 2) sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR) & ~PORT_PODR_B3_BIT); else sil_wrb_mem((uint8_t *)PORT5_PODR_ADDR, sil_reb_mem((uint8_t *)PORT5_PODR_ADDR) | PORT_PODR_B3_BIT); if (main_7seg_pos == 3) sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR) & ~PORT_PODR_B1_BIT); else sil_wrb_mem((uint8_t *)PORTC_PODR_ADDR, sil_reb_mem((uint8_t *)PORTC_PODR_ADDR) | PORT_PODR_B1_BIT); main_7seg_pos = (main_7seg_pos + 1) & 0x3; /* 3ms後に7SEG表示を更新 */ main_led_timer = 3 * 1000; } #define main_ad_count 8 #define main_ad_table_count 64 static uint16_t main_ad_table[main_ad_count][main_ad_table_count]; static int main_ad_pos = 0; static uint32_t main_ad_avelage[main_ad_count]; static uint64_t main_ad_integral[main_ad_count]; volatile uint16_t *const main_ad_addr[main_ad_count] = { (uint16_t *)S12AD_ADDR0_ADDR, (uint16_t *)S12AD_ADDR1_ADDR, (uint16_t *)S12AD_ADDR2_ADDR, (uint16_t *)S12AD_ADDR3_ADDR, (uint16_t *)S12AD_ADDR4_ADDR, (uint16_t *)S12AD_ADDR5_ADDR, (uint16_t *)S12AD_ADDR6_ADDR, (uint16_t *)S12AD_ADDR7_ADDR, }; uint8_t main_port_no = 1; static void main_7seg_view(int port_no); static void main_btn1_change(bool_t push); static void main_btn2_change(bool_t push); /* * タイムアウト処理 */ static void main_ontimer() { uint8_t btn; uint16_t ad_value; switch(main_state){ case main_state_idle: /* 10ms後にボタン状態を確認 */ main_timer = 10 * 1000; /* ADCの変換結果取得 */ if((sil_reb_mem((uint8_t *)S12AD_ADCSR_ADDR) & S12AD_ADCSR_ADST_BIT) == 0){ for (int i = 0; i < main_ad_count; i++) { main_ad_avelage[i] -= main_ad_table[i][main_ad_pos]; ad_value = sil_reh_mem(main_ad_addr[i]); // 12bit値取得 main_ad_integral[i] += 5/*[V]*/ * ad_value/*[A]*/; // 12bit積算値 ad_value = (ad_value << 4) | (ad_value >> 12); // 16bit拡張 main_ad_table[i][main_ad_pos] = ad_value; main_ad_avelage[i] += ad_value; } main_ad_pos++; if (main_ad_pos >= main_ad_table_count) { main_ad_pos = 0; } /* 変換開始(シングルスキャンモード) */ sil_wrb_mem((uint8_t *)S12AD_ADCSR_ADDR, S12AD_ADCSR_ADST_BIT); } main_whm_counter += 10; if (main_whm_counter >= 1250/* 180000=30分 */) { main_whm_counter = 0; for (int i = 0; i < 6; i++) { uint64_t carry; carry = whm_add_integral_value(&electric_energy_meter_data[i], main_ad_integral[i] / ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/))); main_ad_integral[i] -= carry * ((uint64_t)(10LL/* 0.01kWh */ * 360000LL/*=hour*/ * ((1 << 12) - 1) / 2.4/*4095=2.4A*/)); } if (electric_energy_meter_data[0].current_pos == 0) { cmd_execute("logupload", NULL); } } /* ボタン状態読み込み */ btn = sil_reb_mem((uint8_t *)PORT0_PIDR_ADDR); /* ボタン1の処理 */ if(((btn & 0x20) != 0) && !main_btn1_state){ main_btn1_count++; if(main_btn1_count > 10){ main_btn1_count = 0; main_btn1_state = true; main_btn1_change(true); } } else if(((btn & 0x20) == 0) && main_btn1_state){ main_btn1_count++; if(main_btn1_count > 10){ main_btn1_count = 0; main_btn1_state = false; main_btn1_change(false); } } /* ボタン2の処理 */ if(((btn & 0x80) != 0) && !main_btn2_state){ main_btn2_count++; if(main_btn2_count > 10){ main_btn2_count = 0; main_btn2_state = true; main_btn2_change(true); } } else if(((btn & 0x80) == 0) && main_btn2_state){ main_btn2_count++; if(main_btn2_count > 10){ main_btn2_count = 0; main_btn2_state = false; main_btn2_change(false); } } main_7seg_view(main_port_no); break; } } bool_t main_rev = false; /* * ボタン1状態変化処理 */ static void main_btn1_change(bool_t push) { /* 押されて戻った時に処理する */ if(push) return; /* 表示ポート番号 */ if(!main_rev){ main_port_no--; if(main_port_no < 1){ main_port_no = 1; main_rev = true; main_adv_timer = 2000 * 1000; } } else{ main_port_no++; if(main_port_no > main_ad_count){ main_port_no = main_ad_count; main_rev = false; main_adv_timer = 2000 * 1000; } } } /* * ボタン2状態変化処理 */ static void main_btn2_change(bool_t push) { /* 押されて戻った時に処理する */ if(push) return; int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR); if ((swt & 0x20) == 0) { return; } /* 表示ポート番号 */ if(!main_rev){ main_port_no++; if(main_port_no > main_ad_count){ main_port_no = main_ad_count; main_rev = false; main_adv_timer = 2000 * 1000; } } else{ main_port_no--; if(main_port_no < 1){ main_port_no = 1; main_rev = true; main_adv_timer = 2000 * 1000; } } } static void main_adv_ontimer() { int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR); if (swt & 0x20) { main_adv_timer = TMO_FEVR; return; } main_port_no++; if(main_port_no > main_ad_count) main_port_no = 1; main_adv_timer = 2000 * 1000; } static void main_7seg_view(int port_no) { if ((port_no < 1) || (port_no > main_ad_count)) return; int swt = sil_reb_mem((uint8_t *)PORTE_PIDR_ADDR); port_no--; uint32_t adv = (main_ad_avelage[port_no] / main_ad_table_count); if (swt & 0x10) { main_7seg[0] = led_disp[port_no + 1] | 1; main_7seg[1] = led_disp[(adv & 0xF000) >> 12]; main_7seg[2] = led_disp[(adv & 0x0F00) >> 8]; main_7seg[3] = led_disp[(adv & 0x00F0) >> 4]; } else { uint32_t tmp = adv / 26214; main_7seg[0] = led_disp[port_no + 1] | 1; main_7seg[1] = led_disp[tmp] | 1; adv = 10 * (adv - tmp * 26214); tmp = adv / 26214; main_7seg[2] = led_disp[tmp]; adv = 10 * (adv - tmp * 26214); tmp = adv / 26214; main_7seg[3] = led_disp[tmp]; } }