1use crate::error::GpibError;
2use std::fmt;
3use std::os::raw::{c_int, c_short};
4
5pub enum IbOption {
6 PAD,
7 SAD,
8 TMO,
9 EOT,
10 PPC,
11 READDR,
12 AUTOPOLL,
13 CICPROT,
14 SC,
15 SRE,
16 EOSrd,
17 EOSwrt,
18 EOScmp,
19 EOSchar,
20 PP2,
21 TIMING,
22 ReadAdjust,
23 WriteAdjust,
24 EventQueue,
25 SPollBit,
26 SendLLO,
27 SPollTime,
28 PPollTime,
29 EndBitIsNormal,
30 UnAddr,
31 HSCableLength,
32 Ist,
33 Rsv,
34 BNA,
35 SevenBitEOS,
36}
37
38impl fmt::Display for IbOption {
39 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
40 match self {
41 IbOption::PAD => {
42 write!(f, "IbOption::PAD")
43 }
44 IbOption::SAD => {
45 write!(f, "IbOption::SAD")
46 }
47 IbOption::TMO => {
48 write!(f, "IbOption::TMO")
49 }
50 IbOption::EOT => {
51 write!(f, "IbOption::EOT")
52 }
53 IbOption::PPC => {
54 write!(f, "IbOption::PPC")
55 }
56 IbOption::READDR => {
57 write!(f, "IbOption::READDR")
58 }
59 IbOption::AUTOPOLL => {
60 write!(f, "IbOption::AUTOPOLL")
61 }
62 IbOption::CICPROT => {
63 write!(f, "IbOption::CICPROT")
64 }
65 IbOption::SC => {
66 write!(f, "IbOption::SC")
67 }
68 IbOption::SRE => {
69 write!(f, "IbOption::SRE")
70 }
71 IbOption::EOSrd => {
72 write!(f, "IbOption::EOSrd")
73 }
74 IbOption::EOSwrt => {
75 write!(f, "IbOption::EOSwrt")
76 }
77 IbOption::EOScmp => {
78 write!(f, "IbOption::EOScmp")
79 }
80 IbOption::EOSchar => {
81 write!(f, "IbOption::EOSchar")
82 }
83 IbOption::PP2 => {
84 write!(f, "IbOption::PP2")
85 }
86 IbOption::TIMING => {
87 write!(f, "IbOption::TIMING")
88 }
89 IbOption::ReadAdjust => {
90 write!(f, "IbOption::ReadAdjust")
91 }
92 IbOption::WriteAdjust => {
93 write!(f, "IbOption::WriteAdjust")
94 }
95 IbOption::EventQueue => {
96 write!(f, "IbOption::EventQueue")
97 }
98 IbOption::SPollBit => {
99 write!(f, "IbOption::SPollBit")
100 }
101 IbOption::SendLLO => {
102 write!(f, "IbOption::SendLLO")
103 }
104 IbOption::SPollTime => {
105 write!(f, "IbOption::SPollTime")
106 }
107 IbOption::PPollTime => {
108 write!(f, "IbOption::PPollTime")
109 }
110 IbOption::EndBitIsNormal => {
111 write!(f, "IbOption::EndBitIsNormal")
112 }
113 IbOption::UnAddr => {
114 write!(f, "IbOption::UnAddr")
115 }
116 IbOption::HSCableLength => {
117 write!(f, "IbOption::HSCableLength")
118 }
119 IbOption::Ist => {
120 write!(f, "IbOption::Ist")
121 }
122 IbOption::Rsv => {
123 write!(f, "IbOption::Rsv")
124 }
125 IbOption::BNA => {
126 write!(f, "IbOption::BNA")
127 }
128 IbOption::SevenBitEOS => {
129 write!(f, "IbOption::SevenBitEOS")
130 }
131 }
132 }
133}
134
135impl fmt::Debug for IbOption {
136 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
137 match self {
138 IbOption::PAD => {
139 write!(f, "IbOption::PAD (0x1): GPIB primary address")
140 }
141 IbOption::SAD => {
142 write!(
143 f,
144 "IbOption::SAD (0x2): GPIB secondary address (0 for none, 0x60 to 0x7e for secondary addresses 0 to 30)"
145 )
146 }
147 IbOption::TMO => {
148 write!(
149 f,
150 "IbOption::TMO (0x3): Timeout setting for io operations (a number from 0 to 17). See ibmto()."
151 )
152 }
153 IbOption::EOT => {
154 write!(
155 f,
156 "IbOption::EOT (0x4): Nonzero if EOI is asserted with last byte on writes. See ibeot()."
157 )
158 }
159 IbOption::PPC => {
160 write!(
161 f,
162 "IbOption::PPC (0x5): Parallel poll configuration. See ibppc()."
163 )
164 }
165 IbOption::READDR => {
166 write!(
167 f,
168 "IbOption::READDR (0x6): Useless, included for compatibility only."
169 )
170 }
171 IbOption::AUTOPOLL => {
172 write!(
173 f,
174 "IbOption::AUTOPOLL (0x7): Nonzero if automatic serial polling is enabled."
175 )
176 }
177 IbOption::CICPROT => {
178 write!(
179 f,
180 "IbOption::CICPROT (0x8): Useless, included for compatibility only."
181 )
182 }
183 IbOption::SC => {
184 write!(
185 f,
186 "IbOption::SC (0xa): Nonzero if board is system controller. See ibrsc(). "
187 )
188 }
189 IbOption::SRE => {
190 write!(
191 f,
192 "IbOption::SRE (0xb): Nonzero if board autmatically asserts REN line when it becomes the system controller. See ibsre()."
193 )
194 }
195 IbOption::EOSrd => {
196 write!(
197 f,
198 "IbOption::EOSrd (0xc): Nonzero if termination of reads on reception of the end-of-string character is enabled. See ibeos(), in particular the REOS bit."
199 )
200 }
201 IbOption::EOSwrt => {
202 write!(
203 f,
204 "IbOption::EOSwrt (0xd): Nonzero if EOI is asserted whenever end-of-string character is sent. See ibeos(), in particular the XEOS bit."
205 )
206 }
207 IbOption::EOScmp => {
208 write!(
209 f,
210 "IbOption::EOScmp (0xe): Nonzero if all 8 bits are used to match end-of-string character. Zero if only least significant 7 bits are used. See ibeos(), in particular the BIN bit."
211 )
212 }
213 IbOption::EOSchar => {
214 write!(f, "IbOption::EOSchar (0xf): The end-of-string byte.")
215 }
216 IbOption::PP2 => {
217 write!(
218 f,
219 "IbOption::PP2 (0x10): Nonzero if in local parallel poll configure mode. Zero if in remote parallel poll configure mode."
220 )
221 }
222 IbOption::TIMING => {
223 write!(
224 f,
225 "IbOption::TIMING (0x11): Number indicating T1 delay. 1 for 2 microseconds, 2 for 500 nanoseconds, 3 for 350 nanoseconds. The values are declared in the header files as the constants T1_DELAY_2000ns, T1_DELAY_500ns, and T1_DELAY_350ns."
226 )
227 }
228 IbOption::ReadAdjust => {
229 write!(
230 f,
231 "IbOption::ReadAdjust (0x13): Nonzero if byte pairs are automatically swapped during reads."
232 )
233 }
234 IbOption::WriteAdjust => {
235 write!(
236 f,
237 "IbOption::WriteAdjust (0x14): Nonzero if byte pairs are automatically swapped during writes."
238 )
239 }
240 IbOption::EventQueue => {
241 write!(
242 f,
243 "IbOption::EventQueue (0x15): Nonzero if event queue is enabled."
244 )
245 }
246 IbOption::SPollBit => {
247 write!(
248 f,
249 "IbOption::SPollBit (0x16): Nonzero if the use of the SPOLL bit in ibsta is enabled."
250 )
251 }
252 IbOption::SendLLO => {
253 write!(
254 f,
255 "IbOption::SendLLO (0x17): Nonzero if devices connected to this board are automatically put into local lockout mode when brought online with ibfind() or ibdev()."
256 )
257 }
258 IbOption::SPollTime => {
259 write!(
260 f,
261 "IbOption::SPollTime (0x18): Timeout for serial polls. The value of the result is between 0 and 17, and has the same meaning as in ibtmo()."
262 )
263 }
264 IbOption::PPollTime => {
265 write!(
266 f,
267 "IbOption::PPollTime (0x19): Timeout for parallel polls. The value of the result is between 0 and 17, and has the same meaning as in ibtmo()."
268 )
269 }
270 IbOption::EndBitIsNormal => {
271 write!(
272 f,
273 "IbOption::EndBitIsNormal (0x1a): Nonzero if END bit of ibsta is set on reception of end-of-string character or EOI. Zero if END bit is only set on EOI."
274 )
275 }
276 IbOption::UnAddr => {
277 write!(
278 f,
279 "IbOption::UnAddr (0x1b): Nonzero if UNT (untalk) and UNL (unlisten) commands are automatically sent after a completed io operation using this descriptor."
280 )
281 }
282 IbOption::HSCableLength => {
283 write!(
284 f,
285 "IbOption::HSCableLength (0x1f): Useless, included only for compatibility."
286 )
287 }
288 IbOption::Ist => {
289 write!(
290 f,
291 "IbOption::Ist (0x20): Individual status bit, a.k.a. 'ist'."
292 )
293 }
294 IbOption::Rsv => {
295 write!(
296 f,
297 "IbOption::Rsv (0x21): The current status byte this board will use to respond to serial polls."
298 )
299 }
300 IbOption::BNA => {
301 write!(
302 f,
303 "IbOption::BNA (0x200): For a device: the board index (minor number) of interface board through which the device is being accessed. For a board: the board index of the board itself."
304 )
305 }
306 IbOption::SevenBitEOS => {
307 write!(
308 f,
309 "IbOption::SevenBitEOS (0x1000): Nonzero if board supports 7 bit EOS comparisons. See ibeos(), in particular the BIN bit. This is a Linux-GPIB extension."
310 )
311 }
312 }
313 }
314}
315
316impl IbOption {
317 pub fn as_option(&self) -> c_int {
318 match self {
319 IbOption::PAD => 0x1,
320 IbOption::SAD => 0x2,
321 IbOption::TMO => 0x3,
322 IbOption::EOT => 0x4,
323 IbOption::PPC => 0x5,
324 IbOption::READDR => 0x6,
325 IbOption::AUTOPOLL => 0x7,
326 IbOption::CICPROT => 0x8,
327 IbOption::SC => 0xa,
328 IbOption::SRE => 0xb,
329 IbOption::EOSrd => 0xc,
330 IbOption::EOSwrt => 0xd,
331 IbOption::EOScmp => 0xe,
332 IbOption::EOSchar => 0xf,
333 IbOption::PP2 => 0x10,
334 IbOption::TIMING => 0x11,
335 IbOption::ReadAdjust => 0x13,
336 IbOption::WriteAdjust => 0x14,
337 IbOption::EventQueue => 0x15,
338 IbOption::SPollBit => 0x16,
339 IbOption::SendLLO => 0x17,
340 IbOption::SPollTime => 0x18,
341 IbOption::PPollTime => 0x19,
342 IbOption::EndBitIsNormal => 0x1a,
343 IbOption::UnAddr => 0x1b,
344 IbOption::HSCableLength => 0x1f,
345 IbOption::Ist => 0x20,
346 IbOption::Rsv => 0x21,
347 IbOption::BNA => 0x200,
348 IbOption::SevenBitEOS => 0x1000,
349 }
350 }
351}
352
353#[derive(Clone, Copy)]
354pub enum IbTimeout {
355 TNone,
356 T10us,
357 T30us,
358 T100us,
359 T300us,
360 T1ms,
361 T3ms,
362 T10ms,
363 T30ms,
364 T100ms,
365 T300ms,
366 T1s,
367 T3s,
368 T10s,
369 T30s,
370 T100s,
371 T300s,
372 T1000s,
373}
374
375impl fmt::Display for IbTimeout {
376 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
377 match self {
378 IbTimeout::TNone => {
379 write!(f, "Never timeout")
380 }
381 IbTimeout::T10us => {
382 write!(f, "10 microseconds")
383 }
384 IbTimeout::T30us => {
385 write!(f, "30 microseconds")
386 }
387 IbTimeout::T100us => {
388 write!(f, "100 microseconds")
389 }
390 IbTimeout::T300us => {
391 write!(f, "300 microseconds")
392 }
393 IbTimeout::T1ms => {
394 write!(f, "1 millisecond")
395 }
396 IbTimeout::T3ms => {
397 write!(f, "3 milliseconds")
398 }
399 IbTimeout::T10ms => {
400 write!(f, "10 milliseconds")
401 }
402 IbTimeout::T30ms => {
403 write!(f, "30 milliseconds")
404 }
405 IbTimeout::T100ms => {
406 write!(f, "100 milliseconds")
407 }
408 IbTimeout::T300ms => {
409 write!(f, "300 milliseconds")
410 }
411 IbTimeout::T1s => {
412 write!(f, "1 second")
413 }
414 IbTimeout::T3s => {
415 write!(f, "3 seconds")
416 }
417 IbTimeout::T10s => {
418 write!(f, "10 seconds")
419 }
420 IbTimeout::T30s => {
421 write!(f, "30 seconds")
422 }
423 IbTimeout::T100s => {
424 write!(f, "100 seconds")
425 }
426 IbTimeout::T300s => {
427 write!(f, "300 seconds")
428 }
429 IbTimeout::T1000s => {
430 write!(f, "1000 seconds")
431 }
432 }
433 }
434}
435
436impl IbTimeout {
437 pub(crate) fn as_timeout(&self) -> c_int {
438 match self {
439 IbTimeout::TNone => 0,
440 IbTimeout::T10us => 1,
441 IbTimeout::T30us => 2,
442 IbTimeout::T100us => 3,
443 IbTimeout::T300us => 4,
444 IbTimeout::T1ms => 5,
445 IbTimeout::T3ms => 6,
446 IbTimeout::T10ms => 7,
447 IbTimeout::T30ms => 8,
448 IbTimeout::T100ms => 9,
449 IbTimeout::T300ms => 10,
450 IbTimeout::T1s => 11,
451 IbTimeout::T3s => 12,
452 IbTimeout::T10s => 13,
453 IbTimeout::T30s => 14,
454 IbTimeout::T100s => 15,
455 IbTimeout::T300s => 16,
456 IbTimeout::T1000s => 17,
457 }
458 }
459}
460
461#[derive(Copy, Clone)]
462pub struct PrimaryAddress {
463 pad: c_int,
464}
465
466impl PrimaryAddress {
467 pub fn new(pad: c_int) -> Result<PrimaryAddress, GpibError> {
468 if pad >= 0 && pad <= 30 {
469 Ok(PrimaryAddress { pad })
470 } else {
471 Err(GpibError::ValueError(format!(
472 "Primary address must be between 0 and 30. Got: {}.",
473 pad
474 )))
475 }
476 }
477
478 pub(crate) fn as_pad(&self) -> c_int {
479 self.pad
480 }
481}
482
483impl fmt::Display for PrimaryAddress {
484 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
485 write!(f, "{}", self.pad)
486 }
487}
488
489#[derive(Copy, Clone)]
490pub struct SecondaryAddress {
491 sad: c_int,
492}
493
494impl SecondaryAddress {
495 pub fn new(sad: c_int) -> Result<SecondaryAddress, GpibError> {
496 let desc = "Secondary address must be between 0 and 30 (without the 0x60 prefix), or equivalently between 0x60 and 0x7e (with the 0x60 addition). sad = 0 disables secondary address.";
497 let sad = if sad < 0 {
498 return Err(GpibError::ValueError(desc.to_owned()));
499 } else if sad == 0 {
500 sad
502 } else if sad <= 30 {
503 sad + 0x60
506 } else if sad >= 0x60 && sad <= 0x7e {
507 sad
508 } else {
509 return Err(GpibError::ValueError(desc.to_owned()));
510 };
511 Ok(SecondaryAddress { sad })
512 }
513
514 pub(crate) fn as_sad(&self) -> c_int {
515 self.sad
516 }
517}
518
519impl Default for SecondaryAddress {
520 fn default() -> SecondaryAddress {
521 SecondaryAddress { sad: 0 }
522 }
523}
524
525impl fmt::Display for SecondaryAddress {
526 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
527 write!(f, "{}", self.sad)
528 }
529}
530
531#[derive(Copy, Clone)]
532pub enum IbSendEOI {
533 Disabled,
534 Enabled(c_int),
535}
536
537impl IbSendEOI {
538 pub(crate) fn as_eot(&self) -> c_int {
539 match self {
540 IbSendEOI::Disabled => 0,
541 IbSendEOI::Enabled(val) => *val,
542 }
543 }
544}
545
546impl Default for IbSendEOI {
547 fn default() -> IbSendEOI {
548 IbSendEOI::Disabled
549 }
550}
551
552impl fmt::Display for IbSendEOI {
553 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
554 match self {
555 IbSendEOI::Disabled => {
556 write!(f, "IbSendEOI::Disabled")
557 }
558 IbSendEOI::Enabled(value) => {
559 write!(f, "IbSendEOI::Enabled({})", value)
560 }
561 }
562 }
563}
564
565#[derive(Copy, Clone)]
566pub struct IbEosMode {
567 pub reos: bool,
568 pub xeos: bool,
569 pub bin: bool,
570}
571
572impl fmt::Display for IbEosMode {
573 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
574 let mut description = String::new();
575 if self.reos {
576 description.push_str("REOS ");
577 }
578 if self.xeos {
579 description.push_str("XEOS ");
580 }
581 if self.bin {
582 description.push_str("BIN");
583 }
584 if description.len() > 0 {
585 write!(f, "EosMod({description})")
586 } else {
587 write!(f, "EosMod(No flag set)")
588 }
589 }
590}
591
592impl fmt::Debug for IbEosMode {
593 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
594 let mut description = String::new();
595 if self.reos {
596 description.push_str(
597 "REOS (0x400) Enable termination of reads when eos character is received.",
598 );
599 }
600 if self.xeos {
601 description.push_str("XEOS (0x800) Assert the EOI line whenever the eos character is sent during writes.");
602 }
603 if self.bin {
604 description.push_str("BIN (0x1000) Match eos character using all 8 bits (instead of only looking at the 7 least significant bits).");
605 }
606 if description.len() > 0 {
607 write!(f, "EosMod({description})")
608 } else {
609 write!(f, "EosMod(No flag set)")
610 }
611 }
612}
613
614impl IbEosMode {
615 pub fn as_mode(&self) -> c_int {
616 let mut mode = 0;
617 if self.reos {
618 mode = mode | 0x400;
619 }
620 if self.xeos {
621 mode = mode | 0x800;
622 }
623 if self.bin {
624 mode = mode | 0x1000;
625 }
626 mode
627 }
628}
629
630impl Default for IbEosMode {
631 fn default() -> IbEosMode {
632 IbEosMode {
633 reos: true,
634 xeos: false,
635 bin: false,
636 }
637 }
638}
639
640pub enum IbEvent {
641 None,
642 DevTrg,
643 DevClr,
644 IFC,
645}
646
647impl fmt::Display for IbEvent {
648 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
649 match self {
650 IbEvent::None => {
651 write!(f, "None")
652 }
653 IbEvent::DevTrg => {
654 write!(f, "DevTrg")
655 }
656 IbEvent::DevClr => {
657 write!(f, "DevClr")
658 }
659 IbEvent::IFC => {
660 write!(f, "IFC")
661 }
662 }
663 }
664}
665
666impl fmt::Debug for IbEvent {
667 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
668 match self {
669 IbEvent::None => {
670 write!(f, "None (The board's event queue is empty)")
671 }
672 IbEvent::DevTrg => {
673 write!(
674 f,
675 "DevTrg (The board has received a trigger command from the controller-in-charge)"
676 )
677 }
678 IbEvent::DevClr => {
679 write!(
680 f,
681 "DevClr (The board has received a clear command from the controller-in-charge)"
682 )
683 }
684 IbEvent::IFC => {
685 write!(
686 f,
687 "IFC (The board has received an interface clear from the system controller. Note, some models of GPIB interface board lack the ability to report interface clear events)"
688 )
689 }
690 }
691 }
692}
693
694impl IbEvent {
695 pub(crate) fn from_value(value: c_short) -> Result<IbEvent, GpibError> {
696 match value {
697 0 => Ok(IbEvent::None),
698 1 => Ok(IbEvent::DevTrg),
699 2 => Ok(IbEvent::DevClr),
700 3 => Ok(IbEvent::IFC),
701 other => Err(GpibError::ValueError(format!(
702 "Unexpected value ({}) for event.",
703 other,
704 ))),
705 }
706 }
707}
708
709pub struct IbLineStatus {
710 pub valid_dav: bool,
711 pub valid_ndac: bool,
712 pub valid_nrfd: bool,
713 pub valid_ifc: bool,
714 pub valid_ren: bool,
715 pub valid_srq: bool,
716 pub valid_atn: bool,
717 pub valid_eoi: bool,
718 pub bus_dav: bool,
719 pub bus_ndac: bool,
720 pub bus_nrfd: bool,
721 pub bus_ifc: bool,
722 pub bus_ren: bool,
723 pub bus_srq: bool,
724 pub bus_atn: bool,
725 pub bus_eoi: bool,
726}
727
728impl IbLineStatus {
729 pub(crate) fn from_line_status(line_status: c_short) -> IbLineStatus {
730 let valid_dav = (line_status & 0x1) != 0;
731 let valid_ndac = (line_status & 0x2) != 0;
732 let valid_nrfd = (line_status & 0x4) != 0;
733 let valid_ifc = (line_status & 0x8) != 0;
734 let valid_ren = (line_status & 0x10) != 0;
735 let valid_srq = (line_status & 0x20) != 0;
736 let valid_atn = (line_status & 0x40) != 0;
737 let valid_eoi = (line_status & 0x80) != 0;
738 let bus_dav = (line_status & 0x100) != 0;
739 let bus_ndac = (line_status & 0x200) != 0;
740 let bus_nrfd = (line_status & 0x400) != 0;
741 let bus_ifc = (line_status & 0x800) != 0;
742 let bus_ren = (line_status & 0x1000) != 0;
743 let bus_srq = (line_status & 0x2000) != 0;
744 let bus_atn = (line_status & 0x4000) != 0;
745 let bus_eoi = (line_status & 0x8000u16 as i16) != 0;
746 Self {
747 valid_dav,
748 valid_ndac,
749 valid_nrfd,
750 valid_ifc,
751 valid_ren,
752 valid_srq,
753 valid_atn,
754 valid_eoi,
755 bus_dav,
756 bus_ndac,
757 bus_nrfd,
758 bus_ifc,
759 bus_ren,
760 bus_srq,
761 bus_atn,
762 bus_eoi,
763 }
764 }
765}
766
767pub enum IbOnline {
768 Close,
769 Reset(c_int),
770}
771
772impl IbOnline {
773 pub(crate) fn as_online(&self) -> c_int {
774 match self {
775 IbOnline::Close => 0,
776 IbOnline::Reset(val) => *val,
777 }
778 }
779}
780
781impl fmt::Display for IbOnline {
782 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
783 match self {
784 IbOnline::Close => {
785 write!(f, "IbOnline::Close")
786 }
787 IbOnline::Reset(val) => {
788 write!(f, "IbOnline::Reset({})", val)
789 }
790 }
791 }
792}