OSDN Git Service

IDE MPLABXで使えるようにする
[scilog/cpu2010.git] / main.c
1 /*
2  * File:   main.c
3  * sciLogger サブCPU
4  * PIC24Fj64GA004
5  * 8MHz
6
7  **** Ver1.1
8  * 2016/2
9  * IDE MPLABXで使えるようにするため
10  * xc16-gccのオプション, Option Categories: Optimization, Do not override 'inline' チェックを入れる
11  * _CONFIG2変更 定数定義が変わっているので
12  *
13  * Created on February 9, 2010, 10:53 AM
14  */
15
16 #include <stdio.h>
17 #include <stdlib.h>
18 #include <p24FJ64GA004.h>
19 #include <libpic30.h>
20 #include <string.h>
21 #include "myuart.h"
22 #include "myspi.h"
23 #include "debug_print.h"
24 #include "ublox.h"
25 #include "myad.h"
26 #include "delay.h"
27 #include "ring.h"
28 #include "byte2var.h"
29 #include "myint.h"
30 #include "mysts.h"
31 #include "util.h"
32
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
37
38
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
43 // UART2 Debug Port
44 #define BAUDRATE2         19200L
45 // UART1 GPS
46 #define BAUDRATE1         9600L
47
48 // SPI受信データの先頭文字 送信コマンドでも使用
49 #define SPI_HEAD_CHAR   '$'
50
51 /*** ADバッファ *************************************************
52  * 50Hzデータ
53  * 1秒平均データ
54  * タイムスタンプ
55  */
56 #define ADBUF_BYTE  3   // AD 1CH 1sample dataのbyte数
57 #define ADBUF_LEN   (sizeof(ADbufType)+1)   // SPI送信1packetの長さ byte $含まず DMA問題のために+1byteしている
58
59 #define RESDATA_LEN 17  // コマンドに対する返答データ 最大長さ
60
61 // 送信データの先頭からのオフセット adbuf内のオフセット $含まない
62 #define ADBUF_OFS_SUM           962 // checksum
63
64 // SPI送信にそのまま使われるので注意!
65 // 全体のサイズが2byteの整数倍になるようにすること word align
66 typedef struct {
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]のデータ
72     unsigned char suma;
73     unsigned char sumb;
74 } ADbufType;
75 //} __attribute__((__packed__)) ADbufType;
76 static ADbufType   adbuf[RING_NUM];
77
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))
82
83 inline void adbuf_write(unsigned char buf_no, unsigned char ch, int cnt, long *data)
84 {
85     unsigned char    *ptr = (unsigned char*)data;
86     unsigned char   i;
87
88     for(i = 0; i < ADBUF_BYTE; i++) {
89         adbuf[buf_no].data[ch][ADBUF_BYTE*cnt + i] = *(ptr++);
90     }
91 }
92 // 1
93 inline void adbuf_1sec_write(char buf_no, long *data)
94 {
95     my_memcpy(adbuf_1sec_get(buf_no), data, sizeof(long) * AD_CHNUM);
96 /*    char ch;
97     for(ch = 0; ch < AD_CHNUM; ch++)
98         adbuf_1sec[buf_no][ch] = data[ch];
99 */
100 }
101 inline void adbuf_time_write(char buf_no, UbloxNavTimeUtc *t)
102 {
103 //    my_memcpy(&adbuf_t[buf_no], t, sizeof(UbloxNavTimeUtc));
104     my_memcpy(adbuf_time_get(buf_no), t, sizeof(UbloxNavTimeUtc));
105 }
106 inline void adbuf_sum_write(char buf_no, unsigned char *suma, unsigned char *sumb)
107 {
108     adbuf[buf_no].suma = *suma;
109     adbuf[buf_no].sumb = *sumb;
110 }
111
112 /**** SPI CMD受信バッファ ********************************************
113  */
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
117
118 // 受信コマンド内のオフセット位置
119 #define CMD_OFS_CMDCODE 1
120 #define CMD_OFS_CMDDATA 2
121
122 // コマンドコード
123 #define CMD_CODE_GAIN   1
124
125 // 返答コード
126 #define RES_CODE_ACK    1
127 #define RES_CODE_NAK    2
128 #define RES_CODE_NUL    0
129
130 // 状態
131 #define CMD_STS_NONE    0   // 有効なコマンド無し
132 #define CMD_STS_RCVD    1   // 有効なコマンド受け取った
133 static char spi_cmd_sts;    // コマンド受信状態
134
135 #define spi_cmd_sts_set(i)  INTERRUPT_PROTECT(spi_cmd_sts = i)
136 #define spi_cmd_sts_get()   spi_cmd_sts
137
138
139 // ACK送信
140 void spi_res_send(unsigned char res_code, unsigned char *res_data, int data_len)
141 {
142     ADbufType *ad;
143
144     INTERRUPT_PROTECT(
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);
149         } else {
150             my_memcpy(ad->resdata, res_data, data_len);
151         }
152     );
153 }
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)
156
157
158 // コマンドに対応する処理
159 void spi_cmd_proc(void)
160 {
161     int i;
162
163     switch(spi_rx_buf[CMD_OFS_CMDCODE]) {
164         case CMD_CODE_GAIN:
165             for(i = 0; i < AD_CHNUM; i++) {
166                 pga_gain_set(i, spi_rx_buf[CMD_OFS_CMDDATA + i]);
167             }
168             // ACK送信
169             spi_res_send_ack();
170             break;
171         default:
172             PDEBUG("spi_cmd_porc(): unknown CMD CODE\r\n");
173             // NACK送信
174             spi_res_send_nak();
175             break;
176     }
177 }
178
179 /**** ublox ************************************************
180  */
181 static UbloxNavTimeUtc gpsNow;
182 static void ublox_rcv(void)
183 {
184     unsigned char class, id;
185     unsigned int    len;
186     unsigned char   payload[128];
187 //    char    sz[128];
188     UbloxNavTimeUtc *gps = &gpsNow;
189
190     ublox_rcv_pkt(&class, &id, &len, payload);
191 //    sprintf(sz, "CLASS=%02X ID=%02X LEN=%d\r\n", class, id, len);
192 //    PDEBUG(sz);
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
199         );
200         PDEBUG(sz);
201 */
202     }
203 }
204 /**** INT1/SPI1 ***********************************************/
205 /*
206  * INT1 Int及びSPI1 IntでADのデータを取得する
207  */
208 #define ADSTS_IDLE  0
209 #define ADSTS_H 1
210 #define ADSTS_M 2
211 #define ADSTS_L 3
212
213
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秒平均用加算
218
219 /**** 1PPS ********************************************/
220 static char pps_intf;
221
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)
225
226 /**** DataOut SPI2 *********************************************/
227 #define SPI2CSpin  (PORTCbits.RC8)
228
229 // SPI2 未送信データバイト数
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--)
234
235 // 送信位置ポインタ
236 static char    *dout_ptr;
237
238
239 /**** DRDY OUT ****************************************/
240 #define DRDY_OUT    PORTCbits.RC9
241
242
243 /*
244  * main()
245  */
246 int main(int argc, char** argv) {
247     unsigned int i;
248     // UART2 DebugPort
249     const double Baudrate2 = ( double )FCY / ( 16 * BAUDRATE2 ) - 1;
250     // ボーレートの小数点以下を四捨五入する
251     unsigned int baudrate2 = ( unsigned int )( Baudrate2 + 0.5 );
252     // UART1 GPS
253     const double Baudrate1 = ( double )FCY / ( 16 * BAUDRATE1 ) - 1;
254     // ボーレートの小数点以下を四捨五入する
255     unsigned int baudrate1 = ( unsigned int )( Baudrate1 + 0.5 );
256     char    sz[128];
257     UbloxNavTimeUtc *gps = &gpsNow;
258     ADbufType   *ad;
259     
260     /**** 割り込み禁止 ****/
261     SET_CPU_IPL( 7 );
262     __builtin_write_OSCCONL(OSCCON & 0xbf); //clear the bit 6 of OSCCONL to unlock Pin Re-map
263     // 割り込みネストenable
264     int_nest_enable();
265
266     // UART1ピン割り当て
267     RPINR18bits.U1RXR = 6;      // UART1 RX to RP6
268     RPOR2bits.RP5R =  3;        // UART1 TX(3) to RP5
269     // UART2ピン割り当て
270     RPINR19bits.U2RXR = 21;     // UART2 RX to RP21
271     RPOR10bits.RP20R = 5;       // UART2 TX(5) to RP20
272     // PIC-RDYピン割り当て
273     RPOR12bits.RP25R = 0;       // RC9
274
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
286     //        5432109876543210
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
291
292     // INT1(RP12 RB12) AD -DRDY0 setup
293     RPINR0bits.INT1R = 12;  // RP12(RB12)
294     int1_int_disable();
295     int1_level_set(4);    // Int priority
296     int1_edge_neg(); // Negative Edge
297     // INT0(RB7) GPS +PPS setup
298     int0_int_disable();
299     int0_level_set(4);    // INT Priority
300     int0_edge_pos(); // Positive Edge
301     // ChangeNotification INT, CN20(RC8), SPI2(Overo) CS0
302     cnint_int_disable();
303     CNEN2bits.CN20IE = 1;
304     CNPU2bits.CN20PUE = 1;  // Pullup ON
305     cnint_level_set(4);
306
307     adint_cnt = 0;
308     ad_cs_dis();
309     sts_set(STS_NOSYNC);
310     pps_intf_clear();
311     DRDY_OUT = 1;
312     spi_cmd_sts = CMD_STS_NONE;
313     
314     // GPS UART1初期設定 BRGH=Standard mode
315     // 9600bps 8bit nonparity 1stop nonflowcnt.
316     //                           5432109876543210
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.
323     //                           5432109876543210
324     unsigned int U2MODEvalue = 0b1000100000000000;
325     unsigned int U2STAvalue =  0b0000010000000000;
326     uart2_init( U2MODEvalue, U2STAvalue, baudrate2);
327
328
329     spi1_init();
330     spi2_init();
331     spi1_int_disable();
332     spi2_int_disable();
333     spi2_putc(SPI_HEAD_CHAR); // 一番最初のデータ送信のためにセットしておく
334
335     PDEBUG("START\r\n");
336 //    sprintf(sz, "sizeof(ADBUF)=%d\r\n", ADBUF_LEN);
337 //    PDEBUG(sz);
338
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
345 PDEBUG("*");
346
347     //**** 割り込み許可 **************************************************
348     // CPU割り込み優先レベル デフォルト0 ペリフェラルはデフォルト4
349 //    SRbits.IPL = 2;
350     SET_CPU_IPL( 2 );
351 PDEBUG("*");
352
353     // ublox起動待ち
354     delay_ms(100);
355     // UBXプロトコルのみにする
356     ublox_rcvbuf_clear();
357     ublox_send_cfg_prt(BAUDRATE1);
358     ublox_rcv_ack();
359     // TimePulse2にAD用クロック出力する
360     ublox_rcvbuf_clear();
361     ublox_send_cfg_tp5_timepulse2();
362     ublox_rcv_ack();
363 PDEBUG("*");
364     // TimePulse1をGPS時刻fixしなくても出力する
365     // pulse幅 unlocked=500msec locked=100msec
366     ublox_rcvbuf_clear();
367     ublox_send_cfg_tp5_timepulse1();
368     ublox_rcv_ack();
369 PDEBUG("*");
370     // NAV-TIMEUTC出力させる
371     ublox_send_cfg_msg();
372     ublox_rcv_ack();
373 PDEBUG("*");
374
375     // AD初期化
376     ad_reset_dis();
377     ad_start_dis();
378     ad_cs_dis();
379     //
380     ad_reset(); // -AD RESET
381     // WAIT 2^16 AD system clocks
382     delay_ms(100);
383 PDEBUG("*");
384     //
385     ad_cs_init();
386     ad_init();
387     pga_init();
388     
389     ring_init();
390 PDEBUG("*");
391     // AD SPI1 割り込み設定のみ 許可しない
392     // INT1ハンドラ内で有効にされる
393     spi1_intf_clear();
394     spi1_set_int_level(4);
395     // DataOut SPI2 割り込み許可しない CSのCN INTで許可するので
396     spi2_intf_clear();
397     spi2_set_int_level(4);
398 PDEBUG("*");
399
400     /**** ペリフェラル割り込み許可 INT1/INT0/CN ************************/
401     // INT1割り込み許可
402     int1_intf_clear();
403     int1_int_enable();    // Int enable
404 PDEBUG("*");
405     // INT0割り込み許可
406     int0_intf_clear();
407     int0_int_enable();    // Int enable
408 PDEBUG("*");
409     // ChangeNotification INT許可 SPI2(Overo) CS
410     cnint_intf_clear();
411     cnint_int_enable();
412 PDEBUG("*\r\n");
413
414     while(1) {
415         // GPSから受信してデコード
416         ublox_rcv();
417         if (gpsNow.valid == 0x07 && sts_get() == STS_NOSYNC) {
418             // 時刻有効
419             sts_set(STS_SYNCNOW0);
420         }
421         // DebugOutに1secデータ出力
422         if (ring_read2_get() != ring_write_get()) {
423             // タイムスタンプ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
428             );
429             PDEBUG(sz);
430
431 #if 1
432             // AD data get
433             char ch;
434             long    *lp;
435             lp = adbuf_1sec_get(ring_read2_get());
436             for(ch=0; ch<AD_CHNUM; ch++) {
437                 sprintf(sz, ",%+7ld", lp[ch]);
438                 PDEBUG(sz);
439             }
440             PDEBUG("\r\n");
441 #endif
442 #if 0
443             ad = adbuf_get(ring_read2_get());
444             sprintf(sz, "%02X %02X\r\n", ad->sumb, ad->suma);
445             PDEBUG(sz);
446 #endif
447             ring_read2_plus();
448         }
449         // SPIからコマンド受信
450         if (spi_cmd_sts_get() == CMD_STS_RCVD) {
451 #ifdef DEBUG_PRINT
452             PDEBUG("CMD RCV:");
453             for(i = 0; i < SPI_RX_LEN; i++) {
454                 sprintf(sz, " %02X", spi_rx_buf[i]);
455                 PDEBUG(sz);
456             }
457             PDEBUG("\r\n");
458 #endif
459             // コマンドに対応する処理
460             spi_cmd_proc();
461             // コマンド受信再開
462             spi_cmd_sts_set(CMD_STS_NONE);
463         }
464
465     }
466     
467     return (EXIT_SUCCESS);
468 }
469 /*
470  * INT0 GPS 1PPS割り込みハンドラ
471  * 
472  *
473  */
474 void __attribute__((interrupt, no_auto_psv, shadow)) _INT0Interrupt(void)
475 {
476     // AD STARTピン=H
477     ad_start_ena();
478
479     int0_intf_clear();
480     pps_intf_set();
481     /****AD同期!!!!!!!!!!!!!!!*/
482     // AD個数カウンタ=SAMP_FREQ-1
483     adint_cnt = AD_SAMPLE - 1;
484
485     // AD START信号による同期
486     if (sts_get() == STS_SYNCNOW0) {
487         // AD STARTピン=L
488         ad_start_dis();
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) {
494         sts_set(STS_SYNCED);
495     }
496 }
497
498 /*
499  * INT1(RP12) AD DRDY0割り込みハンドラ
500  * Negativ Edge
501  * SPI1受信開始してSPI1割り込み有効にする
502  *
503  */
504 void __attribute__((interrupt, no_auto_psv)) _INT1Interrupt(void)
505 //void _ISR _INT1Interrupt(void)
506 {
507     int1_intf_clear();
508     if (!ad_is_drdy0_enable()) {
509         return;
510     }
511
512     adint_ch = 0;
513     adint_sts = ADSTS_H;
514     if (adint_cnt == 0) {
515         my_memset(adint_add, 0, sizeof(adint_add));
516     }
517
518     ad_cs(adint_ch);    // CSx=L
519     spi1_rx_overrun_clear();
520     // 前に受信したデータをクリア
521     spi1_getc();
522     // SPI割り込みON
523     spi1_intf_clear();
524     spi1_int_enable();
525     // 送信
526     spi1_putc(0);
527
528 }
529 /*
530  * AD SPI1 Interrupt Handler
531  * ADから受信したデータをADバッファに格納する
532  * 6CHぶん受信したらSPI1割り込みをOFF
533  * 
534  */
535 //void _ISR _SPI1Interrupt(void)
536 void __attribute__((interrupt, auto_psv)) _SPI1Interrupt(void)
537 {
538     static unsigned char in[3];
539     unsigned char c;
540     long    l;
541 //int i;
542 //unsigned char   *ptr;
543
544     spi1_intf_clear();
545     c = spi1_getc();
546     spi1_rx_overrun_clear();
547
548     switch(adint_sts) {
549         case ADSTS_H:
550             in[2] = c;
551             adint_sts = ADSTS_M;
552             spi1_putc(0);
553             break;
554         case ADSTS_M:
555             in[1] = c;
556             adint_sts = ADSTS_L;
557             spi1_putc(0);
558             break;
559         case ADSTS_L:
560             // CSx=H
561             ad_cs_dis();
562             in[0] = c;
563             l = byte3_to_long(in);
564             // バッファに書きこみ
565             adbuf_write(ring_write_get(), adint_ch, adint_cnt, &l);
566             // 1秒平均用加算
567             adint_add[adint_ch] += l;
568             // CH進める
569             adint_ch++;
570             if (adint_ch >= AD_CHNUM) {
571                 // 全CHデータgetした
572                 adint_cnt++;
573                 if (adint_cnt == AD_SAMPLE-1) {
574                     // ADバッファにタイムスタンプ付ける
575                     adbuf_time_write(ring_write_get(), &gpsNow);
576                 } else if (adint_cnt >= AD_SAMPLE) {
577                     // 1secぶんのデータgetした
578                     // DRDY->H DRDY=Lの時でもDRDYのエッジを作るため
579                     DRDY_OUT = 1;
580                     // 1sec平均する
581                     char ch;
582                     for(ch = 0; ch < AD_CHNUM; ch++) {
583                         adint_add[ch] /= adint_cnt;
584                     }
585                     // 1secバッファに書きこみ
586                     adbuf_1sec_write(ring_write_get(), adint_add);
587 #if 0
588 ptr = (unsigned char*)adbuf_get(ring_write_get());
589 ptr += 62;
590             for(i = 0; i < 900; i++) {
591                 suma += *ptr++;
592                 sumb += suma;
593             }
594 #endif
595                     // バッファ書き込み位置+1
596                     ring_write_plus();
597                     // 次のADバッファをゼロクリア
598                     my_memset(adbuf_get(ring_write_get()), 0, ADBUF_LEN);
599                     adint_cnt = 0;
600                     // DRDY->L
601 // TODO: waitカウンタで制限
602                     DRDY_OUT = 0;
603                 }
604                 spi1_int_disable(); // SPI割り込みOFF
605                 adint_sts = ADSTS_IDLE;
606             } else {
607                 // 次のCHへ
608                 ad_cs(adint_ch);    // CSx=L
609                 // 送信
610                 spi1_putc(0);
611                 adint_sts = ADSTS_H;
612             }
613
614             break;
615         default:
616             spi1_int_disable(); // SPI割り込みOFF
617             adint_sts = ADSTS_IDLE;
618             break;
619     }
620
621 }
622 static unsigned char    suma;
623 static unsigned char    sumb;
624
625 /*
626  * DataOut SPI2 Interrupt Handler
627  * TX FIFOに1byteの空きが出来ると発生
628  */
629 void __attribute__((interrupt, no_auto_psv)) _SPI2Interrupt(void)
630 {
631     unsigned char   rx;
632
633     spi2_intf_clear();
634     // 送信 AD DATA
635     while(SPI2_TBF == 0) {
636         // checksum
637         if ((ADBUF_LEN - dataout_cnt_get()) == ADBUF_OFS_SUM) {
638             // checksum書き込み
639             adbuf_sum_write(ring_read1_get(), &suma, &sumb);
640         }
641         suma += (unsigned char)*dout_ptr;
642         sumb += suma;
643
644         if (dataout_cnt_get() <= 0) break;
645         spi2_putc(*dout_ptr++);
646         dataout_cnt_minus();
647     }
648     // 受信 CMD
649     while(SPI2_SRXMPT == 0) {
650         rx = spi2_getc();
651         if (spi_cmd_sts == CMD_STS_NONE && spi_rx_cnt < SPI_RX_LEN) {
652             spi_rx_buf[spi_rx_cnt] = rx;
653             spi_rx_cnt++;
654             if (spi_rx_cnt >= SPI_RX_LEN) {
655                 if (spi_rx_buf[CMD_OFS_CMDCODE] != 0) {
656                     spi_cmd_sts = CMD_STS_RCVD;
657                 }
658             }
659         }
660     }
661
662     // オーバーランエラーならばクリアする
663     if (SPI2STATbits.SPIROV == 1) SPI2STATbits.SPIROV = 0;
664
665 }
666 /*
667  * Overo SPI2 CS Input Change Notification
668  * Interrupt Handler
669  *
670  */
671 void __attribute__((interrupt, no_auto_psv)) _CNInterrupt(void)
672 {
673     cnint_intf_clear();
674     if (SPI2CSpin == 1) {
675         // CS=H
676         // SPI2割り込みOFF
677         spi2_int_disable();
678         // SPI2をリセットしてTX/RX FIFOクリア
679         SPI2STATbits.SPIEN = 0;
680         asm("nop");
681         SPI2STATbits.SPIEN = 1;
682         asm("nop");
683         SPI2BUF;    // RBF->0
684         // $->TX FIFO
685         spi2_putc(SPI_HEAD_CHAR);
686         // リングバッファ読み込み位置+1
687         ring_read1_plus();
688         // 送信データがリングバッファにあるとき
689         if (ring_num1_get() > 0) {
690             // DRDY->L
691             DRDY_OUT = 0;
692         }
693     } else {
694         // CS=L
695         // リングバッファ読み込み位置get
696         dout_ptr = (char*)adbuf_get(ring_read1_get());
697         // SPI送信の一番最初
698         dataout_cnt_set(ADBUF_LEN);
699         suma = 0;
700         sumb = 0;
701         // SPI2 TX FIFOに送信データ書き込み
702         while(SPI2_TBF == 0) {
703             suma += (unsigned char)*dout_ptr;
704             sumb += suma;
705             if (dataout_cnt_get() <= 0) break;
706             spi2_putc(*dout_ptr++);
707             dataout_cnt_minus();
708         }
709         if (spi_cmd_sts == CMD_STS_NONE) {
710             // SPI受信文字数カウンタクリア
711             spi_rx_cnt = 0;
712         }
713         // SPI2割り込みON
714         spi2_int_enable();
715         // DRDY=H
716         DRDY_OUT = 1;
717     }
718 }