なんと、私のブログで「共有メモリ」やら「プロセス間通信」なる言葉を使うとは、恐れを知らない素人プログラマー。だって趣味で自分使用のラズパイの話ですから、お構いなしです。
早めにお詫びして起きます。この投稿は無知な私が書いた物なので、全てが誤りかも知れません。
/*
* zeroClock.cpp
*
* プロセス間通信 共有メモリテスト
* NTPチェック用プログラム(プロセス)が書き込んだ共有メモリに応じて表示を変える。
*
* その別プロセスがntpq -p 実行結果に応じて
* NTPサーバー参照同期中ならGを共有メモリに書き込み
* そうでなければWを書き込む。
*
* このプログラムは共有メモリを読み込んで
* Gなら正常時計表示、Wの場合全桁ドット表示させる。
*
*/
#include <iostream>
#include <pigpio.h>
#include <unistd.h>
#include <sys/shm.h>
#define H 0x1
#define L 0x0
#define SEG_ON 0x1
#define SEG_OFF 0x0
using namespace std;
int mainLoop(void);
int main(void)
{
if(daemon(0, 0) == 0) { // デーモン関数
mainLoop();
} else {
cout << "error" << endl;
}
return 0;
}
int mainLoop(void)
{
int i, j, disp;
int num[7];
struct timespec ts;
struct tm lotm;
// 0.1秒1秒 10秒 1分 10分 1時 10時
// Common 1 2 3 4 5 6 7
static int common[7] = {25, 24, 23, 18, 22, 27, 17};
// GPIO 25 24 23 18 22 27 17
// 7seg a b c d e f g dp NTP
static int nanaseg[9] = {21, 20, 16, 26, 19, 6, 13, 5, 12};
// GPIO 21 20 16 26 19 6 13 5 12
static int segdata[12][9] = { // 7セグメント & NTP用LED データ
// a b c d e f g dp NTP
{H, H, H, H, H, H, L, L, H}, // 0
{L, H, H, L, L, L, L, L, H}, // 1
{H, H, L, H, H, L, H, L, H}, // 2
{H, H, H, H, L, L, H, L, H}, // 3
{L, H, H, L, L, H, H, L, H}, // 4
{H, L, H, H, L, H, H, L, H}, // 5
{H, L, H, H, H, H, H, L, H}, // 6
{H, H, H, L, L, L, L, L, H}, // 7
{H, H, H, H, H, H, H, L, H}, // 8
{H, H, H, H, L, H, H, L, H}, // 9
{L, L, L, L, L, L, L, L, H}, // Blank
{L, L, L, L, L, L, L, H, L}, // dp
};
// pigpioライブラリ初期化
if (gpioInitialise() < 0) exit(1);
// コモン用GPIOピンをアウトプット設定
for (i = 0; i < 7; i++) {
gpioSetMode(common[i], PI_OUTPUT);
}
// セグメント用GPIOピンをアウトプット設定(NTP用LEDを含む)
for (i = 0; i < 9; i++) {
gpioSetMode(nanaseg[i], PI_OUTPUT);
}
/*
*
* 共有メモリ設定
*
*/
// 作成済みの共有メモリのIDを取得する
const string file_path = "/home/pi/ntpCheck.dat";
const int id = 50;
const key_t key = ftok(file_path.c_str(), id);
const int seg_id = shmget(key, 0, 0);
if(seg_id == -1){
cerr << "Failed to acquire segment" << endl;
return EXIT_FAILURE;
}
// 共有メモリをプロセスにアタッチする
char* const shared_memory =
reinterpret_cast<char*>(shmat(seg_id, 0, 0));
/*
*
* 時刻取得及びダイナミック表示ルーチン(無限ループ)
*
* 時刻取得、1桁2ミリ秒表示×7、時刻取得、1桁2ミリ秒表示×7の繰り返し
*
* 共有メモリの文字が
* G の場合はNTPサーバと参照同期中
* W の場合はNTPサーバと参照同期していない
*
*/
while (1) {
// 共有メモリから読み込んだ文字により表示を変える
switch (*shared_memory) {
case 0x47: // G (Good) G ASCII Code // G の場合正常時計表示
clock_gettime(CLOCK_REALTIME, &ts); // 時刻の取得
localtime_r(&ts.tv_sec, &lotm); // ローカル時間に変換
num[0] = ts.tv_nsec / 100000000; //0.1秒の桁取得
num[1] = lotm.tm_sec % 10; // 1秒の桁取得
num[2] = lotm.tm_sec / 10; // 10秒の桁取得
num[3] = lotm.tm_min % 10; // 1分の桁取得
num[4] = lotm.tm_min / 10; // 10分の桁取得
num[5] = lotm.tm_hour % 10; // 1時の桁取得
num[6] = lotm.tm_hour / 10; // 10時の桁取得
disp = 2000; // 2ミリ秒
break;
case 0x57: // W (Wait) 0x57 ASCII Code // W の場合ドット表示
for (i = 0; i < 7; i++) {
num[i] = 11; // 全桁 D.P & NTP用LED消灯 セット
}
disp = 100000; // 100ミリ秒
break;
}
for (j = 0; j < 7; j++) { // 7桁ダイナミック表示ルーチン
for (i = 0; i < 9; i++) { // 7セグメントデータセット
gpioWrite(nanaseg[i], segdata[num[j]][i]);
}
gpioWrite(common[j], SEG_ON); // 7セグLED点灯
gpioDelay(disp); // 点灯維持
gpioWrite(common[j], SEG_OFF); // 7セグLED消灯
}
}
// ここから以降は無限ループに含まれないので不要?
// pigpioライブラリ終了処理
gpioTerminate();
// 共有メモリをプロセスから切り離す
shmdt(shared_memory);
return 0;
}