Overoで動作するデータ収録プログラム
サブCPUからGPS時刻付きADデータを取得してSDに記録する。
Revisão | 1502df658e0de66863f3c51d862ce91239f4c0a5 (tree) |
---|---|
Hora | 2011-12-09 17:20:22 |
Autor | Naoya Takamura <ntaka206@user...> |
Commiter | Naoya Takamura |
1sec and high smpling file record add.
@@ -30,9 +30,9 @@ INCDIR = ${STAGEDIR}/include | ||
30 | 30 | |
31 | 31 | TARGET = scilog |
32 | 32 | |
33 | -OBJS = scilog.o spi.o thread_rcv.o | |
33 | +OBJS = scilog.o spi.o thread_rcv.o ring.o ad_ring.o thread_rec.o sts.o ad_file.o conf.o | |
34 | 34 | |
35 | -HDRS = mes_print.h debug_print.h spi.h my_thread.h | |
35 | +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 | |
36 | 36 | |
37 | 37 | ${TARGET} : $(OBJS) $(HDRS) |
38 | 38 | ${CC} ${CFLAGS} ${OBJS} -L ${LIBDIR} -o ${TARGET} |
@@ -0,0 +1,260 @@ | ||
1 | +/* | |
2 | + 1secファイル | |
3 | + 高速サンプルファイル | |
4 | + | |
5 | +#define DEBUG_FILE_MIN | |
6 | + 定義するとファイルが1日単位ではなく指定された分単位になる | |
7 | + ただし、ファイルのサイズは1日と同じサイズのまま | |
8 | +#deifne DEBUG_FILE_MIN_PERIOD | |
9 | + ファイルの単位 | |
10 | + 単位 分 | |
11 | + | |
12 | +*/ | |
13 | +#include <stdio.h> | |
14 | +#include <string.h> | |
15 | +#include <sys/types.h> | |
16 | +#include <sys/stat.h> | |
17 | +#include <stdlib.h> | |
18 | +#include <syslog.h> | |
19 | +#include <errno.h> | |
20 | +#include <unistd.h> | |
21 | + | |
22 | +#include "ad_ring.h" | |
23 | +#include "ad_file.h" | |
24 | +#include "debug_print.h" | |
25 | +#include "conf.h" | |
26 | + | |
27 | +// mkdir_p()で使用する | |
28 | +#define MKDIR_MODE "755" | |
29 | + | |
30 | +/**** util | |
31 | +*/ | |
32 | +/* | |
33 | + 指定さえれたディレクトリを作成 | |
34 | + 親がないときは親まで作る | |
35 | + char *mode | |
36 | + 755とか | |
37 | + return | |
38 | + 0=OK | |
39 | + -1=ERROR | |
40 | +*/ | |
41 | +static int mkdir_p(const char *path, char *mode) | |
42 | +{ | |
43 | + struct stat st; | |
44 | + char cmd[128]; | |
45 | + | |
46 | + // コピー先ディレクトリ存在しなければ作成する | |
47 | + if (stat(path, &st) == -1) { | |
48 | + PDEBUG("mkdir_p(): make dir %s\n", path); | |
49 | + | |
50 | + sprintf(cmd, "mkdir -p -m %s %s > /dev/null 2> /dev/null &", mode, path); | |
51 | + switch(system(cmd)) { | |
52 | + case 127: | |
53 | + // shell exec error | |
54 | + PDEBUG("mkdir_p(): shell exec error\n"); | |
55 | + syslog(LOG_ERR, "mkdir_p(): system() shell exec error"); | |
56 | + return -1; | |
57 | + case -1: | |
58 | + // error | |
59 | + PDEBUG("mkdir_p(): error\n"); | |
60 | + syslog(LOG_ERR, "mkdir_p(): system() error"); | |
61 | + return -1; | |
62 | + default: | |
63 | + // 作成されるまで待つ | |
64 | + sleep(3); | |
65 | + return 0; | |
66 | + } | |
67 | + } | |
68 | + return 0; | |
69 | +} | |
70 | + | |
71 | + | |
72 | +/**** 1秒ファイル関係 ************************************************************ | |
73 | +*/ | |
74 | +/* | |
75 | + 1秒データファイル オープン | |
76 | + | |
77 | + Return: | |
78 | + 1 = Error | |
79 | + 0 = OK | |
80 | + */ | |
81 | +int sec_file_open(FILE **fp, AdData *D) | |
82 | +{ | |
83 | + char szDir[64]; | |
84 | + struct stat st; | |
85 | + char fname[64]; | |
86 | + char path[128]; | |
87 | + | |
88 | + // サブディレクトリ作成 | |
89 | + sprintf(szDir, "%s/%s/%04d/%02d", DIR_DATA, sid_getp(), D->t.tm_year+1900, D->t.tm_mon+1); | |
90 | + // ディレクトリ存在しなければ作成する | |
91 | + if (stat(szDir, &st) == -1) mkdir_p(szDir, MKDIR_MODE); | |
92 | + | |
93 | + // ファイル名作成 | |
94 | +#ifdef DEBUG_FILE_MIN | |
95 | + sprintf(fname, "%04d%02d%02d_%02d%02d.sec", | |
96 | + D->t.tm_year+1900, D->t.tm_mon+1, D->t.tm_mday, D->t.tm_hour, D->t.tm_min / DEBUG_FILE_MIN_PERIOD * DEBUG_FILE_MIN_PERIOD); | |
97 | +#else | |
98 | + sprintf(fname, "%04d%02d%02d.sec", D->t.tm_year+1900, D->t.tm_mon+1, D->t.tm_mday); | |
99 | +#endif | |
100 | + // フルパス作成 | |
101 | + strcpy(path, szDir); | |
102 | + strcat(path, "/"); | |
103 | + strcat(path, fname); | |
104 | + PDEBUGF("path=%s\n", path); | |
105 | + | |
106 | + *fp = fopen(path, "a"); | |
107 | + if (*fp == NULL) { | |
108 | + syslog(LOG_ERR, "%s(): fopen() ERROR. %s", __FUNCTION__, strerror(errno)); | |
109 | + return 1; | |
110 | + } | |
111 | + return 0; | |
112 | +} | |
113 | +/* | |
114 | + Return: | |
115 | + 1 = Error | |
116 | + 0 = OK | |
117 | + */ | |
118 | +int sec_file_out(FILE *fp, char *out, int len) | |
119 | +{ | |
120 | + int ret; | |
121 | + | |
122 | + if (fp == NULL) return 1; | |
123 | + if ((ret = fwrite(out, 1, len, fp)) < len) { | |
124 | + syslog(LOG_ERR, "%s(): fwrite() return %d < %d. %s", __FUNCTION__, ret, len, strerror(errno)); | |
125 | + return 1; | |
126 | + } | |
127 | + return 0; | |
128 | +} | |
129 | +/* | |
130 | + 1秒データファイル クローズ | |
131 | + | |
132 | + Return: | |
133 | + 1 = Error | |
134 | + 0 = OK | |
135 | + */ | |
136 | +int sec_file_close(FILE *fp) | |
137 | +{ | |
138 | + if (fp == NULL) return 1; | |
139 | + fclose(fp); | |
140 | + return 0; | |
141 | +} | |
142 | + | |
143 | +/* | |
144 | + 1secファイル記録用データ作る | |
145 | +*/ | |
146 | +int sec_make_rec_data(AdData *ad, char *buf) | |
147 | +{ | |
148 | + char buf2[32]; | |
149 | + int ch; | |
150 | + | |
151 | + sprintf(buf, "%04d/%02d/%02d %02d:%02d:%02d,%3lu,%02X", | |
152 | + ad->gps.year, ad->gps.month, ad->gps.day, ad->gps.hour, ad->gps.min, ad->gps.sec, | |
153 | + ad->gps.tacc, ad->gps.valid); | |
154 | + for(ch = 0; ch < AD_CHNUM; ch++) { | |
155 | + sprintf(buf2, ",%+7ld", ad->data1sec[ch]); | |
156 | + strcat(buf, buf2); | |
157 | + } | |
158 | + strcat(buf, "\n"); | |
159 | + return 0; | |
160 | +} | |
161 | +/**** 高速サンプルファイル関係 ************************************************************ | |
162 | +*/ | |
163 | +/* | |
164 | + Return: | |
165 | + 1 = Error | |
166 | + 0 = OK | |
167 | + */ | |
168 | +int high_file_open(FILE **fp, AdData *D) | |
169 | +{ | |
170 | + char szDir[64]; | |
171 | + struct stat st; | |
172 | + char fname[64]; | |
173 | + char path[128]; | |
174 | + | |
175 | + // サブディレクトリ作成 | |
176 | + sprintf(szDir, "%s/%s/%04d/%02d", DIR_DATA, sid_getp(), D->t.tm_year+1900, D->t.tm_mon+1); | |
177 | + // ディレクトリ存在しなければ作成する | |
178 | + if (stat(szDir, &st) == -1) mkdir_p(szDir, MKDIR_MODE); | |
179 | + | |
180 | + // ファイル名作成 | |
181 | +#ifdef DEBUG_FILE_MIN | |
182 | + sprintf(fname, "%04d%02d%02d_%02d%02d.sec", | |
183 | + D->t.tm_year+1900, D->t.tm_mon+1, D->t.tm_mday, D->t.tm_hour, D->t.tm_min / DEBUG_FILE_MIN_PERIOD * DEBUG_FILE_MIN_PERIOD); | |
184 | +#else | |
185 | + sprintf(fname, "%04d%02d%02d%02d.high", D->t.tm_year+1900, D->t.tm_mon+1, D->t.tm_mday, D->t.tm_hour); | |
186 | +#endif | |
187 | + // フルパス作成 | |
188 | + strcpy(path, szDir); | |
189 | + strcat(path, "/"); | |
190 | + strcat(path, fname); | |
191 | + PDEBUGF("path=%s\n", path); | |
192 | + | |
193 | + *fp = fopen(path, "a"); | |
194 | + if (*fp == NULL) { | |
195 | + syslog(LOG_ERR, "%s(): fopen() ERROR. %s", __FUNCTION__, strerror(errno)); | |
196 | + return 1; | |
197 | + } | |
198 | + return 0; | |
199 | +} | |
200 | +/* | |
201 | + Return: | |
202 | + 1 = Error | |
203 | + 0 = OK | |
204 | + */ | |
205 | +int high_file_out(FILE *fp, char *out, int len) | |
206 | +{ | |
207 | + int ret; | |
208 | + | |
209 | + if (fp == NULL) return 1; | |
210 | + if ((ret = fwrite(out, 1, len, fp)) < len) { | |
211 | + syslog(LOG_ERR, "%s(): fwrite() return %d < %d. %s", __FUNCTION__, ret, len, strerror(errno)); | |
212 | + return 1; | |
213 | + } | |
214 | + return 0; | |
215 | +} | |
216 | +/* | |
217 | + Return: | |
218 | + 1 = Error | |
219 | + 0 = OK | |
220 | + */ | |
221 | +int high_file_close(FILE *fp) | |
222 | +{ | |
223 | + if (fp == NULL) return 1; | |
224 | + fclose(fp); | |
225 | + return 0; | |
226 | +} | |
227 | + | |
228 | +/* | |
229 | + 記録用データ作る | |
230 | +*/ | |
231 | +int high_make_rec_data(AdData *ad, char *ptr) | |
232 | +{ | |
233 | + unsigned char *src; | |
234 | + int ch, i, j; | |
235 | + | |
236 | + *ptr++ = ad->gps.year & 0xFF; | |
237 | + *ptr++ = (ad->gps.year >> 8) & 0xFF; | |
238 | + *ptr++ = ad->gps.month; | |
239 | + *ptr++ = ad->gps.day; | |
240 | + *ptr++ = ad->gps.hour; | |
241 | + *ptr++ = ad->gps.min; | |
242 | + *ptr++ = ad->gps.sec; | |
243 | + *ptr++ = ad->gps.nano; | |
244 | + *ptr++ = ad->gps.valid; | |
245 | + // | |
246 | + src = ad->data; | |
247 | + for(ch = 0; ch < AD_CHNUM; ch++) { | |
248 | + for(i = 0; i < AD_SAMPLE; i++) { | |
249 | + for(j = 0; j < AD_BYTES; j++) { | |
250 | + *ptr++ = *src++; | |
251 | + } | |
252 | + src++; | |
253 | + } | |
254 | + } | |
255 | + return 0; | |
256 | +} | |
257 | + | |
258 | + | |
259 | + | |
260 | + |
@@ -0,0 +1,53 @@ | ||
1 | +#if !defined(__AD_FILE_H__) | |
2 | +#define __AD_FILE_H__ | |
3 | + | |
4 | +#include "ad_ring.h" | |
5 | + | |
6 | +// データ記録用dir 末尾に/付けない | |
7 | +#ifdef DUMMY | |
8 | + #define DIR_DATA "/home/ntaka/dev/arm2011n/data" | |
9 | +#else | |
10 | + #define DIR_DATA "/home/data" | |
11 | +#endif | |
12 | + | |
13 | +#if 0 | |
14 | +// NAV-TIMEUTCパケットのファイル記録用データタイプ | |
15 | +typedef struct { | |
16 | + unsigned long tow; // ms GPS Millisecond Time of Week | |
17 | + unsigned long tacc; // ns Time Accuracy Estimate | |
18 | + long nano; // ns Nanoseconds of second, range -1e9 .. 1e9 (UTC) | |
19 | + unsigned int year __attribute__((aligned(1))); // 12 UTC | |
20 | + unsigned char month __attribute__((aligned(1))); // 16 | |
21 | + unsigned char day __attribute__((aligned(1))); | |
22 | + unsigned char hour __attribute__((aligned(1))); | |
23 | + unsigned char min __attribute__((aligned(1))); | |
24 | + unsigned char sec __attribute__((aligned(1))); | |
25 | + unsigned char valid __attribute__((aligned(1))); // Validity Flags | |
26 | + // bit0 validTOW 1 = Valid Time of Week | |
27 | + // bit1 validWKN 1 = Valid Week Number | |
28 | + // bit2 validUTC 1 = Valid UTC (Leap Seconds already known) | |
29 | +} UbloxNavTimeUtcRecType __attribute__((aligned(1))); | |
30 | + | |
31 | +// 高速サンプルデータ記録用データタイプ | |
32 | +typedef struct { | |
33 | + UbloxNavTimeUtcRecType gps; // GPSタイムスタンプ | |
34 | + unsigned char data[AD_CHNUM][AD_SAMPLE][AD_BYTES]; // AD | |
35 | +} HighSampleRecType; | |
36 | + | |
37 | +#define HIGH_WRITE_LEN szieof(HighSampleRecType) | |
38 | +#endif | |
39 | + | |
40 | +#define HIGH_WRITE_LEN (9 + AD_CHNUM*AD_SAMPLE*AD_BYTES) // 仮で50Hz 記録周波数で変わるので要変更!!!!!!!!!!!!!! | |
41 | + | |
42 | + | |
43 | +int sec_file_open(FILE **fp, AdData *D); | |
44 | +int sec_file_out(FILE *fp, char *out, int len); | |
45 | +int sec_file_close(FILE *fp); | |
46 | +int sec_make_rec_data(AdData *ad, char *buf); | |
47 | + | |
48 | +int high_file_open(FILE **fp, AdData *D); | |
49 | +int high_file_out(FILE *fp, char *out, int len); | |
50 | +int high_file_close(FILE *fp); | |
51 | +int high_make_rec_data(AdData *ad, char *buf); | |
52 | + | |
53 | +#endif |
@@ -0,0 +1,200 @@ | ||
1 | +#include <pthread.h> | |
2 | +#include <semaphore.h> | |
3 | + | |
4 | + | |
5 | +#include "ring.h" | |
6 | +#include "ad_ring.h" | |
7 | +#include "mes_print.h" | |
8 | + | |
9 | +// Ring Buffer読み込みポインタ個数 | |
10 | +#define AD_RING_READ_NUM 2 | |
11 | +// Ring Buffer読み込みポインター 1sec記録用 | |
12 | +#define AD_RING_READ_PTR1 0 | |
13 | +// Ring Buffer読み込みポインター 1min記録用 | |
14 | +#define AD_RING_READ_PTR2 1 | |
15 | + | |
16 | +static AdData ad_ring_buf[AD_RING_NUM]; | |
17 | + | |
18 | +// ミューテックス | |
19 | +static pthread_mutex_t mutex_ad_ring = PTHREAD_MUTEX_INITIALIZER; | |
20 | + | |
21 | +// Ring buffer | |
22 | +static RING_T *ring; | |
23 | + | |
24 | +int ad_ring_init(void) | |
25 | +{ | |
26 | +pthread_mutex_lock(&mutex_ad_ring); | |
27 | + ring = ring_create(AD_RING_READ_NUM); | |
28 | + if (ring == NULL) { | |
29 | + PERRF("ERROR ring_create() == NULL\n"); | |
30 | +pthread_mutex_unlock(&mutex_ad_ring); | |
31 | + return -1; | |
32 | + } | |
33 | + ring_init(ring, AD_RING_NUM); | |
34 | +pthread_mutex_unlock(&mutex_ad_ring); | |
35 | + return 0; | |
36 | +} | |
37 | +void ad_ring_clear_sec(void) | |
38 | +{ | |
39 | + ring_clear(ring, AD_RING_READ_PTR1); | |
40 | +} | |
41 | +void ad_ring_clear_high(void) | |
42 | +{ | |
43 | + ring_clear(ring, AD_RING_READ_PTR2); | |
44 | +} | |
45 | +void ad_ring_clear_latest(void) | |
46 | +{ | |
47 | + ring_latest_set(ring, -1); | |
48 | +} | |
49 | + | |
50 | +// 読み出し位置 1secデータ記録で使用 | |
51 | +int ad_ring_read_get_sec(void) | |
52 | +{ | |
53 | + return ring_read_get(ring, AD_RING_READ_PTR1); | |
54 | +} | |
55 | +void ad_ring_read_set_sec(int i) | |
56 | +{ | |
57 | + ring_read_set(ring, AD_RING_READ_PTR1, i); | |
58 | +} | |
59 | +void ad_ring_read_plus_sec(void) | |
60 | +{ | |
61 | + ring_read_plus(ring, AD_RING_READ_PTR1); | |
62 | +} | |
63 | +// 読み出し位置 高速データ記録で使用 | |
64 | +int ad_ring_read_get_high(void) | |
65 | +{ | |
66 | + return ring_read_get(ring, AD_RING_READ_PTR2); | |
67 | +} | |
68 | +void ad_ring_read_set_high(int i) | |
69 | +{ | |
70 | + ring_read_set(ring, AD_RING_READ_PTR2, i); | |
71 | +} | |
72 | +void ad_ring_read_plus_high(void) | |
73 | +{ | |
74 | + ring_read_plus(ring, AD_RING_READ_PTR2); | |
75 | +} | |
76 | + | |
77 | +// 書き込み位置 AD受信で使用 | |
78 | +int ad_ring_write_get(void) | |
79 | +{ | |
80 | + return ring_write_get(ring); | |
81 | +} | |
82 | +void ad_ring_write_plus(void) | |
83 | +{ | |
84 | + ring_write_plus(ring); | |
85 | +} | |
86 | +// 読み込んでいないデータ数 | |
87 | +int ad_ring_num_get_sec(void) | |
88 | +{ | |
89 | + return ring_num_get(ring, AD_RING_READ_PTR1); | |
90 | +} | |
91 | +// 読み込んでいないデータ数 | |
92 | +int ad_ring_num_get_high(void) | |
93 | +{ | |
94 | + return ring_num_get(ring, AD_RING_READ_PTR2); | |
95 | +} | |
96 | +// 最新データ位置 表示 | |
97 | +int ad_ring_latest_get(void) | |
98 | +{ | |
99 | + return ring_latest_get(ring); | |
100 | +} | |
101 | +void ad_ring_latest_set(int i) | |
102 | +{ | |
103 | + ring_latest_set(ring, i); | |
104 | +} | |
105 | +// データ取得 | |
106 | +AdData* ad_ring_get(int ptr) | |
107 | +{ | |
108 | + AdData* p; | |
109 | +pthread_mutex_lock(&mutex_ad_ring); | |
110 | + p = &ad_ring_buf[ptr]; | |
111 | +pthread_mutex_unlock(&mutex_ad_ring); | |
112 | + return p; | |
113 | +} | |
114 | +/* | |
115 | + バッファにデータコピー | |
116 | +*/ | |
117 | +void ad_ring_set(AdData *data) | |
118 | +{ | |
119 | + int i; | |
120 | + | |
121 | +pthread_mutex_lock(&mutex_ad_ring); | |
122 | + i = ring_write_get(ring); | |
123 | + ad_ring_buf[i] = *data; | |
124 | + // 最新データ位置セット | |
125 | + ring_latest_set(ring, i); | |
126 | +pthread_mutex_unlock(&mutex_ad_ring); | |
127 | +} | |
128 | + | |
129 | +/* | |
130 | + パケットバッファフル? | |
131 | + 1=Full | |
132 | + 0=not Full | |
133 | +*/ | |
134 | +int ad_ring_is_full(void) | |
135 | +{ | |
136 | + return ring_is_full(ring, AD_RING_READ_PTR1); | |
137 | +} | |
138 | + | |
139 | + | |
140 | +/**** CUnit test | |
141 | +*/ | |
142 | +#ifdef CUNIT | |
143 | +static void test_ad_ring(void) | |
144 | +{ | |
145 | + ad_ring_init(); | |
146 | + | |
147 | + // CLEAR | |
148 | + ad_ring_clear_sec(); | |
149 | + CU_ASSERT(ad_ring_read_get_sec() == 0); | |
150 | + ad_ring_clear_high(); | |
151 | + CU_ASSERT(ad_ring_read_get_high() == 0); | |
152 | + ad_ring_clear_latest(); | |
153 | + CU_ASSERT(ad_ring_latest_get() == -1); | |
154 | + | |
155 | + // PLUS | |
156 | + ad_ring_read_plus_sec(); | |
157 | + CU_ASSERT(ad_ring_read_get_sec() == 1); | |
158 | + ad_ring_read_plus_high(); | |
159 | + CU_ASSERT(ad_ring_read_get_high() == 1); | |
160 | + ad_ring_write_plus(); | |
161 | + CU_ASSERT(ad_ring_write_get() == 1); | |
162 | + | |
163 | + // 境界値でPLUS | |
164 | + ad_ring_read_set_sec(AD_RING_NUM - 1); | |
165 | + ad_ring_read_plus_sec(); | |
166 | + CU_ASSERT(ad_ring_read_get_sec() == 0); | |
167 | + | |
168 | + ad_ring_read_set_high(AD_RING_NUM - 1); | |
169 | + ad_ring_read_plus_high(); | |
170 | + CU_ASSERT(ad_ring_read_get_high() == 0); | |
171 | + | |
172 | + ring->write = AD_RING_NUM - 1; | |
173 | + ad_ring_write_plus(); | |
174 | + CU_ASSERT(ad_ring_write_get() == 0); | |
175 | + | |
176 | + // | |
177 | + ring->write = 1; | |
178 | + ring->read[AD_RING_READ_PTR1] = 0; | |
179 | + CU_ASSERT(ad_ring_num_get_sec() == 1); | |
180 | + | |
181 | + ring->write = 0; | |
182 | + ring->read[AD_RING_READ_PTR1] = AD_RING_NUM - 1; | |
183 | + CU_ASSERT(ad_ring_num_get_sec() == 1); | |
184 | + | |
185 | + ring->write = 1; | |
186 | + ring->read[AD_RING_READ_PTR2] = 0; | |
187 | + CU_ASSERT(ad_ring_num_get_high() == 1); | |
188 | + | |
189 | + ring->write = 0; | |
190 | + ring->read[AD_RING_READ_PTR2] = AD_RING_NUM - 1; | |
191 | + CU_ASSERT(ad_ring_num_get_high() == 1); | |
192 | + | |
193 | +} | |
194 | + | |
195 | +void ad_ring_test(CU_pSuite test_suite) | |
196 | +{ | |
197 | + CU_add_test(test_suite, "test_ad_ring", test_ad_ring); | |
198 | + | |
199 | +} | |
200 | +#endif |
@@ -0,0 +1,70 @@ | ||
1 | +#if !defined(__AVG_RING_H__) | |
2 | +#define __AVG_RING_H__ | |
3 | + | |
4 | +#include <time.h> | |
5 | + | |
6 | +// リングバッファサイズ 個数 | |
7 | +#define AD_RING_NUM (60 * 5) | |
8 | + | |
9 | +#define AD_CHNUM 6 // AD CH数 | |
10 | +#define AD_SAMPLE 50 // AD ICの出力レート [Hz] | |
11 | +#define AD_BYTES 3 // AD 1sample dataのバイト数 | |
12 | + | |
13 | +// NAV-TIMEUTCパケットのデータ格納 | |
14 | +typedef struct { | |
15 | + unsigned long tow; // ms GPS Millisecond Time of Week | |
16 | + unsigned long tacc; // ns Time Accuracy Estimate | |
17 | + long nano; // ns Nanoseconds of second, range -1e9 .. 1e9 (UTC) | |
18 | + unsigned int year; // UTC | |
19 | + unsigned char month; // | |
20 | + unsigned char day; | |
21 | + unsigned char hour; | |
22 | + unsigned char min; | |
23 | + unsigned char sec; | |
24 | + unsigned char valid; // Validity Flags | |
25 | + // bit0 validTOW 1 = Valid Time of Week | |
26 | + // bit1 validWKN 1 = Valid Week Number | |
27 | + // bit2 validUTC 1 = Valid UTC (Leap Seconds already known) | |
28 | +} UbloxNavTimeUtc; | |
29 | + | |
30 | +// リングバッファのデータタイプ | |
31 | +typedef struct { | |
32 | + UbloxNavTimeUtc gps; // GPSタイムスタンプ SPIで受信 | |
33 | + struct tm t; // タイムスタンプ struct tmの月は(0〜11)なので注意 年は1900からのオフセット | |
34 | + long data1sec[AD_CHNUM]; // 1sec平均値 SPIで受信 | |
35 | + long data[AD_CHNUM][AD_SAMPLE]; // AD_SAMPLE[Hz]の生データ SPIで受信 | |
36 | + long avg[AD_CHNUM][AD_SAMPLE]; // 平均後データ | |
37 | +} AdData; | |
38 | + | |
39 | + | |
40 | + | |
41 | +int ad_ring_init(void); | |
42 | + | |
43 | +void ad_ring_clear_sec(void); | |
44 | +void ad_ring_clear_high(void); | |
45 | +void ad_ring_clear_latest(void); | |
46 | + | |
47 | +int ad_ring_read_get_sec(void); | |
48 | +void ad_ring_read_set_sec(int i); | |
49 | +void ad_ring_read_plus_sec(void); | |
50 | +int ad_ring_num_get_sec(void); | |
51 | + | |
52 | +int ad_ring_read_get_high(void); | |
53 | +void ad_ring_read_set_high(int i); | |
54 | +void ad_ring_read_plus_high(void); | |
55 | +int ad_ring_num_get_high(void); | |
56 | + | |
57 | +int ad_ring_write_get(void); | |
58 | +void ad_ring_write_plus(void); | |
59 | +int ad_ring_latest_get(void); | |
60 | +void ad_ring_latest_set(int i); | |
61 | +AdData* ad_ring_get(int ptr); | |
62 | +void ad_ring_set(AdData *data); | |
63 | +int ad_ring_full(void); | |
64 | + | |
65 | +#ifdef CUNIT | |
66 | + #include <CUnit/CUnit.h> | |
67 | + void ad_ring_test(CU_pSuite test_suite); | |
68 | +#endif | |
69 | + | |
70 | +#endif |
@@ -0,0 +1,154 @@ | ||
1 | +#include <pthread.h> | |
2 | +#include <semaphore.h> | |
3 | +#include <string.h> | |
4 | +#include <syslog.h> | |
5 | +#include <stdio.h> | |
6 | + | |
7 | +#include "conf.h" | |
8 | +#include "debug_print.h" | |
9 | + | |
10 | +// | |
11 | +/**** Station ID *************************************************** | |
12 | +*/ | |
13 | +#define SID_MAX 16 | |
14 | +static char gsid[SID_MAX + 1]; | |
15 | + | |
16 | +// ミューテックス | |
17 | +static pthread_mutex_t mutex_sid = PTHREAD_MUTEX_INITIALIZER; | |
18 | + | |
19 | +void sid_set(char *s) | |
20 | +{ | |
21 | +pthread_mutex_lock(&mutex_sid); | |
22 | + strncpy(gsid, s, SID_MAX); | |
23 | + gsid[SID_MAX] = 0; | |
24 | +pthread_mutex_unlock(&mutex_sid); | |
25 | +} | |
26 | +void sid_get(char *s) | |
27 | +{ | |
28 | +pthread_mutex_lock(&mutex_sid); | |
29 | + strncpy(s, gsid, SID_MAX); | |
30 | + s[SID_MAX] = 0; | |
31 | +pthread_mutex_unlock(&mutex_sid); | |
32 | +} | |
33 | +char *sid_getp(void) | |
34 | +{ | |
35 | + return gsid; | |
36 | +} | |
37 | + | |
38 | +// | |
39 | +/**** 設定ファイル ******************************************* | |
40 | +*/ | |
41 | +/* | |
42 | + 文字列の前から空白を取り除く | |
43 | +*/ | |
44 | +static void trims_space(char *name) | |
45 | +{ | |
46 | + char c; | |
47 | + char *name0; | |
48 | + int len; | |
49 | + | |
50 | + name0 = name; | |
51 | + len = strlen(name); | |
52 | + | |
53 | + // 最初の非空白文字までポインタ移動 | |
54 | + while (*name) { | |
55 | + c = *name; | |
56 | + if (c != ' ') break; | |
57 | + name++; | |
58 | + len--; | |
59 | + } | |
60 | + if (len < 0) return; | |
61 | + // 移動 | |
62 | + if (name0 != name) memmove(name0, name, len); | |
63 | + // 末尾に0入れる | |
64 | + name0[len] = 0; | |
65 | +} | |
66 | +/* | |
67 | + 文字列の後ろから空白を取り除く | |
68 | +*/ | |
69 | +static void trime_space(char *name) | |
70 | +{ | |
71 | + char c; | |
72 | + int len, i; | |
73 | + | |
74 | + // 文字列末尾 | |
75 | + len = strlen(name); | |
76 | + name += (len - 1); | |
77 | + // 最初の非空白文字までポインタ移動 | |
78 | + for(i = len - 1; i >= 0; i--) { | |
79 | + c = *name; | |
80 | + if (c != ' ') break; | |
81 | + name--; | |
82 | + } | |
83 | + // 末尾に0入れる | |
84 | + *(name + 1) = 0; | |
85 | +} | |
86 | +/* | |
87 | + 文字列の前後から空白を取り除く | |
88 | +*/ | |
89 | +static void trim_space(char *name) | |
90 | +{ | |
91 | + if (name == NULL) return; | |
92 | + trims_space(name); | |
93 | + trime_space(name); | |
94 | +} | |
95 | +/* | |
96 | + 文字列の末尾からCR LFを除く | |
97 | +*/ | |
98 | +static void trim_crlf(char *name) | |
99 | +{ | |
100 | + int i; | |
101 | + int len; | |
102 | + char *src, *dst; | |
103 | + | |
104 | + if (name == NULL) return; | |
105 | + len = strlen(name); | |
106 | + src = name; | |
107 | + dst = name; | |
108 | + for(i = 0; i < len; i++) { | |
109 | + if (*src != 0x0d && *src != 0x0a) { | |
110 | + *dst = *src; | |
111 | + dst++; | |
112 | + } | |
113 | + src++; | |
114 | + } | |
115 | + *dst = 0; | |
116 | +} | |
117 | + | |
118 | +/* | |
119 | + 読み込み | |
120 | + | |
121 | +return | |
122 | + -1=ERR | |
123 | + 0=OK | |
124 | +*/ | |
125 | +int conf_read(void) | |
126 | +{ | |
127 | + FILE *fp; | |
128 | + char buf[256]; | |
129 | + char buf2[256]; | |
130 | + | |
131 | + fp = fopen(CONF_FILE, "rt"); | |
132 | + if (fp == NULL) { | |
133 | + syslog(LOG_ERR, "conf_read(): conf file not found. %s", CONF_FILE); | |
134 | + return -1; | |
135 | + } | |
136 | + | |
137 | + syslog(LOG_INFO, "conf_read():"); | |
138 | + while(fgets(buf, sizeof(buf), fp)) { | |
139 | + // CR LF除く | |
140 | + trim_crlf(buf); | |
141 | + trim_space(buf); | |
142 | + PDEBUG(buf); | |
143 | + PDEBUG("\n"); | |
144 | + // Station ID | |
145 | + if (sscanf(buf, "sid = %s", buf2) == 1) { | |
146 | + sid_set(buf2); | |
147 | + syslog(LOG_INFO, "sid=%s", sid_getp()); | |
148 | + } | |
149 | + } | |
150 | + fclose(fp); | |
151 | + return 0; | |
152 | +} | |
153 | + | |
154 | + |
@@ -0,0 +1,13 @@ | ||
1 | +#if !defined(__CONF_H__) | |
2 | +#define __CONF_H__ | |
3 | + | |
4 | +// 設定ファイル | |
5 | +#define CONF_FILE "/etc/meas.conf" | |
6 | + | |
7 | +void sid_set(char *s); | |
8 | +void sid_get(char *s); | |
9 | +char *sid_getp(void); | |
10 | +int conf_read(void); | |
11 | + | |
12 | + | |
13 | +#endif |
@@ -0,0 +1,35 @@ | ||
1 | +CC = gcc | |
2 | + | |
3 | +# -DDUMMY ダミーデータで動作する | |
4 | +all: CFLAGS = -DDUMMY | |
5 | +cunit: CFLAGS = -DCUNIT | |
6 | + | |
7 | +LDFLAGS = | |
8 | +LIBS = -lm -lpthread | |
9 | +TEST_LIBS = $(LIBS) -lcunit | |
10 | + | |
11 | +SRCS0 = thread_rcv.c spi.c ring.c ad_ring.c rec.c sts.c ad_file.c | |
12 | +SRCS = scilog.c $(SRCS0) | |
13 | +TEST_SRCS = test.c $(SRCS0) | |
14 | + | |
15 | +HDRS = mes_print.h debug_print.h my_thread.h spi.h ring.h ad_ring.h rec.h sts.h ad_file.h | |
16 | + | |
17 | +OBJS = $(SRCS:.c=.o) | |
18 | +TEST_OBJS = $(TEST_SRCS:.c=.o) | |
19 | + | |
20 | +PROGRAM = scilog | |
21 | +TEST_PROG = test | |
22 | + | |
23 | +all: $(PROGRAM) | |
24 | + | |
25 | +cunit: $(TEST_PROG) | |
26 | + | |
27 | +$(PROGRAM): $(OBJS) $(HDRS) | |
28 | + $(CC) $(OBJS) $(LDFLAGS) $(LIBS) -o $(PROGRAM) | |
29 | + | |
30 | +$(TEST_PROG): $(TEST_OBJS) $(HDRS) | |
31 | + $(CC) $(TEST_OBJS) $(LDFLAGS) $(TEST_LIBS) -o $(TEST_PROG) | |
32 | + | |
33 | +clean:; rm -f *.o *~ $(PROGRAM) $(TEST_PROG) | |
34 | + | |
35 | +### End of Makefile |
@@ -3,4 +3,9 @@ | ||
3 | 3 | |
4 | 4 | void* thread_rcv(void* pParam); |
5 | 5 | |
6 | +#ifdef CUNIT | |
7 | + #include <CUnit/CUnit.h> | |
8 | + void thread_rcv_test(CU_pSuite test_suite); | |
9 | +#endif | |
10 | + | |
6 | 11 | #endif |
@@ -0,0 +1,142 @@ | ||
1 | +/* | |
2 | + Ring Buffer用基本機能 | |
3 | + write位置 | |
4 | + read位置 | |
5 | +*/ | |
6 | +#include <stdlib.h> | |
7 | +#include <pthread.h> | |
8 | +#include <semaphore.h> | |
9 | + | |
10 | +#include "ring.h" | |
11 | + | |
12 | +#define READ_NUM_MAX 256 | |
13 | +// ミューテックス | |
14 | +static pthread_mutex_t mutex_ring = PTHREAD_MUTEX_INITIALIZER; | |
15 | + | |
16 | +/* | |
17 | + int read_num | |
18 | + 読み込みポインタの個数 | |
19 | +*/ | |
20 | +RING_T* ring_create(int read_num) | |
21 | +{ | |
22 | + RING_T *t; | |
23 | + if (read_num <= 0) return NULL; | |
24 | + if (read_num > READ_NUM_MAX) return NULL; | |
25 | + | |
26 | + t = malloc(sizeof(RING_T)); | |
27 | + if (t != NULL) { | |
28 | + // readポインタ確保 | |
29 | + t->read = malloc(sizeof(int) * read_num); | |
30 | + if (t->read == NULL) { | |
31 | + free(t); | |
32 | + return NULL; | |
33 | + } | |
34 | + t->read_num = read_num; | |
35 | + } | |
36 | + return t; | |
37 | +} | |
38 | +void ring_destroy(RING_T *t) | |
39 | +{ | |
40 | + free(t->read); | |
41 | + free(t); | |
42 | +} | |
43 | +/* | |
44 | + int num: バッファの個数 | |
45 | +*/ | |
46 | +void ring_init(RING_T *t, int num) | |
47 | +{ | |
48 | + int i; | |
49 | + | |
50 | +pthread_mutex_lock(&mutex_ring); | |
51 | + t->write = 0; | |
52 | + for(i = 0; i < t->read_num; i++) { | |
53 | + t->read[i] = 0; | |
54 | + } | |
55 | + t->latest = -1; | |
56 | + t->num = num; | |
57 | +pthread_mutex_unlock(&mutex_ring); | |
58 | +} | |
59 | +void ring_clear(RING_T *t, int no) | |
60 | +{ | |
61 | + ring_read_set(t, no, ring_write_get(t)); | |
62 | +} | |
63 | +/* | |
64 | + 読み出し位置 | |
65 | + int no | |
66 | + readポインタ番号 | |
67 | +*/ | |
68 | +int ring_read_get(RING_T *t, int no) | |
69 | +{ | |
70 | + int i; | |
71 | +pthread_mutex_lock(&mutex_ring); | |
72 | + i = t->read[no]; | |
73 | +pthread_mutex_unlock(&mutex_ring); | |
74 | + return i; | |
75 | +} | |
76 | +void ring_read_set(RING_T *t, int no, int i) | |
77 | +{ | |
78 | +pthread_mutex_lock(&mutex_ring); | |
79 | + t->read[no] = i; | |
80 | +pthread_mutex_unlock(&mutex_ring); | |
81 | +} | |
82 | +void ring_read_plus(RING_T *t, int no) | |
83 | +{ | |
84 | +pthread_mutex_lock(&mutex_ring); | |
85 | + t->read[no]++; | |
86 | + if (t->read[no] >= t->num) t->read[no] = 0; | |
87 | +pthread_mutex_unlock(&mutex_ring); | |
88 | +} | |
89 | + | |
90 | +// 書き込み位置 | |
91 | +int ring_write_get(RING_T *t) | |
92 | +{ | |
93 | + int i; | |
94 | +pthread_mutex_lock(&mutex_ring); | |
95 | + i = t->write; | |
96 | +pthread_mutex_unlock(&mutex_ring); | |
97 | + return i; | |
98 | +} | |
99 | +void ring_write_plus(RING_T *t) | |
100 | +{ | |
101 | +pthread_mutex_lock(&mutex_ring); | |
102 | + t->write++; | |
103 | + if (t->write >= t->num) t->write = 0; | |
104 | +pthread_mutex_unlock(&mutex_ring); | |
105 | +} | |
106 | +// 読み込んでいないデータ数 | |
107 | +int ring_num_get(RING_T *t, int no) | |
108 | +{ | |
109 | + int i; | |
110 | + | |
111 | +pthread_mutex_lock(&mutex_ring); | |
112 | + i = t->write - t->read[no]; | |
113 | + if (i < 0) i += t->num; | |
114 | +pthread_mutex_unlock(&mutex_ring); | |
115 | + return i; | |
116 | +} | |
117 | +// 最新データ位置 | |
118 | +int ring_latest_get(RING_T *t) | |
119 | +{ | |
120 | + int i; | |
121 | +pthread_mutex_lock(&mutex_ring); | |
122 | + i = t->latest; | |
123 | +pthread_mutex_unlock(&mutex_ring); | |
124 | + return i; | |
125 | +} | |
126 | +void ring_latest_set(RING_T *t, int i) | |
127 | +{ | |
128 | +pthread_mutex_lock(&mutex_ring); | |
129 | + t->latest = i; | |
130 | +pthread_mutex_unlock(&mutex_ring); | |
131 | +} | |
132 | + | |
133 | +/* | |
134 | + パケットバッファフル? | |
135 | + 1=Full | |
136 | + 0=not Full | |
137 | +*/ | |
138 | +int ring_is_full(RING_T *t, int no) | |
139 | +{ | |
140 | + if (ring_num_get(t, no) >= t->num - 1) return 1; | |
141 | + return 0; | |
142 | +} |
@@ -0,0 +1,33 @@ | ||
1 | + | |
2 | + | |
3 | +#if !defined(__RING_H__) | |
4 | +#define __RING_H__ | |
5 | + | |
6 | +typedef struct { | |
7 | + // 読み出し位置 複数設定できる | |
8 | + int *read; | |
9 | + // 書き込み位置 | |
10 | + int write; | |
11 | + // 最新データ位置 | |
12 | + int latest; | |
13 | + // バッファ個数 | |
14 | + int num; | |
15 | + // readポインタ個数 | |
16 | + int read_num; | |
17 | +} RING_T; | |
18 | + | |
19 | +RING_T* ring_create(int read_num); | |
20 | +void ring_destroy(RING_T *t); | |
21 | +void ring_init(RING_T *t, int num); | |
22 | +void ring_clear(RING_T *t, int no); | |
23 | +int ring_read_get(RING_T *t, int no); | |
24 | +void ring_read_set(RING_T *t, int no, int i); | |
25 | +void ring_read_plus(RING_T *t, int no); | |
26 | +int ring_write_get(RING_T *t); | |
27 | +void ring_write_plus(RING_T *t); | |
28 | +int ring_num_get(RING_T *t, int no); | |
29 | +int ring_latest_get(RING_T *t); | |
30 | +void ring_latest_set(RING_T *t, int i); | |
31 | +int ring_is_full(RING_T *t, int no); | |
32 | + | |
33 | +#endif |
@@ -22,6 +22,11 @@ | ||
22 | 22 | |
23 | 23 | #include "my_thread.h" |
24 | 24 | #include "spi.h" |
25 | +#include "ad_ring.h" | |
26 | +#include "sts.h" | |
27 | +#include "thread_rec.h" | |
28 | +#include "conf.h" | |
29 | +#include "ad_file.h" | |
25 | 30 | |
26 | 31 | // debug_print.h内で#define DEBUG_PRINTしているので |
27 | 32 | // リリース時は、debug_print.hでコメントする |
@@ -39,7 +44,7 @@ | ||
39 | 44 | |
40 | 45 | /**** 設定デフォルト値 |
41 | 46 | */ |
42 | -//#define SID_DEF "DEF" | |
47 | +#define SID_DEF "DEF" | |
43 | 48 | |
44 | 49 | |
45 | 50 | // |
@@ -83,11 +88,18 @@ int main (int argc, char *argv[]) | ||
83 | 88 | // lcd_print("sciLogger"); |
84 | 89 | // lcd_pos(0, 3); |
85 | 90 | |
91 | + ad_ring_init(); | |
92 | + sts_init(); | |
93 | + | |
94 | +//printf("%d\n", sizeof(UbloxNavTimeUtcRecType)); | |
95 | +//printf("%d\n", sizeof(HighSampleRecType)); | |
96 | +//goto END; | |
97 | + | |
86 | 98 | // デフォルト設定 |
87 | -// sid_set(SID_DEF); | |
99 | + sid_set(SID_DEF); | |
88 | 100 | // 設定ファイル読み込み |
89 | -// conf_read(); | |
90 | -// PDEBUG("sid=%s\n", sid_getp()); | |
101 | + conf_read(); | |
102 | + PDEBUG("sid=%s\n", sid_getp()); | |
91 | 103 | // lcd_print("*"); |
92 | 104 | |
93 | 105 | PDEBUG("sciLogger %s START\n", VERSION); |
@@ -116,9 +128,7 @@ int main (int argc, char *argv[]) | ||
116 | 128 | // |
117 | 129 | /**** メインループ 記録 ************************ |
118 | 130 | */ |
119 | - while(1) { | |
120 | - sleep(1); | |
121 | - } // メインループ終わり | |
131 | + thread_rec(NULL); | |
122 | 132 | END: |
123 | 133 | sig_handler(0); |
124 | 134 |
@@ -18,36 +18,17 @@ | ||
18 | 18 | // SPIで実際に受信したデータ長を取得 |
19 | 19 | #define CMD_RECEIVED_LEN_GET 20 |
20 | 20 | |
21 | -// SPIで受信するデータ長 固定長 | |
21 | +// SPIで受信するデータ長 固定長 $含む | |
22 | 22 | #define SPI_DATA_LEN 945 |
23 | 23 | // SPI受信データの先頭文字 |
24 | 24 | #define SPI_HEAD_CHAR '$' |
25 | 25 | |
26 | -// NAV-TIMEUTCパケットのデータ格納 | |
27 | -typedef struct { | |
28 | - unsigned long tow; // 0 ms GPS Millisecond Time of Week | |
29 | - unsigned long tacc; // 4 ns Time Accuracy Estimate | |
30 | - long nano; // 8 ns Nanoseconds of second, range -1e9 .. 1e9 (UTC) | |
31 | - unsigned int year; // 12 UTC | |
32 | - unsigned char month; // 16 | |
33 | - unsigned char day; | |
34 | - unsigned char hour; | |
35 | - unsigned char min; | |
36 | - unsigned char sec; | |
37 | - unsigned char valid; // Validity Flags | |
38 | - // bit0 validTOW 1 = Valid Time of Week | |
39 | - // bit1 validWKN 1 = Valid Week Number | |
40 | - // bit2 validUTC 1 = Valid UTC (Leap Seconds already known) | |
41 | -} UbloxNavTimeUtc; | |
26 | +// SPI受信データの先頭からのオフセット | |
27 | +#define SPI_OFS_GPS (18-17) | |
28 | +#define SPI_OFS_1SEC (38-17) | |
29 | +#define SPI_OFS_DATA (62-17) | |
42 | 30 | |
43 | -#define AD_CHNUM 6 | |
44 | -#define AD_SAMPLE 50 // AD ICの出力レート [Hz] | |
45 | 31 | |
46 | -typedef struct { | |
47 | - UbloxNavTimeUtc t; // タイムスタンプ | |
48 | - long data1sec[AD_CHNUM]; // 1sec平均値 | |
49 | - long data[AD_CHNUM][AD_SAMPLE]; // AD_SAMPLE[Hz]のデータ | |
50 | -} ADbufType; | |
51 | 32 | |
52 | 33 | |
53 | 34 | int spi_get_fd(void); |
@@ -0,0 +1,40 @@ | ||
1 | +#include "sts.h" | |
2 | + | |
3 | +/* | |
4 | + ステータス | |
5 | +*/ | |
6 | +static int sts; | |
7 | + | |
8 | +void sts_init(void) | |
9 | +{ | |
10 | + sts = STS_TIME_FIX; | |
11 | +} | |
12 | +/* | |
13 | + ステータス返す | |
14 | +*/ | |
15 | +int sts_get(void) | |
16 | +{ | |
17 | + return sts; | |
18 | +} | |
19 | + | |
20 | +// LCD表示用 | |
21 | +char *sts_get_str(void) | |
22 | +{ | |
23 | + switch(sts) { | |
24 | + case STS_TIME_FIX: | |
25 | + return "WAIT TIME FIX"; | |
26 | + case STS_REC_INIT: | |
27 | + return "REC INIT "; | |
28 | + case STS_REC: | |
29 | + return "RECORDING "; | |
30 | + case STS_REC_OFF: | |
31 | + return "RECORD OFF "; | |
32 | + case STS_FILE_ERR: | |
33 | + return "WRITE ERROR "; | |
34 | + } | |
35 | + return "UNKNOWN "; | |
36 | +} | |
37 | +void sts_set(int sts0) | |
38 | +{ | |
39 | + sts = sts0; | |
40 | +} |
@@ -0,0 +1,17 @@ | ||
1 | +#if !defined(__STS_H__) | |
2 | +#define __STS_H__ | |
3 | + | |
4 | +#define STS_TIME_FIX 1 | |
5 | +#define STS_REC_INIT 3 | |
6 | +#define STS_REC 4 | |
7 | +#define STS_REC_OFF 5 | |
8 | +#define STS_FILE_ERR 6 | |
9 | + | |
10 | + | |
11 | +void sts_init(void); | |
12 | +int sts_get(void); | |
13 | +char *sts_get_str(void); | |
14 | +void sts_set(int sts0); | |
15 | + | |
16 | +#endif | |
17 | + |
@@ -0,0 +1,23 @@ | ||
1 | + | |
2 | +#include <stdio.h> | |
3 | +#include <CUnit/CUnit.h> | |
4 | +#include <CUnit/Console.h> | |
5 | + | |
6 | +#include "my_thread.h" | |
7 | +#include "spi.h" | |
8 | +#include "ad_ring.h" | |
9 | + | |
10 | +int main (int argc, char *argv[]) | |
11 | +{ | |
12 | + CU_pSuite test_suite; | |
13 | + CU_initialize_registry(); | |
14 | + test_suite = CU_add_suite("scilog", NULL, NULL); | |
15 | + | |
16 | + thread_rcv_test(test_suite); | |
17 | + ad_ring_test(test_suite); | |
18 | + | |
19 | + CU_console_run_tests(); | |
20 | + | |
21 | + CU_cleanup_registry(); | |
22 | + | |
23 | +} |
@@ -5,18 +5,38 @@ | ||
5 | 5 | #include <fcntl.h> |
6 | 6 | #include <syslog.h> |
7 | 7 | #include <sys/types.h> |
8 | +#include <string.h> | |
8 | 9 | |
9 | 10 | #include "spi.h" |
11 | +#include "ad_ring.h" | |
10 | 12 | |
11 | - | |
12 | -static int decode(char *buf, ADbufType *ad) | |
13 | +/* | |
14 | + Little Endian | |
15 | + 3byte -> signed long(4byte) | |
16 | +*/ | |
17 | +static long b3_to_long32(unsigned char *ptr) | |
18 | +{ | |
19 | + char buf[4]; | |
20 | + | |
21 | + buf[0] = *ptr++; | |
22 | + buf[1] = *ptr++; | |
23 | + buf[2] = *ptr; | |
24 | + if (*ptr & 0x80) { | |
25 | + buf[3] = 0xFF; | |
26 | + } else { | |
27 | + buf[3] = 0; | |
28 | + } | |
29 | + return *((long*)buf); | |
30 | +} | |
31 | +static int decode(char *buf, AdData *ad) | |
13 | 32 | { |
14 | 33 | UbloxNavTimeUtc *gps; |
15 | 34 | u_int8_t *ptr; |
16 | 35 | int ch; |
36 | + int i; | |
17 | 37 | |
18 | 38 | ptr = (u_int8_t*)buf; |
19 | - gps = &(ad->t); | |
39 | + gps = &(ad->gps); | |
20 | 40 | |
21 | 41 | if (*ptr++ != SPI_HEAD_CHAR) return -1; |
22 | 42 | // GPS |
@@ -36,18 +56,42 @@ static int decode(char *buf, ADbufType *ad) | ||
36 | 56 | ptr += 4; |
37 | 57 | } |
38 | 58 | // 50Hz data |
59 | + for(ch = 0; ch < AD_CHNUM; ch++) { | |
60 | + for(i = 0; i < AD_SAMPLE; i++) { | |
61 | + ad->data[ch][i] = b3_to_long32(ptr); | |
62 | + ptr += 3; | |
63 | + } | |
64 | + } | |
65 | + // Checksum | |
39 | 66 | |
67 | + // gps->struct tm | |
68 | + ad->t.tm_year = gps->year - 1900; | |
69 | + ad->t.tm_mon = gps->month - 1; // struct tmの月は(0〜11)なので注意 | |
70 | + ad->t.tm_mday = gps->day; | |
71 | + ad->t.tm_hour = gps->hour; | |
72 | + ad->t.tm_min = gps->min; | |
73 | + ad->t.tm_sec = gps->sec; | |
74 | + | |
40 | 75 | return 0; |
41 | 76 | } |
77 | +/* | |
78 | + int freq | |
79 | + 平均化後の周波数 Hz | |
80 | +*/ | |
81 | +static void do_avg(int freq, AdData *ad) | |
82 | +{ | |
83 | +// 仮コード | |
84 | + memcpy(ad->avg, ad->data, AD_CHNUM*AD_SAMPLE*AD_BYTES); | |
85 | +} | |
42 | 86 | void* thread_rcv(void* pParam) |
43 | 87 | { |
44 | 88 | while(1) { |
45 | 89 | fd_set fds; |
46 | 90 | char buf[SPI_DATA_LEN+256]; |
47 | 91 | int i; |
48 | - int ch; | |
92 | +// int ch; | |
49 | 93 | int fd_spi; |
50 | -ADbufType ad; | |
94 | + AdData ad, *ad_ptr; | |
51 | 95 | |
52 | 96 | fd_spi = spi_get_fd(); |
53 | 97 | // select の準備 |
@@ -67,7 +111,11 @@ ADbufType ad; | ||
67 | 111 | // ring_zero(); |
68 | 112 | // データ取得 |
69 | 113 | spi_rx_get(buf); |
114 | + // デコード | |
70 | 115 | decode(buf, &ad); |
116 | + // 平均 仮コード 要変更 | |
117 | + do_avg(AD_SAMPLE, &ad); | |
118 | +#if 0 | |
71 | 119 | printf("%04d/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X", |
72 | 120 | ad.t.year, ad.t.month, ad.t.day, ad.t.hour, ad.t.min, ad.t.sec, ad.t.nano, |
73 | 121 | ad.t.tow, ad.t.tacc, ad.t.valid); |
@@ -75,6 +123,22 @@ for(ch = 0; ch < AD_CHNUM; ch++) { | ||
75 | 123 | printf(",%+7ld", ad.data1sec[ch]); |
76 | 124 | } |
77 | 125 | printf("\r\n"); |
126 | +for(ch = 0; ch < AD_CHNUM; ch++) { | |
127 | + printf(",%+7ld", ad.data[ch][0]); | |
128 | +} | |
129 | +printf("\r\n"); | |
130 | +for(ch = 0; ch < AD_CHNUM; ch++) { | |
131 | + printf(",%+7ld", ad.data[ch][49]); | |
132 | +} | |
133 | +printf("\r\n"); | |
134 | +#endif | |
135 | + // ADリングバッファに書き込み | |
136 | + ad_ptr = ad_ring_get(ad_ring_write_get()); | |
137 | + *ad_ptr = ad; | |
138 | + // 最新データ位置 | |
139 | + ad_ring_latest_set(ad_ring_write_get()); | |
140 | + // 書き込み位置+1 | |
141 | + ad_ring_write_plus(); | |
78 | 142 | |
79 | 143 | } // while((i = sub_dnum_get()) > 0) { |
80 | 144 | } // if(FD_ISSET(fd_sub, &fds)) { |
@@ -82,3 +146,60 @@ printf("\r\n"); | ||
82 | 146 | return NULL; |
83 | 147 | } |
84 | 148 | |
149 | +// | |
150 | +/**** CUnit test | |
151 | +*/ | |
152 | +#ifdef CUNIT | |
153 | +#include <CUnit/CUnit.h> | |
154 | + | |
155 | +static void test_b3_to_long32(void) | |
156 | +{ | |
157 | + long l; | |
158 | + char buf[SPI_DATA_LEN+256]; | |
159 | + AdData ad; | |
160 | + int i; | |
161 | + | |
162 | + buf[0] = 0x56; | |
163 | + buf[1] = 0x34; | |
164 | + buf[2] = 0x12; | |
165 | + l = b3_to_long32(buf); | |
166 | + CU_ASSERT(l == 0x00123456); | |
167 | + | |
168 | + buf[0] = 0x56; | |
169 | + buf[1] = 0x34; | |
170 | + buf[2] = 0x82; | |
171 | + l = b3_to_long32(buf); | |
172 | + CU_ASSERT(l == (long)0xFF823456); | |
173 | + | |
174 | + buf[0] = 0xFF; | |
175 | + buf[1] = 0xFF; | |
176 | + buf[2] = 0xFF; | |
177 | + l = b3_to_long32(buf); | |
178 | + CU_ASSERT(l == -1); | |
179 | + | |
180 | + buf[0] = '$'; | |
181 | + i = SPI_OFS_DATA; | |
182 | + buf[i++] = 0x56; | |
183 | + buf[i++] = 0x34; | |
184 | + buf[i++] = 0x12; | |
185 | + decode(buf, &ad); | |
186 | + CU_ASSERT(ad.data[0][0] == 0x123456); | |
187 | + | |
188 | + buf[0] = '$'; | |
189 | + i = SPI_OFS_DATA + AD_CHNUM * AD_SAMPLE * 3; | |
190 | + i -= 3; | |
191 | + buf[i++] = 0x56; | |
192 | + buf[i++] = 0x34; | |
193 | + buf[i++] = 0x12; | |
194 | + decode(buf, &ad); | |
195 | + CU_ASSERT(ad.data[AD_CHNUM-1][AD_SAMPLE-1] == 0x123456); | |
196 | +} | |
197 | + | |
198 | +void thread_rcv_test(CU_pSuite test_suite) | |
199 | +{ | |
200 | + | |
201 | + CU_add_test(test_suite, "test_b3_to_long32", test_b3_to_long32); | |
202 | + | |
203 | +} | |
204 | + | |
205 | +#endif |
@@ -0,0 +1,251 @@ | ||
1 | + | |
2 | +#include <stdio.h> | |
3 | +#include <syslog.h> | |
4 | +#include <unistd.h> | |
5 | +#include <string.h> | |
6 | + | |
7 | +#include "ad_ring.h" | |
8 | +#include "sts.h" | |
9 | +#include "debug_print.h" | |
10 | +#include "ad_file.h" | |
11 | + | |
12 | +// 1secファイル書き込み間隔 sec | |
13 | +#define SEC_FLUSH_NUM 1 | |
14 | +//#define SEC_FLUSH_NUM 60 | |
15 | + | |
16 | +// 高速サンプルファイル書き込み間隔 sec | |
17 | +#define HIGH_FLUSH_NUM 1 | |
18 | + | |
19 | +// 日付変化検出用 | |
20 | +static struct tm high_tm; | |
21 | +static struct tm sec_tm; | |
22 | + | |
23 | +// | |
24 | +/**** 時刻校正待ち | |
25 | + パケット中の時刻が有効になるのを待つ | |
26 | + | |
27 | + Return: | |
28 | + 次の状態 | |
29 | +*/ | |
30 | +int ProcTimeFix(void) | |
31 | +{ | |
32 | + AdData *d; | |
33 | + static int latest = -1; | |
34 | + /* | |
35 | + 時刻校正終わったら、記録開始 | |
36 | + */ | |
37 | + if (latest == ad_ring_latest_get()) return STS_TIME_FIX; | |
38 | + latest = ad_ring_latest_get(); | |
39 | + if (latest >= 0) { | |
40 | + // 最新データの時刻取得 | |
41 | + d = ad_ring_get(latest); | |
42 | + // GPS Validチェック | |
43 | + if (d->gps.valid & 0x07) { | |
44 | + PDEBUG("ProcTimeFix: rec init.\n"); | |
45 | + return STS_REC_INIT; | |
46 | + } | |
47 | + } | |
48 | + return STS_TIME_FIX; | |
49 | +} | |
50 | + | |
51 | +// | |
52 | +/**** 記録初期化 | |
53 | + | |
54 | + Return: | |
55 | + 次の状態 | |
56 | +*/ | |
57 | +int ProcRecInit(void) | |
58 | +{ | |
59 | + AdData *d; | |
60 | + | |
61 | + if (ad_ring_latest_get() >= 0) { | |
62 | + // 記録開始 | |
63 | + ad_ring_clear_sec(); | |
64 | + ad_ring_clear_high(); | |
65 | + | |
66 | + // 最新データの時刻取得 | |
67 | + d = ad_ring_get(ad_ring_latest_get()); | |
68 | + // 日付変化検出用変数初期化 | |
69 | + high_tm = d->t; | |
70 | + sec_tm = d->t; | |
71 | + | |
72 | + PDEBUG("ProcRecInit: rec start.\n"); | |
73 | + return STS_REC; | |
74 | + } | |
75 | + return STS_REC_INIT; | |
76 | +} | |
77 | + | |
78 | +/**** 記録中 | |
79 | + 定期的にカードに書き込み | |
80 | + | |
81 | + Return: | |
82 | + 次の状態 | |
83 | +*/ | |
84 | +int ProcRec(void) | |
85 | +{ | |
86 | + AdData *d; | |
87 | + FILE *fp = NULL; | |
88 | + char buf[HIGH_WRITE_LEN+128]; | |
89 | + | |
90 | +// | |
91 | +/**** 1secデータ記録 | |
92 | +*/ | |
93 | + /* | |
94 | + パケットバッファにデータたまった? | |
95 | + */ | |
96 | + if (ad_ring_num_get_sec() >= SEC_FLUSH_NUM) { | |
97 | + // データ取り出し | |
98 | + d = ad_ring_get(ad_ring_read_get_sec()); | |
99 | + // ファイルオープン | |
100 | + sec_file_open(&fp, d); | |
101 | + | |
102 | + // 書き込みループ | |
103 | + while(ad_ring_num_get_sec() > 0) { | |
104 | + // データ取り出し | |
105 | + d = ad_ring_get(ad_ring_read_get_sec()); | |
106 | +PDEBUG("%04d/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X", | |
107 | + d->gps.year, d->gps.month, d->gps.day, d->gps.hour, d->gps.min, d->gps.sec, d->gps.nano, | |
108 | + d->gps.tow, d->gps.tacc, d->gps.valid); | |
109 | +int ch; | |
110 | +for(ch = 0; ch < AD_CHNUM; ch++) { | |
111 | + PDEBUG(",%+7ld", d->data1sec[ch]); | |
112 | +} | |
113 | +PDEBUG("\r\n"); | |
114 | + | |
115 | + // 日にち変わった ファイル切換する | |
116 | +#ifdef DEBUG_FILE_MIN | |
117 | + // デバッグ用 ?分ごとファイル切り替え | |
118 | + if ((d->t.tm_min % DEBUG_FILE_MIN_PERIOD) == 0 && (d->t.tm_sec == 0) && (d->t.tm_min != sec_tm.tm_min)) { | |
119 | +#else | |
120 | + if (d->t.tm_year != sec_tm.tm_year || d->t.tm_mon != sec_tm.tm_mon || d->t.tm_mday != sec_tm.tm_mday) { | |
121 | +#endif | |
122 | + // 日付変わったのでファイル切り替える | |
123 | + // 前のファイル閉じる | |
124 | + if (fp != NULL) sec_file_close(fp); | |
125 | + // ファイルオープン | |
126 | + if (sec_file_open(&fp, d)) { | |
127 | + PDEBUG("REC: FG file change ERROR\n"); | |
128 | + syslog(LOG_INFO, "REC: FG file change ERROR\n"); | |
129 | + } else { | |
130 | + PDEBUG("REC: FG file change OK\n"); | |
131 | + syslog(LOG_INFO, "REC: FG file change OK\n"); | |
132 | + } | |
133 | + } | |
134 | + // ファイルに書き込むデータ作成 | |
135 | + sec_make_rec_data(d, buf); | |
136 | + // ファイルに1データ書き込み Open/Closeなし | |
137 | + if (sec_file_out(fp, buf, strlen(buf))) { | |
138 | + /* 書き込みエラー */ | |
139 | + // 読み出し位置クリア | |
140 | + ad_ring_clear_sec(); | |
141 | + // ファイル閉じる | |
142 | + sec_file_close(fp); | |
143 | + // | |
144 | + PDEBUG("ProcRec: 1sec file write err\n"); | |
145 | + syslog(LOG_INFO, "REC: 1sec file write error\n"); | |
146 | + return STS_FILE_ERR; | |
147 | + } | |
148 | + // 読み込み位置進める | |
149 | + ad_ring_read_plus_sec(); | |
150 | + // タイムスタンプ記録 | |
151 | + sec_tm = d->t; | |
152 | + } | |
153 | + // ファイル閉じる | |
154 | + sec_file_close(fp); | |
155 | + // | |
156 | + PDEBUG("ProcRec: 1sec file write.\n"); | |
157 | + } | |
158 | +// | |
159 | +/**** 高速サンプルデータ記録 | |
160 | +*/ | |
161 | + /* | |
162 | + パケットバッファにデータたまった? | |
163 | + */ | |
164 | + if (ad_ring_num_get_high() >= HIGH_FLUSH_NUM) { | |
165 | + // データ取り出し | |
166 | + d = ad_ring_get(ad_ring_read_get_high()); | |
167 | + // ファイルオープン | |
168 | + high_file_open(&fp, d); | |
169 | + | |
170 | + // 書き込みループ | |
171 | + while(ad_ring_num_get_high() > 0) { | |
172 | + // データ取り出し | |
173 | + d = ad_ring_get(ad_ring_read_get_high()); | |
174 | + // 時が変わった ファイル切換する | |
175 | +#ifdef DEBUG_FILE_MIN | |
176 | + // デバッグ用 ?分ごとファイル切り替え | |
177 | + if ((d->t.tm_min % DEBUG_FILE_MIN_PERIOD) == 0 && (d->t.tm_high == 0) && (d->t.tm_min != hightm.tm_min)) { | |
178 | +#else | |
179 | + if (d->t.tm_year != high_tm.tm_year || d->t.tm_mon != high_tm.tm_mon || d->t.tm_mday != high_tm.tm_mday | |
180 | + || d->t.tm_hour != high_tm.tm_hour) { | |
181 | +#endif | |
182 | + // 時が変わったのでファイル切り替える | |
183 | + // 前のファイル閉じる | |
184 | + if (fp != NULL) high_file_close(fp); | |
185 | + // ファイルオープン | |
186 | + if (high_file_open(&fp, d)) { | |
187 | + PDEBUG("REC: FG file change ERROR\n"); | |
188 | + syslog(LOG_INFO, "REC: HIGH file change ERROR\n"); | |
189 | + } else { | |
190 | + PDEBUG("REC: FG file change OK\n"); | |
191 | + syslog(LOG_INFO, "REC: HIGH file change OK\n"); | |
192 | + } | |
193 | + } | |
194 | + // ファイルに書き込むデータ作成 | |
195 | + high_make_rec_data(d, buf); | |
196 | + // ファイルに1データ書き込み Open/Closeなし | |
197 | + if (high_file_out(fp, buf, HIGH_WRITE_LEN)) { | |
198 | + /* 書き込みエラー */ | |
199 | + // 読み出し位置クリア | |
200 | + ad_ring_clear_high(); | |
201 | + // ファイル閉じる | |
202 | + high_file_close(fp); | |
203 | + // | |
204 | + PDEBUG("ProcRec: HIGH file write err\n"); | |
205 | + syslog(LOG_INFO, "REC: HIGH file write error\n"); | |
206 | + return STS_FILE_ERR; | |
207 | + } | |
208 | + // 読み込み位置進める | |
209 | + ad_ring_read_plus_high(); | |
210 | + // タイムスタンプ記録 | |
211 | + high_tm = d->t; | |
212 | + } | |
213 | + // ファイル閉じる | |
214 | + high_file_close(fp); | |
215 | + // | |
216 | + PDEBUG("ProcRec: HIGH file write.\n"); | |
217 | + } | |
218 | + | |
219 | + return STS_REC; | |
220 | +} | |
221 | + | |
222 | +void* thread_rec(void* pParam) | |
223 | +{ | |
224 | + while(1) { | |
225 | + usleep(10*1000); | |
226 | + switch (sts_get()) { | |
227 | + /* 時刻校正中 */ | |
228 | + case STS_TIME_FIX: | |
229 | + sts_set(ProcTimeFix()); | |
230 | + break; | |
231 | + /* 記録初期化 */ | |
232 | + case STS_REC_INIT: | |
233 | + sts_set(ProcRecInit()); | |
234 | + break; | |
235 | + /* 記録中 */ | |
236 | + case STS_REC: | |
237 | + sts_set(ProcRec()); | |
238 | + break; | |
239 | + /* 記録OFF中 */ | |
240 | + case STS_REC_OFF: | |
241 | +// sts_set(ProcRecOff()); | |
242 | + break; | |
243 | + /* ファイルエラー発生中 */ | |
244 | + case STS_FILE_ERR: | |
245 | +// sts_set(ProcErr()); | |
246 | + break; | |
247 | + default: | |
248 | + break; | |
249 | + } | |
250 | + } // メインループ終わり | |
251 | +} |
@@ -0,0 +1,11 @@ | ||
1 | +#if !defined(__REC_H__) | |
2 | +#define __REC_H__ | |
3 | + | |
4 | + | |
5 | + | |
6 | +int ProcTimeFix(void); | |
7 | +int ProcRecInit(void); | |
8 | +int ProcRec(void); | |
9 | +void* thread_rec(void* pParam); | |
10 | + | |
11 | +#endif |