TARGET = scilog
-OBJS = scilog.o spi.o thread_rcv.o ring.o ad_ring.o thread_rec.o sts.o ad_file.o conf.o
+OBJS = scilog.o spi.o thread_rcv.o ring.o ad_ring.o thread_rec.o sts.o ad_file.o conf.o lcd.o
-HDRS = mes_print.h debug_print.h spi.h my_thread.h ring.h ad_ring.h thread_rec.h sts.h ad_file.h conf.h
+HDRS = mes_print.h debug_print.h spi.h my_thread.h ring.h ad_ring.h thread_rec.h sts.h ad_file.h conf.h lcd.h
${TARGET} : $(OBJS) $(HDRS)
${CC} ${CFLAGS} ${OBJS} -L ${LIBDIR} -o ${TARGET}
#define __AVG_RING_H__
#include <time.h>
+#include "spi.h"
// リングバッファサイズ 個数
#define AD_RING_NUM (60 * 5)
// リングバッファのデータタイプ
typedef struct {
+ char rescode; // コマンドに対する返答 ACK/NAK/NUL
+ char resdata[SPI_RESDATA_LEN]; // コマンドに対する返答データ
UbloxNavTimeUtc gps; // GPSタイムスタンプ SPIで受信
struct tm t; // タイムスタンプ struct tmの月は(0〜11)なので注意 年は1900からのオフセット
int freq; // 平均周波数 Hz
long data1sec[AD_CHNUM]; // 1sec平均値 SPIで受信
long data[AD_CHNUM][AD_SAMPLE]; // AD_SAMPLE[Hz]の生データ SPIで受信
long avg[AD_CHNUM][AD_SAMPLE]; // 平均後データ
+ unsigned int checksum; // SPI受信データのchecksumフィールド
} AdData;
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/i2c-dev.h> /* for I2C_SLAVE */
+
+#include "mes_print.h"
+#include "lcd.h"
+
+#define DEV_LCD "/dev/i2c-3"
+
+
+static int fh = -1;
+
+static int lcd_open(void)
+{
+ fh = open(DEV_LCD, O_RDWR);
+ return fh;
+}
+static void lcd_close(void)
+{
+ close(fh);
+ fh = -1;
+}
+// 1byte out
+static void lcd_out(unsigned char dat, char rs)
+{
+ unsigned char data[2];
+
+ if (lcd_open() < 0) {
+ PERRF("ERROR lcd_open()\n");
+ return;
+ }
+ ioctl(fh, I2C_SLAVE, I2CLCD_ADDRESS >> 1);
+
+ data[0] = rs ? 0x40 : 0x00; // RS
+ data[1] = dat;
+ write(fh, data, 2);
+
+ lcd_close();
+}
+/*
+ 複数バイトout
+ RS=1
+*/
+static void lcd_out_mul(unsigned char *out, int len)
+{
+ unsigned char data[256];
+
+ if (lcd_open() < 0) {
+ PERRF("ERROR lcd_open()\n");
+ return;
+ }
+ ioctl(fh, I2C_SLAVE, I2CLCD_ADDRESS >> 1);
+
+ data[0] = 0x40; // RS = 1
+ if (len >= sizeof(data)) len = sizeof(data)-1;
+ memcpy(data+1, out, len);
+ write(fh, data, len+1);
+
+ lcd_close();
+}
+/*
+ i2c LCDモジュールの設定
+*/
+static void i2clcd_init(void)
+{
+ unsigned char data[16];
+ unsigned char cfg;
+
+ fh = -1;
+ if (lcd_open() < 0) {
+ PERRF("ERROR lcd_open()\n");
+ return;
+ }
+ ioctl(fh, I2C_SLAVE, I2CLCD_ADDRESS >> 1);
+
+ cfg = 0;
+ data[0] = I2CLCD_CFG_ENABLE | (cfg & 0x1f);
+ data[1] = 0;
+ write(fh, data, 2);
+
+ lcd_close();
+}
+/*
+ LCD初期化
+*/
+void lcd_init(void)
+{
+ unsigned char func, display, entry;
+
+ i2clcd_init();
+ usleep(10*1000);
+
+ lcd_out(0x30, 0);
+ usleep(5*1000);
+ lcd_out(0x30, 0);
+ usleep(2*1000);
+ lcd_out(0x30, 0);
+
+ func = I2CLCD_8BITMODE | I2CLCD_2LINE | I2CLCD_5x8DOTS;
+// shift =
+ display = I2CLCD_DISPLAYON | I2CLCD_CURSOROFF | I2CLCD_BLINKOFF;
+ entry = I2CLCD_ENTRYLEFT;
+
+ lcd_out(0x20 | (func & 0x1f), 0); // func
+// lcd_out(0x10 | (shift & 0x0f), 0); // shift
+ lcd_out(0x08 | (display & 0x07), 0); // display
+ lcd_out(0x04 | (entry & 0x03), 0); // entry mode
+
+ lcd_clear();
+ lcd_home();
+}
+/*
+ int x,y: 0始まり
+*/
+void lcd_pos(int x, int y)
+{
+ unsigned char adr;
+ unsigned char ofs[] = {0, 0x40, 0x14, 0x54 };
+
+ if (y >= LCD_YMAX) y = LCD_YMAX - 1;
+ if (x >= LCD_XMAX) x = LCD_XMAX - 1;
+ adr = ofs[y] + x;
+ lcd_out(I2CLCD_SETDDRAMADDR | (adr & 0x7F), 0);
+}
+
+void lcd_print(char *str)
+{
+ lcd_out_mul((unsigned char*)str, strlen(str));
+}
+void lcd_clear(void)
+{
+ lcd_out(I2CLCD_CLEARDISPLAY, 0);
+usleep(2*1000);
+}
+void lcd_home(void)
+{
+ lcd_out(I2CLCD_RETURNHOME, 0);
+usleep(2*1000);
+}
+
+
--- /dev/null
+#if !defined(__I2CLCD_H__)
+#define __I2CLCD_H__
+
+#define I2CLCD_ADDRESS 0x7c
+// i2c LCDモジュール設定用
+#define I2CLCD_CFG_ENABLE 0x20
+#define I2CLCD_CFG_LED 0x08
+#define I2CLCD_CFG_3V 0x04
+#define I2CLCD_CFG_ADDR 0x02
+#define I2CLCD_CFG_INIT 0x01
+
+// commands
+#define I2CLCD_CLEARDISPLAY 0x01
+#define I2CLCD_RETURNHOME 0x02
+#define I2CLCD_ENTRYMODESET 0x04
+#define I2CLCD_DISPLAYCONTROL 0x08
+#define I2CLCD_CURSORSHIFT 0x10
+#define I2CLCD_FUNCTIONSET 0x20
+#define I2CLCD_SETCGRAMADDR 0x40
+#define I2CLCD_SETDDRAMADDR 0x80
+
+// flags for display entry mode
+#define I2CLCD_ENTRYRIGHT 0x00
+#define I2CLCD_ENTRYLEFT 0x02
+#define I2CLCD_ENTRYSHIFTINCREMENT 0x01
+#define I2CLCD_ENTRYSHIFTDECREMENT 0x00
+
+// flags for display on/off control
+#define I2CLCD_DISPLAYON 0x04
+#define I2CLCD_DISPLAYOFF 0x00
+#define I2CLCD_CURSORON 0x02
+#define I2CLCD_CURSOROFF 0x00
+#define I2CLCD_BLINKON 0x01
+#define I2CLCD_BLINKOFF 0x00
+
+// flags for display/cursor shift
+#define I2CLCD_DISPLAYMOVE 0x08
+#define I2CLCD_CURSORMOVE 0x00
+#define I2CLCD_MOVERIGHT 0x04
+#define I2CLCD_MOVELEFT 0x00
+
+// flags for function set
+#define I2CLCD_8BITMODE 0x10
+#define I2CLCD_4BITMODE 0x00
+#define I2CLCD_2LINE 0x08
+#define I2CLCD_1LINE 0x00
+#define I2CLCD_5x10DOTS 0x04
+#define I2CLCD_5x8DOTS 0x00
+
+#define LCD_YMAX 4
+#define LCD_XMAX 20
+
+void lcd_init(void);
+void lcd_pos(int x, int y);
+void lcd_print(char *str);
+void lcd_clear(void);
+void lcd_home(void);
+
+#endif
#include "thread_rec.h"
#include "conf.h"
#include "ad_file.h"
+#include "lcd.h"
// debug_print.h内で#define DEBUG_PRINTしているので
// リリース時は、debug_print.hでコメントする
signal(SIGKILL, sig_handler);
signal(SIGTERM, sig_handler);
-// lcd_init();
-// lcd_pos(6, 1);
-// lcd_print("sciLogger");
-// lcd_pos(0, 3);
+ lcd_init();
+ lcd_pos(6, 1);
+ lcd_print("sciLogger");
+ lcd_pos(0, 3);
ad_ring_init();
sts_init();
// 設定ファイル読み込み
conf_read();
PDEBUG("freq=%d\n", conf_freq_get());
-// lcd_print("*");
+ lcd_print("*");
PDEBUG("sciLogger %s START\n", VERSION);
sleep(1);
perror("spi_open() ERROR!");
goto END;
}
-// lcd_print(fd_lcd0, "*");
+ lcd_print("*");
//
/**** スレッド生成
} else {
PDEBUG("SPI RCV thread create\n");
}
-// lcd_print("*");
+ lcd_print("*");
//
/**** メインループ 記録 ************************
\r
// SPI送信データ長セット\r
#define CMD_TX_LEN 12\r
-// SPI送信データセット\r
+// SPI送信データセット PICへのコマンド\r
#define CMD_TX_SET 13\r
-\r
// リングバッファにあるデータ数を返す\r
#define CMD_DNUM_GET 14\r
-\r
// リングバッファクリア\r
#define CMD_BUF_CLEAR 15\r
-\r
// SPIで実際に受信したデータ長を取得\r
#define CMD_RECEIVED_LEN_GET 20\r
\r
// SPIで受信するデータ長 固定長 $含む\r
-#define SPI_DATA_LEN 945\r
-// SPI受信データの先頭文字\r
+#define SPI_DATA_LEN 965\r
+// SPI受信データの先頭文字 送信コマンドでも使用\r
#define SPI_HEAD_CHAR '$'\r
\r
+// SPI受信データ 応答データ 長さ\r
+#define SPI_RESDATA_LEN 17\r
+\r
+// SPI受信データ Checksum 長さ\r
+#define SPI_CHECKSUM_LEN 2\r
+\r
+// SPI送信するコマンド長 固定長 $含む\r
+#define SPI_CMD_LEN 20\r
+\r
+\r
// SPI受信データの先頭からのオフセット\r
-#define SPI_OFS_GPS (18-17)\r
-#define SPI_OFS_1SEC (38-17)\r
-#define SPI_OFS_DATA (62-17)\r
+#define SPI_OFS_GPS (19)\r
+#define SPI_OFS_1SEC (39)\r
+#define SPI_OFS_DATA (63)\r
\r
\r
\r
#include <sys/types.h>\r
#include <string.h>\r
\r
+#include "debug_print.h"\r
#include "spi.h"\r
#include "ad_ring.h"\r
#include "conf.h"\r
gps = &(ad->gps);\r
\r
if (*ptr++ != SPI_HEAD_CHAR) return -1;\r
+ // Response Code\r
+ ad->rescode = *ptr++;\r
+ // Response Data\r
+ memcpy(ad->resdata, ptr, SPI_RESDATA_LEN);\r
+ ptr += SPI_RESDATA_LEN;\r
// GPS\r
gps->tow = *((int32_t*)ptr); ptr += 4;\r
gps->tacc = *((int32_t*)ptr); ptr += 4;\r
}\r
}\r
// Checksum\r
+ memcpy(&(ad->checksum), ptr, SPI_CHECKSUM_LEN);\r
\r
// gps->struct tm\r
ad->t.tm_year = gps->year - 1900;\r
}\r
void* thread_rcv(void* pParam)\r
{\r
- while(1) {\r
- fd_set fds;\r
- char buf[SPI_DATA_LEN+256];\r
- int i;\r
-// int ch;\r
- int fd_spi;\r
- AdData ad, *ad_ptr;\r
\r
+ fd_set fds;\r
+ char buf[SPI_DATA_LEN+256];\r
+ int i;\r
+ int fd_spi;\r
+ AdData ad, *ad_ptr;\r
+#if 0\r
+char cmd[SPI_CMD_LEN];\r
+char c;\r
+c=0;\r
+#endif\r
+ // spiドライバのリングバッファクリア\r
+ spi_buf_clear();\r
+ // spi送信コマンド長セット\r
+ spi_tx_len_set(SPI_CMD_LEN);\r
+\r
+ while(1) {\r
fd_spi = spi_get_fd();\r
// select の準備\r
FD_ZERO(&fds);\r
i = select(fd_spi + 1, &fds, NULL, NULL, NULL); // 読みselect\r
if(i <= 0) syslog(LOG_ERR, "%s: select returned with signal or error. ret=%d\n", __FUNCTION__, i);\r
if(FD_ISSET(fd_spi, &fds)) {\r
+#if 0\r
+// SPI送信データセット\r
+memset(cmd, 0, SPI_CMD_LEN);\r
+cmd[0] = SPI_HEAD_CHAR;\r
+cmd[1] = 1;\r
+cmd[2] = 2;\r
+cmd[3] = c++;\r
+spi_tx_set(cmd);\r
+#endif\r
// 受信した\r
i = spi_dnum_get();\r
-//printf("thread_rcv(): wakeup dnum=%d rcv_len=%d\n", i, spi_rcvd_len_get());\r
+//PDEBUG("thread_rcv(): wakeup dnum=%d rcv_len=%d\n", i, spi_rcvd_len_get());\r
while(i-- > 0) {\r
memset(&ad, 0, sizeof(ad));\r
// データ取得\r
ad.freq = conf_freq_get();\r
// 平均 仮コード 要変更\r
do_avg(AD_SAMPLE, &ad);\r
-#if 0\r
-printf("%04d/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X",\r
- ad.t.year, ad.t.month, ad.t.day, ad.t.hour, ad.t.min, ad.t.sec, ad.t.nano,\r
- ad.t.tow, ad.t.tacc, ad.t.valid);\r
+#if 1\r
+int ch;\r
+PDEBUG("%04d/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X",\r
+ ad.gps.year, ad.gps.month, ad.gps.day, ad.gps.hour, ad.gps.min, ad.gps.sec, ad.gps.nano,\r
+ ad.gps.tow, ad.gps.tacc, ad.gps.valid);\r
for(ch = 0; ch < AD_CHNUM; ch++) {\r
- printf(",%+7ld", ad.data1sec[ch]);\r
+ PDEBUG(",%+7ld", ad.data1sec[ch]);\r
}\r
-printf("\r\n");\r
+PDEBUG("\r\n");\r
+#endif\r
+#if 0\r
for(ch = 0; ch < AD_CHNUM; ch++) {\r
- printf(",%+7ld", ad.data[ch][0]);\r
+ PDEBUG(",%+7ld", ad.data[ch][0]);\r
}\r
-printf("\r\n");\r
+PDEBUG("\r\n");\r
for(ch = 0; ch < AD_CHNUM; ch++) {\r
- printf(",%+7ld", ad.data[ch][49]);\r
+ PDEBUG(",%+7ld", ad.data[ch][49]);\r
}\r
-printf("\r\n");\r
+PDEBUG("\r\n");\r
#endif\r
// ADリングバッファに書き込み\r
ad_ptr = ad_ring_get(ad_ring_write_get());\r
#include "ad_file.h"
// 1secファイル書き込み間隔 sec
-#define SEC_FLUSH_NUM 1
-//#define SEC_FLUSH_NUM 60
+//#define SEC_FLUSH_NUM 1
+#define SEC_FLUSH_NUM 60
// 高速サンプルファイル書き込み間隔 sec
-#define HIGH_FLUSH_NUM 1
+//#define HIGH_FLUSH_NUM 1
+#define HIGH_FLUSH_NUM 10
// 日付変化検出用
static struct tm high_tm;
while(ad_ring_num_get_sec() > 0) {
// データ取り出し
d = ad_ring_get(ad_ring_read_get_sec());
+#if 0
PDEBUG("%04d/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X",
d->gps.year, d->gps.month, d->gps.day, d->gps.hour, d->gps.min, d->gps.sec, d->gps.nano,
d->gps.tow, d->gps.tacc, d->gps.valid);
PDEBUG(",%+7ld", d->data1sec[ch]);
}
PDEBUG("\r\n");
+#endif
// 日にち変わった ファイル切換する
#ifdef DEBUG_FILE_MIN