9 * IDE MPLABXで使えるようにするため
10 * xc16-gccのオプション, Option Categories: Optimization, Do not override 'inline' チェックを入れる
11 * _CONFIG2変更 定数定義が変わっているので
13 * Created on February 9, 2010, 10:53 AM
18 #include <p24FJ64GA004.h>
23 #include "debug_print.h"
33 _CONFIG1( JTAGEN_OFF & GCP_OFF & GWRP_OFF & COE_OFF & FWDTEN_OFF & ICS_PGx2 )
34 //_CONFIG2( FCKSM_CSDCMD & OSCIOFNC_ON & POSCMOD_OFF & FNOSC_FRC)
35 //#pragma config FCKSM = CSDCMD, OSCIOFNC = ON, POSCMOD = OFF, FNOSC = FRC, FPBDIV = DIV_8
36 _CONFIG2(POSCMOD_NONE & IOL1WAY_OFF & OSCIOFNC_ON & FCKSM_CSDCMD & FCKSM_CSECMD & FNOSC_FRC) // RC 8MHz
39 //#define CPU_CLOCK 10000000 // クロック[ Hz ]
40 //#define CPU_PLL 8 // PLL
41 //#define CLOCK_FREQUENCY ( ( CPU_CLOCK * CPU_PLL ) / 4 ) // 動作周波数[ Hz ]
42 //#define FOSC 4000000L
44 #define BAUDRATE2 19200L
46 #define BAUDRATE1 9600L
48 // SPI受信データの先頭文字 送信コマンドでも使用
49 #define SPI_HEAD_CHAR '$'
51 /*** ADバッファ *************************************************
56 #define ADBUF_BYTE 3 // AD 1CH 1sample dataのbyte数
57 #define ADBUF_LEN (sizeof(ADbufType)+1) // SPI送信1packetの長さ byte $含まず DMA問題のために+1byteしている
59 #define RESDATA_LEN 17 // コマンドに対する返答データ 最大長さ
61 // 送信データの先頭からのオフセット adbuf内のオフセット $含まない
62 #define ADBUF_OFS_SUM 962 // checksum
64 // SPI送信にそのまま使われるので注意!
65 // 全体のサイズが2byteの整数倍になるようにすること word align
67 unsigned char rescode; // コマンドに対する返答 ACK/NAK/NUL
68 unsigned char resdata[RESDATA_LEN]; // コマンドに対する返答データ
69 UbloxNavTimeUtc t; // タイムスタンプ
70 long data1sec[AD_CHNUM]; // 1sec平均値
71 unsigned char data[AD_CHNUM][ADBUF_BYTE*AD_SAMPLE]; // AD_SAMPLE[Hz]のデータ
75 //} __attribute__((__packed__)) ADbufType;
76 static ADbufType adbuf[RING_NUM];
78 #define adbuf_get(buf_no) (&adbuf[buf_no])
79 #define adbuf_data_get(buf_no) (adbuf[buf_no].data)
80 #define adbuf_1sec_get(buf_no) (adbuf[buf_no].data1sec)
81 #define adbuf_time_get(buf_no) (&(adbuf[buf_no].t))
83 inline void adbuf_write(unsigned char buf_no, unsigned char ch, int cnt, long *data)
85 unsigned char *ptr = (unsigned char*)data;
88 for(i = 0; i < ADBUF_BYTE; i++) {
89 adbuf[buf_no].data[ch][ADBUF_BYTE*cnt + i] = *(ptr++);
93 inline void adbuf_1sec_write(char buf_no, long *data)
95 my_memcpy(adbuf_1sec_get(buf_no), data, sizeof(long) * AD_CHNUM);
97 for(ch = 0; ch < AD_CHNUM; ch++)
98 adbuf_1sec[buf_no][ch] = data[ch];
101 inline void adbuf_time_write(char buf_no, UbloxNavTimeUtc *t)
103 // my_memcpy(&adbuf_t[buf_no], t, sizeof(UbloxNavTimeUtc));
104 my_memcpy(adbuf_time_get(buf_no), t, sizeof(UbloxNavTimeUtc));
106 inline void adbuf_sum_write(char buf_no, unsigned char *suma, unsigned char *sumb)
108 adbuf[buf_no].suma = *suma;
109 adbuf[buf_no].sumb = *sumb;
112 /**** SPI CMD受信バッファ ********************************************
114 #define SPI_RX_LEN 20 // Overoから受信するコマンド長 $含む
115 static char spi_rx_buf[SPI_RX_LEN];
116 static char spi_rx_cnt; // 受信文字数カウント 0〜SPI_RX_LEN
119 #define CMD_OFS_CMDCODE 1
120 #define CMD_OFS_CMDDATA 2
123 #define CMD_CODE_GAIN 1
126 #define RES_CODE_ACK 1
127 #define RES_CODE_NAK 2
128 #define RES_CODE_NUL 0
131 #define CMD_STS_NONE 0 // 有効なコマンド無し
132 #define CMD_STS_RCVD 1 // 有効なコマンド受け取った
133 static char spi_cmd_sts; // コマンド受信状態
135 #define spi_cmd_sts_set(i) INTERRUPT_PROTECT(spi_cmd_sts = i)
136 #define spi_cmd_sts_get() spi_cmd_sts
140 void spi_res_send(unsigned char res_code, unsigned char *res_data, int data_len)
145 ad = adbuf_get(ring_read1_get());
146 ad->rescode = res_code;
147 if (res_data == NULL || data_len <= 0) {
148 my_memset(ad->resdata, 0, RESDATA_LEN);
150 my_memcpy(ad->resdata, res_data, data_len);
154 #define spi_res_send_ack() spi_res_send(RES_CODE_ACK, NULL, 0)
155 #define spi_res_send_nak() spi_res_send(RES_CODE_NAK, NULL, 0)
159 void spi_cmd_proc(void)
163 switch(spi_rx_buf[CMD_OFS_CMDCODE]) {
165 for(i = 0; i < AD_CHNUM; i++) {
166 pga_gain_set(i, spi_rx_buf[CMD_OFS_CMDDATA + i]);
172 PDEBUG("spi_cmd_porc(): unknown CMD CODE\r\n");
179 /**** ublox ************************************************
181 static UbloxNavTimeUtc gpsNow;
182 static void ublox_rcv(void)
184 unsigned char class, id;
186 unsigned char payload[128];
188 UbloxNavTimeUtc *gps = &gpsNow;
190 ublox_rcv_pkt(&class, &id, &len, payload);
191 // sprintf(sz, "CLASS=%02X ID=%02X LEN=%d\r\n", class, id, len);
193 // ublox_debug_pkt_out(payload, len);
194 if (class == UBX_CLS_NAV && id == UBX_ID_NAV_TIMEUTC && len == UBX_LEN_NAV_TIMEUTC) {
195 ublox_decode_nav_timeutc(payload, gps);
196 /* sprintf(sz, "%04u/%02d/%02d %02d:%02d:%02d.%09ld %6lums %6luns %02X\r\n",
197 gps->year, gps->month, gps->day, gps->hour, gps->min, gps->sec, gps->nano,
198 gps->tow, gps->tacc, gps->valid
204 /**** INT1/SPI1 ***********************************************/
206 * INT1 Int及びSPI1 IntでADのデータを取得する
214 static char adint_ch; // 取得中のCH
215 static char adint_cnt = 0; // 0〜AD_SAMPLE-1
216 static char adint_sts = ADSTS_IDLE;
217 static long adint_add[AD_CHNUM]; // 1秒平均用加算
219 /**** 1PPS ********************************************/
220 static char pps_intf;
222 #define pps_intf_clear() pps_intf = 0
223 #define pps_intf_set() pps_intf = 1
224 #define pps_is_intf_enable() (pps_intf != 0)
226 /**** DataOut SPI2 *********************************************/
227 #define SPI2CSpin (PORTCbits.RC8)
230 static int dataout_cnt;
231 #define dataout_cnt_set(i) dataout_cnt = (i)
232 #define dataout_cnt_get() dataout_cnt
233 #define dataout_cnt_minus() (dataout_cnt--)
236 static char *dout_ptr;
239 /**** DRDY OUT ****************************************/
240 #define DRDY_OUT PORTCbits.RC9
246 int main(int argc, char** argv) {
249 const double Baudrate2 = ( double )FCY / ( 16 * BAUDRATE2 ) - 1;
250 // ボーレートの小数点以下を四捨五入する
251 unsigned int baudrate2 = ( unsigned int )( Baudrate2 + 0.5 );
253 const double Baudrate1 = ( double )FCY / ( 16 * BAUDRATE1 ) - 1;
254 // ボーレートの小数点以下を四捨五入する
255 unsigned int baudrate1 = ( unsigned int )( Baudrate1 + 0.5 );
257 UbloxNavTimeUtc *gps = &gpsNow;
262 __builtin_write_OSCCONL(OSCCON & 0xbf); //clear the bit 6 of OSCCONL to unlock Pin Re-map
267 RPINR18bits.U1RXR = 6; // UART1 RX to RP6
268 RPOR2bits.RP5R = 3; // UART1 TX(3) to RP5
270 RPINR19bits.U2RXR = 21; // UART2 RX to RP21
271 RPOR10bits.RP20R = 5; // UART2 TX(5) to RP20
273 RPOR12bits.RP25R = 0; // RC9
275 // DataOut SPI2 pin config
276 RPINR22bits.SDI2R = 13; // SPI2 RX to RP13
277 RPINR22bits.SCK2R = 23; // SPI2 CLK to RP23
278 RPINR23bits.SS2R = 24; // SPI2 SS to RP24
279 RPOR11bits.RP22R = 10; // SPI1 SDO2(10) to RP22
280 // AD SPI1 pin config
281 RPINR20bits.SDI1R = 18; // SPI1 RX to RP18
282 RPOR8bits.RP16R = 8; // SPI1 SCK1(8) to RP16
283 RPOR8bits.RP17R = 7; // SPI1 SDO1(7) to RP17
284 // TRISx 1=input 0=output
285 TRISA = 0x0000; // PortA RA7,8,9 output
287 TRISB = 0b0011000011000000; // PortB RB13(RP13),RB12,RB7,RB6(RP6) input
288 TRISC = 0x01A4; // ポートC RC8(RP24),RC7(RP23),RC5(RP21),RC2(RP18) input
289 CLKDIV = 0; // CPU Peripheral Clock Ratio=1:1
290 AD1PCFG = 0xFFFF; // AN1-12input pin = Digital mode
292 // INT1(RP12 RB12) AD -DRDY0 setup
293 RPINR0bits.INT1R = 12; // RP12(RB12)
295 int1_level_set(4); // Int priority
296 int1_edge_neg(); // Negative Edge
297 // INT0(RB7) GPS +PPS setup
299 int0_level_set(4); // INT Priority
300 int0_edge_pos(); // Positive Edge
301 // ChangeNotification INT, CN20(RC8), SPI2(Overo) CS0
303 CNEN2bits.CN20IE = 1;
304 CNPU2bits.CN20PUE = 1; // Pullup ON
312 spi_cmd_sts = CMD_STS_NONE;
314 // GPS UART1初期設定 BRGH=Standard mode
315 // 9600bps 8bit nonparity 1stop nonflowcnt.
317 unsigned int U1MODEvalue = 0b1000100000000000;
318 unsigned int U1STAvalue = 0b0000010000000000;
319 // OpenUART1( U1MODEvalue, U1STAvalue, baudrate1);
320 uart1_init( U1MODEvalue, U1STAvalue, baudrate1);
321 // DEBUG UART2初期設定 BRGH=Standard mode
322 // 9600bps 8bit nonparity 1stop nonflowcnt.
324 unsigned int U2MODEvalue = 0b1000100000000000;
325 unsigned int U2STAvalue = 0b0000010000000000;
326 uart2_init( U2MODEvalue, U2STAvalue, baudrate2);
333 spi2_putc(SPI_HEAD_CHAR); // 一番最初のデータ送信のためにセットしておく
336 // sprintf(sz, "sizeof(ADBUF)=%d\r\n", ADBUF_LEN);
339 // GPS UART1 受信割り込み許可
340 uart1_rx_int_enable();
341 uart1_set_int_level(4); // 割り込みレベル デフォルト4
342 // DebugOut UART2 受信割り込み許可
343 uart2_rx_int_enable();
344 uart2_set_int_level(4); // 割り込みレベル デフォルト4
347 //**** 割り込み許可 **************************************************
348 // CPU割り込み優先レベル デフォルト0 ペリフェラルはデフォルト4
356 ublox_rcvbuf_clear();
357 ublox_send_cfg_prt(BAUDRATE1);
359 // TimePulse2にAD用クロック出力する
360 ublox_rcvbuf_clear();
361 ublox_send_cfg_tp5_timepulse2();
364 // TimePulse1をGPS時刻fixしなくても出力する
365 // pulse幅 unlocked=500msec locked=100msec
366 ublox_rcvbuf_clear();
367 ublox_send_cfg_tp5_timepulse1();
371 ublox_send_cfg_msg();
380 ad_reset(); // -AD RESET
381 // WAIT 2^16 AD system clocks
391 // AD SPI1 割り込み設定のみ 許可しない
394 spi1_set_int_level(4);
395 // DataOut SPI2 割り込み許可しない CSのCN INTで許可するので
397 spi2_set_int_level(4);
400 /**** ペリフェラル割り込み許可 INT1/INT0/CN ************************/
403 int1_int_enable(); // Int enable
407 int0_int_enable(); // Int enable
409 // ChangeNotification INT許可 SPI2(Overo) CS
417 if (gpsNow.valid == 0x07 && sts_get() == STS_NOSYNC) {
419 sts_set(STS_SYNCNOW0);
421 // DebugOutに1secデータ出力
422 if (ring_read2_get() != ring_write_get()) {
424 gps = adbuf_time_get(ring_read2_get());
425 sprintf(sz, "%04u/%02d/%02d %02d:%02d:%02d.%09ld,%6lums,%6luns,%02X",
426 gps->year, gps->month, gps->day, gps->hour, gps->min, gps->sec, gps->nano,
427 gps->tow, gps->tacc, gps->valid
435 lp = adbuf_1sec_get(ring_read2_get());
436 for(ch=0; ch<AD_CHNUM; ch++) {
437 sprintf(sz, ",%+7ld", lp[ch]);
443 ad = adbuf_get(ring_read2_get());
444 sprintf(sz, "%02X %02X\r\n", ad->sumb, ad->suma);
450 if (spi_cmd_sts_get() == CMD_STS_RCVD) {
453 for(i = 0; i < SPI_RX_LEN; i++) {
454 sprintf(sz, " %02X", spi_rx_buf[i]);
462 spi_cmd_sts_set(CMD_STS_NONE);
467 return (EXIT_SUCCESS);
470 * INT0 GPS 1PPS割り込みハンドラ
474 void __attribute__((interrupt, no_auto_psv, shadow)) _INT0Interrupt(void)
481 /****AD同期!!!!!!!!!!!!!!!*/
482 // AD個数カウンタ=SAMP_FREQ-1
483 adint_cnt = AD_SAMPLE - 1;
486 if (sts_get() == STS_SYNCNOW0) {
489 sts_set(STS_SYNCNOW1);
490 } else if (sts_get() == STS_SYNCNOW1) {
491 // AD STARTピン=H 関数先頭で行っているのでここではやらない
492 sts_set(STS_SYNCWAIT);
493 } else if (sts_get() == STS_SYNCWAIT) {
499 * INT1(RP12) AD DRDY0割り込みハンドラ
501 * SPI1受信開始してSPI1割り込み有効にする
504 void __attribute__((interrupt, no_auto_psv)) _INT1Interrupt(void)
505 //void _ISR _INT1Interrupt(void)
508 if (!ad_is_drdy0_enable()) {
514 if (adint_cnt == 0) {
515 my_memset(adint_add, 0, sizeof(adint_add));
518 ad_cs(adint_ch); // CSx=L
519 spi1_rx_overrun_clear();
530 * AD SPI1 Interrupt Handler
531 * ADから受信したデータをADバッファに格納する
532 * 6CHぶん受信したらSPI1割り込みをOFF
535 //void _ISR _SPI1Interrupt(void)
536 void __attribute__((interrupt, auto_psv)) _SPI1Interrupt(void)
538 static unsigned char in[3];
542 //unsigned char *ptr;
546 spi1_rx_overrun_clear();
563 l = byte3_to_long(in);
565 adbuf_write(ring_write_get(), adint_ch, adint_cnt, &l);
567 adint_add[adint_ch] += l;
570 if (adint_ch >= AD_CHNUM) {
573 if (adint_cnt == AD_SAMPLE-1) {
575 adbuf_time_write(ring_write_get(), &gpsNow);
576 } else if (adint_cnt >= AD_SAMPLE) {
578 // DRDY->H DRDY=Lの時でもDRDYのエッジを作るため
582 for(ch = 0; ch < AD_CHNUM; ch++) {
583 adint_add[ch] /= adint_cnt;
586 adbuf_1sec_write(ring_write_get(), adint_add);
588 ptr = (unsigned char*)adbuf_get(ring_write_get());
590 for(i = 0; i < 900; i++) {
598 my_memset(adbuf_get(ring_write_get()), 0, ADBUF_LEN);
604 spi1_int_disable(); // SPI割り込みOFF
605 adint_sts = ADSTS_IDLE;
608 ad_cs(adint_ch); // CSx=L
616 spi1_int_disable(); // SPI割り込みOFF
617 adint_sts = ADSTS_IDLE;
622 static unsigned char suma;
623 static unsigned char sumb;
626 * DataOut SPI2 Interrupt Handler
627 * TX FIFOに1byteの空きが出来ると発生
629 void __attribute__((interrupt, no_auto_psv)) _SPI2Interrupt(void)
635 while(SPI2_TBF == 0) {
637 if ((ADBUF_LEN - dataout_cnt_get()) == ADBUF_OFS_SUM) {
639 adbuf_sum_write(ring_read1_get(), &suma, &sumb);
641 suma += (unsigned char)*dout_ptr;
644 if (dataout_cnt_get() <= 0) break;
645 spi2_putc(*dout_ptr++);
649 while(SPI2_SRXMPT == 0) {
651 if (spi_cmd_sts == CMD_STS_NONE && spi_rx_cnt < SPI_RX_LEN) {
652 spi_rx_buf[spi_rx_cnt] = rx;
654 if (spi_rx_cnt >= SPI_RX_LEN) {
655 if (spi_rx_buf[CMD_OFS_CMDCODE] != 0) {
656 spi_cmd_sts = CMD_STS_RCVD;
663 if (SPI2STATbits.SPIROV == 1) SPI2STATbits.SPIROV = 0;
667 * Overo SPI2 CS Input Change Notification
671 void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void)
674 if (SPI2CSpin == 1) {
678 // SPI2をリセットしてTX/RX FIFOクリア
679 SPI2STATbits.SPIEN = 0;
681 SPI2STATbits.SPIEN = 1;
685 spi2_putc(SPI_HEAD_CHAR);
688 // 送信データがリングバッファにあるとき
689 if (ring_num1_get() > 0) {
696 dout_ptr = (char*)adbuf_get(ring_read1_get());
698 dataout_cnt_set(ADBUF_LEN);
701 // SPI2 TX FIFOに送信データ書き込み
702 while(SPI2_TBF == 0) {
703 suma += (unsigned char)*dout_ptr;
705 if (dataout_cnt_get() <= 0) break;
706 spi2_putc(*dout_ptr++);
709 if (spi_cmd_sts == CMD_STS_NONE) {