view gpib.cc @ 9:16a338171c99

remove random.h after programming
author Frank Kingswood <frank@kingswood-consulting.co.uk>
date Mon, 21 Apr 2014 11:14:00 +0100
parents ef38703286dd
children
line wrap: on
line source
1 /* #------------------------------------------------------------------------#
2 | |
3 | gpib.cc |
4 | |
5 | USB-GPIB GPIB processing and state machine. |
6 | |
7 | Copyright 2014, Frank A. Kingswood, www.kingswood-consulting.co.uk |
8 | |
9 #------------------------------------------------------------------------# */
11 #include <avr/pgmspace.h>
12 #include <avr/interrupt.h>
13 #include <stdint.h>
14 #include <ctype.h>
15 #include <util/delay.h>
16 #include "usb_serial.h"
17 #include "gpib.h"
19 // GPIB Connector
20 //
21 // Pin Name Signal Description Pin Name Signal Description
22 // --- ------ ------------------------- --- ------ -------------------------
23 // 1 DIO1 Data Input/Output Bit 1 13 DIO5 Data Input/Output Bit 5
24 // 2 DIO2 Data Input/Output Bit 2 14 DIO6 Data Input/Output Bit 6
25 // 3 DIO3 Data Input/Output Bit 3 15 DIO7 Data Input/Output Bit 7
26 // 4 DIO4 Data Input/Output Bit 4 16 DIO8 Data Input/Output Bit 8
27 // 5 EIO End-Or-Identify 17 REN Remote Enable
28 // 6 DAV Data Valid 18 GND Ground DAV
29 // 7 NRFD Not Ready For Data 19 GND Ground NRFD
30 // 8 NDAC Not Data Accepted 20 GND Ground NDAC
31 // 9 IFC Interface Clear 21 GND Ground IFC
32 // 10 SRQ Service Request 22 GND Ground SRQ
33 // 11 ATN Attention 23 GND Ground ATN
34 // 12 Shield Chassis Ground 24 GND Ground DIO, REN, EOI
35 //
36 // Handshake Output
37 // --------- ---------
38 // NRFD Listener
39 // NDAC Listener
40 // DAV Talker
41 //
42 // Control Output
43 // --------- ---------
44 // ATN Controller
45 // IFC Controller
46 // REN Controller
47 // SRQ Any
48 // EOI Talker and Controller
49 //
50 // Teensy 2.0 has two complete 8-bit ports PB and PD
51 // Arduino Leonardo and "Pro Micro" have 15 out of 16, good try!
52 // 20 mA/pin, 100 mA max for 8-bit port
53 //
54 // 32U4 Arduino GPIB 32U4 Arduino GPIB
55 // ---------- ----- ---- ---------- ----- ----
56 // PB0 (SS) - : DIO1 PD0 (INT0) "d3" : EOI
57 // PB1 (SCLK) "sck" : DIO2 PD1 (INT1) "d2" : NRFD
58 // PB2 (MOSI) "mosi" : DIO3 PD2 (INT2) "rxi" : NDAC
59 // PB3 (MISO) "miso" : DIO4 PD3 (INT3) "txo" : SRQ
60 // PB4 "d8" : DIO5 PD4 "d4" (pull down for arduino)
61 // PB5 "d9" : DIO6 PD5 (LED) (debug serial)
62 // PB6 "d10" : DIO7 PD6 (LED) - -
63 // PB7 - : DIO8 PD7 "d6" : DAV
64 //
65 // Other pins
66 //
67 // 32U4 Arduino GPIB 32U4 Arduino GPIB
68 // ---------- ----- ---- ---------- ----- ----
69 // PF0 (ADC0) - - PC6 "d5" DIO8
70 // PF1 (ADC1) - - PC7 -
71 // PF4 (ADC4) "a3" : ATN PE6 "d7" DIO1
72 // PF5 (ADC5) "a2" : IFC
73 // PF6 (ADC6) "a1" : REN
74 // PF7 (ADC7) "a0" :
75 //
76 // Teensy has LED on PD6 to GND (shared)
77 // Arduino has LED on PD5 to VCC
78 // and on PB0 to VCC (shared with DIO1)
80 #undef DEBUG
82 Queue<GPIBDriver::QUEUE_SIZE> GPIBDriver::CommandQueue;
83 Queue<GPIBDriver::QUEUE_SIZE> GPIBDriver::ReadQueue;
85 uint16_t GPIBDriver::MyAddress;
86 uint16_t GPIBDriver::DeviceAddress;
87 uint16_t GPIBDriver::Timeout;
88 uint8_t GPIBDriver::Byte;
89 bool GPIBDriver::MicroPro;
90 GPIBDriver::State_t GPIBDriver::State;
91 ::Timer GPIBDriver::Timer;
93 GPIBDriver::GPIBDriver()
94 {
95 Initialize();
96 }
98 void GPIBDriver::Initialize()
99 {
100 Float();
101 MyAddress=0;
102 DeviceAddress=1;
103 Timeout=1000; // one second
104 MicroPro=test_bit_clear(PIND,PORTD_TEENSY_N_MP);
105 FloatData();
107 CommandQueue.Clear();
108 ReadQueue.Clear();
109 State=RESET;
110 }
112 // float data bus
113 void GPIBDriver::FloatData()
114 {
115 DDRB=0;
116 PORTB=0xff;
117 if(MicroPro)
118 { clear_bit(DDRE,6);
119 clear_bit(DDRC,6);
120 }
121 }
123 // float all pins
124 void GPIBDriver::Float()
125 {
126 // data lines all inputs
127 FloatData();
129 static const uint8_t used_c=(1<<PORTC_DIO8);
130 DDRC&=0xff^used_c;
131 PORTC=(PORTC&~used_c)|(0xff&used_c);
133 static const uint8_t used_e=(1<<PORTE_DIO1);
134 DDRE&=0xff^used_e;
135 PORTE=(PORTE&~used_e)|(0xff&used_e);
137 // grab all of port D, two outputs
138 DDRD=(1<<PORTD_LED_MP_GREEN) |
139 (1<<PORTD_LED_T);
141 // pull ups, LED off
142 PORTD=(1<<PORTD_EOI) |
143 (1<<PORTD_NDAC) |
144 (1<<PORTD_NRFD) |
145 (1<<PORTD_SRQ) |
146 (1<<PORTD_TEENSY_N_MP) |
147 (1<<PORTD_LED_MP_GREEN) |
148 (1<<PORTD_DAV);
150 // controls, used indicates bits that are used by us
151 static const uint8_t used_f=(1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
152 DDRF&=0xff^used_f;
153 PORTF=(PORTF&~used_f)|(0xff&used_f);
154 }
156 // drive LED
157 void GPIBDriver::LED(bool on)
158 {
159 if(MicroPro)
160 { if(on)
161 clear_bit(PORTD, PORTD_LED_MP_GREEN);
162 else
163 set_bit(PORTD, PORTD_LED_MP_GREEN);
164 }
165 else
166 { if(on)
167 set_bit(PORTD, PORTD_LED_T);
168 else
169 clear_bit(PORTD, PORTD_LED_T);
170 }
171 }
173 // Become controller in charge of the bus
174 //
175 // ++cic
176 // - float all pins
177 // - REN=0
179 void GPIBDriver::Controller()
180 {
181 Float();
183 // start driving ATN IFC and REN
184 PORTF |= (1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
185 DDRF |= (1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN);
187 // pull /REN low to become actice controller
188 REN(true);
189 }
192 uint8_t GPIBDriver::Lines()
193 {
194 uint8_t pd=PIND & ((1<<PORTD_EOI) | (1<<PORTD_NRFD) | (1<<PORTD_NDAC) |
195 (1<<PORTD_SRQ) | (1<<PORTD_DAV));
196 uint8_t pf=PINF & ((1<<PORTF_ATN) | (1<<PORTF_IFC) | (1<<PORTF_REN));
198 return ~(pf | pd);
199 }
201 void GPIBDriver::Report(_ROMS msg)
202 {
203 if(msg)
204 USB<<msg<<':';
205 else
206 USB<<'<';
207 if(DDRB==0)
208 USB<<"i=";
209 else
210 USB<<"o=";
211 USB.Hex(Data());
213 uint8_t lines=Lines();
214 if(lines & (1<<PORTD_EOI)) USB<<ROMS(" EOI");
215 if(lines & (1<<PORTF_ATN)) USB<<ROMS(" ATN");
216 if(lines & (1<<PORTD_SRQ)) USB<<ROMS(" SRQ");
217 if(lines & (1<<PORTF_REN)) USB<<ROMS(" REN");
218 if(lines & (1<<PORTF_IFC)) USB<<ROMS(" IFC");
219 if(lines & (1<<PORTD_NRFD)) USB<<ROMS(" NRFD");
220 if(lines & (1<<PORTD_NDAC)) USB<<ROMS(" NDAC");
221 if(lines & (1<<PORTD_DAV)) USB<<ROMS(" DAV");
223 if(msg)
224 USB<<endl;
225 else
226 USB<<'>';
227 }
229 static const uint32_t TIMEOUT=0x1ff000ULL; // 20 seconds
231 void GPIBDriver::Data(uint8_t byte)
232 {
233 PORTB=~byte;
234 DDRB=SAFER ? byte : 0xff;
235 if(MicroPro)
236 {
237 // disable the LED
238 clear_bit(DDRB,0);
240 // pathetic board does not have an 8-bit port
241 if(byte&1)
242 { clear_bit(PORTE,6);
243 set_bit(DDRE,6);
244 }
245 else
246 { clear_bit(DDRE,6);
247 set_bit(PORTE,6);
248 }
250 if(byte&0x80)
251 { clear_bit(PORTC,6);
252 set_bit(DDRC,6);
253 }
254 else
255 { clear_bit(DDRC,6);
256 set_bit(PORTC,6);
257 }
258 }
259 }
261 uint8_t GPIBDriver::Data()
262 {
263 uint8_t byte=~PINB;
264 if(MicroPro)
265 {
266 // pathetic board does not have an 8-bit port
267 byte &= 0x7e;
268 if(test_bit_clear(PINE,6))
269 byte |= 1;
270 if(test_bit_clear(PINC,6))
271 byte |= 0x80;
272 }
273 return byte;
274 }
276 bool GPIBDriver::Command(uint16_t data)
277 {
278 #ifdef DEBUG
279 USB<<ROMS("Command(");
280 USB.Hex(data);
282 uint16_t d=data&(CMD_SOURCE|CMD_ATN|0xff);
283 if(d>=CMD_SOURCE+32 && d<CMD_SOURCE+127)
284 USB<<'='<<'\''<<char(d)<<'\'';
285 USB<<ROMS(")\r\n");
286 #endif
287 if(data==0)
288 return true;
289 return CommandQueue.Put(data);
290 }
292 uint16_t GPIBDriver::Read()
293 {
294 return ReadQueue.Get();
295 }
297 #ifdef DEBUG
298 GPIBDriver::State_t last=(GPIBDriver::State_t)~0; // debug
299 uint16_t lasttimer=0;
300 #endif
302 int8_t GPIBDriver::Poll()
303 {
304 // tune this so we go round the loop often enough to send/receive one byte
305 for(uint8_t loop=0; loop<7; loop++)
306 {
307 #ifdef DEBUG
308 if(Timer.Read()%128==1 && Timer.Read()!=lasttimer)
309 {
310 last=(GPIBDriver::State_t)~0;
311 lasttimer=Timer.Read();
312 }
314 if(State!=last)
315 {
316 //Report();
317 USB<<ROMS(" state=")<<State<<
318 ROMS(" cq=")<<CommandQueue.Used()<<
319 ROMS(" rq=")<<ReadQueue.Used()<<
320 ROMS(" t=")<<Timer.Read();
321 if(Timer.Timeout())
322 {
323 USB<<ROMS(" TO");
324 }
325 USB<<endl;
326 last=State;
327 }
328 #endif
330 switch(State)
331 {
332 case RESET:
333 Float();
334 Timer.Clear();
335 CommandQueue.Clear();
336 State=IDLE;
337 return 0;
339 case IDLE:
340 { uint16_t data=CommandQueue.Peek();
342 #ifdef DEBUG
343 if(data)
344 {
345 USB<<ROMS("data=");
346 USB.Hex(data);
347 USB<<endl;
348 }
349 #endif
351 switch(data & CMD_MASK)
352 { case 0:
353 return 0; // idle
354 case CMD_SOURCE:
355 State=SH_START;
356 break;
357 case CMD_ACCEPT:
358 State=AH_START;
359 break;
360 case CMD_CONTROLLER:
361 State=CAC_START;
362 break;
363 case CMD_SIC:
364 State=SIC_START;
365 break;
366 case CMD_RELEASE:
367 Float();
368 State=IDLE;
369 break;
370 default:
371 // drop unknown command
372 CommandQueue.Get();
373 return EINTERN; // internal error
374 }
375 } break;
378 /* ..... source handshake ................................................... */
380 case SH_START:
381 { uint16_t data=CommandQueue.Peek();
382 ATN(data&CMD_ATN);
383 DAV(false);
385 // settling delay
386 _delay_us(2);
388 if(!NRFD() && !NDAC())
389 { State=RESET;
390 return EACPROT; // acceptor protocol error
391 }
392 State=SH_DATA;
393 } break;
395 case SH_DATA:
396 { // remove command from the queue
397 uint16_t data=CommandQueue.Get();
399 // drive data
400 EOI(data&CMD_EOI);
401 Data(data);
403 // settling delay
404 _delay_us(2);
406 // start timer default
407 Timer.Single(Timeout);
409 State=SH_WAIT_NRFD;
410 } break;
412 case SH_WAIT_NRFD:
413 if(!NRFD())
414 State=SH_DAV;
415 else if(Timer.Timeout())
416 { State=RESET;
417 return EACTMO; // acceptor timeout
418 }
419 break;
421 case SH_DAV:
422 DAV(true);
424 // start timer default
425 Timer.Single(Timeout);
427 State=SH_WAIT_NDAC;
428 break;
430 case SH_WAIT_NDAC:
431 if(!NDAC())
432 State=SH_N_DAV;
433 else if(Timer.Timeout())
434 { State=RESET;
435 return EACTMO; // acceptor timeout
436 }
437 break;
439 case SH_N_DAV:
440 DAV(false);
441 EOI(false);
442 FloatData();
443 State=IDLE;
444 break;
447 /* ..... acceptor handshake ................................................. */
449 case AH_START:
450 { uint16_t cmd=CommandQueue.Peek();
451 Byte=cmd;
453 NDAC(true);
455 if(ATN())
456 { // settling delay
457 _delay_us(1);
458 State=AH_N_ATN;
459 }
460 else
461 State=AH_READY;
462 } break;
464 case AH_N_ATN:
465 // negate ATN
466 ATN(false);
467 State=AH_READY;
468 break;
470 case AH_READY:
471 { uint16_t cmd=CommandQueue.Peek();
473 // ready for data
474 NRFD(false);
476 // start timer
477 Timer.Single(cmd&CMD_AC_QUICK ? 100 : Timeout);
479 State=AH_WAIT_DAV;
480 } break;
482 case AH_WAIT_DAV:
483 if(DAV())
484 State=AH_NRFD;
485 else if(Timer.Timeout())
486 { uint16_t cmd=CommandQueue.Get();
487 if(cmd&CMD_AC_QUICK)
488 { NDAC(false);
489 State=IDLE;
490 return 0;
491 }
492 else
493 { State=RESET;
494 return ESRCTMO; // source timeout
495 }
496 }
497 break;
499 case AH_NRFD:
500 { NRFD(true);
502 uint16_t cmd=CommandQueue.Peek();
503 uint8_t eoi=EOI();
505 uint16_t data=CMD_ACCEPT | Data();
506 if(ATN())
507 data|=CMD_ATN;
508 if(eoi)
509 data|=CMD_EOI;
511 #ifdef DEBUG
512 USB<<ROMS("data=");
513 USB.Hex(data);
514 if((data&0xff)>=32 && (data&0xff)<127)
515 { USB<<'='<<'\''<<char(data)<<'\'';
516 }
517 USB<<endl;
518 #endif
520 bool last;
522 switch(cmd & CMD_AC_MASK)
523 {
524 case CMD_AC_EOI:
525 last=eoi; // EOI on byte
526 break;
528 case CMD_AC_BYTE:
529 last=(Byte==(data & 0xff)); // byte match
530 break;
532 case CMD_AC_COUNT:
533 last=--Byte==0; // counter
534 break;
536 default:
537 last=false; // forever/until timeout
538 break;
539 }
541 if(ReadQueue.Put(data))
542 State=last ? AH_N_NDAC_LAST : AH_N_NDAC;
543 else if(Timer.Timeout())
544 { State=last ? AH_WAIT_NDAV_LAST : AH_WAIT_NDAV;
545 return EFULL; // timeout on read queue
546 }
547 else
548 return 0;
549 } break;
551 case AH_N_NDAC:
552 NDAC(false);
553 State=AH_WAIT_NDAV;
554 break;
556 case AH_WAIT_NDAV:
557 if(!DAV())
558 State=AH_NDAC;
559 else if(Timer.Timeout())
560 { State=RESET;
561 return ESRCTMO; // source timeout
562 }
563 break;
565 case AH_NDAC:
566 NDAC(true);
567 State=AH_READY;
568 break;
570 case AH_N_NDAC_LAST:
571 NDAC(false);
572 State=AH_WAIT_NDAV_LAST;
573 break;
575 case AH_WAIT_NDAV_LAST:
576 if(!DAV())
577 { CommandQueue.Get(); // remove command from queue
578 State=IDLE;
579 }
580 else if(Timer.Timeout())
581 { State=RESET;
582 return ESRCTMO; // source timeout
583 }
584 break;
587 /* ..... take control ....................................................... */
589 case CAC_START:
590 ATN(false);
591 EOI(false);
592 NRFD(false);
593 DAV(false);
594 NDAC(false);
596 if(CommandQueue.Get()&CMD_CTRL_FORCE)
597 State=CAC_COMPLETE;
598 else
599 {
600 Timer.Single(Timeout);
601 State=CAC_WAIT;
602 }
603 break;
605 case CAC_WAIT:
606 if(!(GPIB.ATN() || GPIB.NRFD() || GPIB.NDAC() || GPIB.DAV()))
607 State=CAC_COMPLETE;
608 else if(Timer.Timeout())
609 { State=RESET;
610 return ECTRLTMO; // controller timeout
611 }
612 break;
614 case CAC_COMPLETE:
615 Controller();
616 State=IDLE;
617 break;
620 /* ..... send interface clear ............................................... */
622 case SIC_START:
623 CommandQueue.Get();
624 GPIB.IFC(true);
625 Timer.Single(Timeout);
626 State=SIC_WAIT;
627 break;
629 case SIC_WAIT:
630 if(!(GPIB.DAV() || GPIB.NRFD() || GPIB.NDAC()))
631 State=SIC_COMPLETE;
632 else if(Timer.Timeout())
633 { State=SIC_COMPLETE;
634 return ECTRLTMO; // controller timeout
635 }
636 break;
638 case SIC_COMPLETE:
639 GPIB.IFC(false);
640 State=IDLE;
641 break;
644 /* ..... parallel poll ...................................................... */
646 case PP_START:
647 GPIB.ATN(true);
648 GPIB.EOI(true);
649 // settling delay
650 _delay_us(1);
651 State=PP_COMPLETE;
652 break;
654 case PP_COMPLETE:
655 { uint16_t data;
657 data=CMD_PARPOLL | Data();
658 GPIB.ATN(false);
659 GPIB.EOI(false);
660 State=IDLE;
662 if(!ReadQueue.Put(data))
663 return EFULL; // timeout on read queue
665 } break;
667 /* .......................................................................... */
669 default:
670 State=RESET;
671 return EINTERN; // internal error
672 }
673 }
674 return 0;
675 }
677 /* ========================================================================== */
679 const GPIBDriver __attribute__((__progmem__)) GPIB;
681 //
683 // GPIB System Concepts
684 // ====================
685 // ______________________
686 // ATN_________________________ATN___/ ATN
687 //
688 // ______ _________ ________ ________
689 // DAV \________/ DAV \________/ DAV
690 //
691 // _____ _____ __________ ____
692 // NRFD__/ \_________/ NRFD \_________/ NRFD
693 //
694 // _____ _____
695 // NDAC__________/ \_______NDAC____________/ \______NDAC
696 //
697 // ________________ ___________________
698 // DATA---<________________>---DATA--<___________________>--DATA
699 //
700 //
701 // TNT4882 Manual
702 // ==============
703 // __________________________
704 // ATN___/ ATN
705 //
706 // ___________ _________
707 // DAV \________/ DAV
708 //
709 // ________ ___
710 // NRFD_____/ \__________/ NRFD
711 //
712 // _____
713 // NDAC________________/ \______NDAC
714 //
715 // ___________________
716 // DATA--------<___________________>--DATA
717 //
719 /* ----- EOF gpib.cc ----- */