Skip to content

Commit 7be0a6f

Browse files
committed
Release of FW version 2.0
Changes: - fix autoid slower and autoid slowest options - Implement USBTMC compliant method to set read termination method - Made pulse indicator request function work asynchronous See README.MD for more details.
1 parent 1acb081 commit 7be0a6f

File tree

14 files changed

+160
-80
lines changed

14 files changed

+160
-80
lines changed

HW/REV2/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ As a next step insert the PCB into the big part of the housing again. It has a r
6262

6363
Then put the smaller part of the housing on top of it, insert the screws (they can be pushed hard to destroy the "membrane" first time) and nuts and screw it together.
6464

65-
Voilà... your adapter is finished and ready to use :-)
65+
Voilà.. your adapter is finished and ready to use :-)
6666

6767
<img src="https://raw.githubusercontent.com/xyphro/UsbGpib/master/pictures/Upcoming_Rev2.png" width="80%"/>
6868

README.md

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,11 @@ Versatile, cheap, portable and robust USB to GPIB converter (USBTMC class based)
33

44
You'll find many projects like this, but this one is special (ok, everybody will claim this) :-)
55

6-
<img src="https://raw.githubusercontent.com/xyphro/UsbGpib/master/pictures/UsbGPIB.jpg" width="80%"/>
6+
V1 Hardware:
7+
<img src="https://raw.githubusercontent.com/xyphro/UsbGpib/master/pictures/UsbGPIB.jpg" width="50%"/>
8+
9+
V2 Hardware:
10+
<img src="https://raw.githubusercontent.com/xyphro/UsbGpib/master/pictures/Upcoming_Rev2.png" width="50%"/>
711

812
If you have a lot of test equipment at home, you might know the issues: Lots of devices only have GPIB as interface and the GPIB adapters and GPIB cables on the market are very expensive and some of them even have many issues, when run under Windows 10 (device driver does not work). Or they e.g. are not able to be operated with VISA, because they are UART based, need special command sequences, ...
913

@@ -29,9 +33,26 @@ Some goals of the project were:
2933

3034
All those goals are met.
3135

36+
# 21st April '25 update
37+
38+
Today it's time for another release - version V2.0.
39+
40+
While writing this and looking at this readme.md file, I certainly think that I should clean it up in future - it is not well structured for new users. Sorry for this, but I have this on my radar and will improve. Whenever I have more time I will also extend it with usage examples / small "trainings", especially for those who are completely new to GPIB and controlling instruments.
41+
42+
I had btw. some occasions where users had issues flashing the device. Many of them were caused by the fact that the .hex and .bin files were saved over the GitHub web interface by rightclicking and selecting "Save as". This will result in a HTML page being saved which will not flash well :-)
43+
The safest option is to do a git clone or to download this whole github repository as .zip file.
44+
45+
Here the release V2.0 details:
46+
- **Bugfix:** the options autoid slower and autoid slowest did not work. This is addressed and I test those settings now also properly in release testing, promised :-) The issue was caused in my super slim parser implementation for custom internal commands and "autoid slow" and "autoid slower" start with the same letters causing hickups.
47+
The Windows GUI is also updated to expose those 2 autoid settings - they were not included before.
48+
As general good recommendation, I still recommend to turn autoid feature off, as it limits the measurement instruments which are used - Instruments HAVE to support *IDN? query for it to work well, which is for many old equipment not the case and for such old equipment errors will be flagged after the instrument is turned on.
49+
- **New feature:** I enabled a new method to set the READ termination. One that is fully compliant with usbtmc standard and does not need a workaround with pulse indicator requests. I don't know why I did not spot this earlier, but a discussion with the usbtmc linux kernel mode driver maintainer exposed this to me. When using direct access to usbtmc kernel mode driver you can use the <a href="https://github.com/dpenkler/linux-usbtmc?tab=readme-ov-file#ioctl-to-control-setting-eom-bit" target="_blank">USBTMC_IOCTL_EOM_ENABLE</a> IOCTL to set the read termination. When using a VISA layer, you can set the read termination by setting the VI_ATTR_TERMCHAR_EN and VI_ATTR_TERMCHAR attributes (see below for more details).
50+
The previous method of setting read termination is not modified in any way, this just gives an additional method to set the readtermination.
51+
- **Bugfix / Improvement:** The pulse indicator request function did use a blocking delay to pulse the LED. This delayed USB side handling. In some cases this could trigger timeouts. The LED blinking is now handled fully asynchronous and those timeouts will not occur anymore.
52+
3253
# 6th April '25 update
3354

34-
time to release a bugfix (reported by rapgenic #80): V1.9 of the firmware fixes an issue where the "autoid slow" setting was not applied properly.
55+
Time to release a bugfix (reported by rapgenic #80): V1.9 of the firmware fixes an issue where the "autoid slow" setting was not applied properly.
3556

3657
# 12th January '25 update
3758

@@ -244,7 +265,10 @@ Don't add extra spaces or make other modifications or concatenate commands.
244265

245266
While most GPIB interfaces use the hardware signal EOI to signal the end of a message, not all old equipment supports it. Some older instruments even don't have the EOI pin hardware wise wired and use \r or \n termination.
246267

247-
The following commands are available:
268+
The USB-TMC standard allows to set the read termination. While in firmware versions before < 2.0 I did not enable that method, it is now finally supported with standard compliance.
269+
270+
I document here the older method (using pulse indicator request), but I add also the newer methods. You can choose which ones to use, but in some cases pulse indicator requests can be difficult to issue, for which reason it is likely better to use the standard compliant method.
271+
248272

249273
### Set read termination to CR (\r):
250274
```
@@ -253,20 +277,38 @@ dev.write('!term cr')
253277
```
254278
Above setting is volatile. To make this a permanent setting call the below mentioned "!term store" command.
255279

280+
Alternatively you can set the termination directly with visa means, e.g. using PyVisa:
281+
```
282+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, True)
283+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR, ord('\r') )
284+
```
285+
256286
### Set read termination to LF (\n):
257287
```
258288
dev.control_in(0xa1, 0x40, 0, 0, 1); # USBTMC pulse indicator request (enables internal command processing)
259289
dev.write('!term lf')
260290
```
261291
Above setting is volatile. To make this a permanent setting call the below mentioned "!term store" command.
262292

293+
Alternatively you can set the termination directly with visa means, e.g. using PyVisa:
294+
```
295+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, True)
296+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR, ord('\n') )
297+
```
298+
263299
### Set read termination to EOI only (default setting):
264300
```
265301
dev.control_in(0xa1, 0x40, 0, 0, 1); # USBTMC pulse indicator request (enables internal command processing)
266302
dev.write('!term eoi')
267303
```
268304
Above setting is volatile. To make this a permanent setting call the below mentioned "!term store" command.
269305

306+
Alternatively you can set the termination directly with visa means, e.g. using PyVisa:
307+
```
308+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, True)
309+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR, ord('\0') )
310+
```
311+
270312
### Save readtermination setting in eeprom (make them non-volatile)
271313
```
272314
dev.control_in(0xa1, 0x40, 0, 0, 1); # USBTMC pulse indicator request (enables internal command processing)

SW/TestAndMeasurement/TestAndMeasurement.c

Lines changed: 37 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ TMC_Capabilities_t Capabilities =
5757

5858
.Device =
5959
{
60-
.SupportsAbortINOnMatch = false, // false
60+
.SupportsAbortINOnMatch = true, // was false before version 2.0
6161
.Reserved = 0,
6262
},
6363
.Reserved2 = {0, 0, 0, 0, 0, 0},
@@ -122,6 +122,8 @@ static uint16_t LastTransferLength = 0;
122122
/** This will be set true after a indicator pulse command is received. If the next GPIB command starts with '!', a parameter has to be set */
123123
static bool s_nextwrite_mightbeparameterset = false;
124124

125+
static volatile uint8_t s_pulse_indicator = 0;
126+
125127
static uint32_t s_remaining_bytes_receive=0;
126128

127129
static uint8_t gpib_addr = 1;
@@ -467,7 +469,6 @@ int main(void)
467469

468470
/* physically GPIB is connected, now check if any GPIB address is responsive */
469471
#ifndef SPEEDTEST_DUMMY_DEVICE
470-
//asdf
471472
while (!findGpibdevice())
472473
{
473474
_delay_ms(100);
@@ -548,11 +549,28 @@ int main(void)
548549
LED(1);
549550
USB_Attach();
550551

552+
s_pulse_indicator = 0;
553+
uint8_t pulseind_starttime = 0;
551554
for (;;)
552555
{
553556
TMC_Task(); // this task is 9.42us active when nothing is triggered, the rest takes 3.3us
554557
check_bootloaderEntry();
555558

559+
if (s_pulse_indicator > 0) // asynchronous handling of pulse indicator request LED flashing
560+
{
561+
if (s_pulse_indicator == 2)
562+
{
563+
pulseind_starttime = timer0_100mscounter;
564+
LED(0);
565+
s_pulse_indicator--;
566+
}
567+
else if (timer0_100mscounter > (uint8_t)(2 + pulseind_starttime))
568+
{
569+
LED(1);
570+
s_pulse_indicator--;
571+
}
572+
}
573+
556574
if (!gpib_is_connected()) /* check, if gpib is disconnected */
557575
{ /* when we get here, reset the MCU and disconnect from USB ! It will reconnect once plugged in to GPIB again */
558576
LED(0);
@@ -865,9 +883,7 @@ void EVENT_USB_Device_ControlRequest(void)
865883
Endpoint_ClearIN();
866884
Endpoint_ClearStatusStage();
867885

868-
LED(0);
869-
_delay_ms(250);
870-
LED(1);
886+
s_pulse_indicator = 2;
871887

872888
s_nextwrite_mightbeparameterset = true;
873889
break;
@@ -912,19 +928,6 @@ void EVENT_USB_Device_ControlRequest(void)
912928
}
913929
}
914930

915-
static uint8_t charToval(char c)
916-
{
917-
uint8_t val;
918-
val = 0;
919-
if ( (c >= '0') && (c <= '9') )
920-
val = c-'0';
921-
if ( (c >= 'a') && (c <= 'f') )
922-
val = c-'a'+10;
923-
if ( (c >= 'A') && (c <= 'F') )
924-
val = c-'A'+10;
925-
return val;
926-
}
927-
928931
void set_internal_response(uint8_t *pdat, uint8_t len)
929932
{
930933
if (len < sizeof(internal_response_buffer))
@@ -961,13 +964,16 @@ void ProcessInternalCommand(uint8_t Length)
961964

962965
parser_reset();
963966
cmd_executed = false;
964-
while ( (Length--) && (!cmd_executed) )
967+
while ( (Length) && (!cmd_executed) )
965968
{
969+
Length--;
966970
uint8_t dat = Endpoint_Read_8();
967-
cmd_executed = parser_add( dat );
971+
if ((dat != '\r') && (dat != '\n') ) // remove potential termination characters
972+
cmd_executed = parser_add( dat );
968973
}
974+
parser_add('_'); // workaround for autoid slower/est matching in first letters the option autoid slow (result of parser simplification)
969975

970-
// remove residual characters from the endpoint buffer
976+
// remove residual characters from the endpoint buffer (most likely: termination)
971977
while ( (Length--) )
972978
{
973979
uint8_t dat = Endpoint_Read_8();
@@ -1231,6 +1237,16 @@ static inline void TMC_Task(void)
12311237
curlen16 = sizeof(readbuffer);// -1;
12321238
if (curlen16 > MessageHeader.TransferSize)
12331239
curlen16 = MessageHeader.TransferSize;
1240+
1241+
/* New additional method to set termination. Pyvisa example:
1242+
dev is here an opened device ressource)
1243+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR_EN, True)
1244+
dev.set_visa_attribute(visa.constants.VI_ATTR_TERMCHAR, ord('\r') ) # pass \0 for eoi, \n for \n or eoi and \r for \r or eoi. All other options will use EOI only termination
1245+
*/
1246+
if (MessageHeader.MessageIDSpecific.DeviceIN.LastMessageTransaction & 0x02) // the read termination character is set as part of this read transaction request
1247+
{
1248+
gpib_set_readtermination(MessageHeader.MessageIDSpecific.DeviceIN.TermChar);
1249+
}
12341250

12351251
/* Check if a response from an internal query is in the buffer */
12361252
if (internal_response_buffer_len)
@@ -1256,7 +1272,6 @@ static inline void TMC_Task(void)
12561272
MessageHeader.TransferSize = GetNextMessage(readbuffer, curlen16, TMC_InLastMessageComplete, &lastmessage, tmc_gpib_read_timedout);
12571273
}
12581274
TMC_InLastMessageComplete = lastmessage;
1259-
12601275
MessageHeader.MessageIDSpecific.DeviceOUT.LastMessageTransaction = lastmessage;
12611276
if (!IsTMCBulkINReset)
12621277
WriteTMCHeader(&MessageHeader);

SW/TestAndMeasurement/TestAndMeasurement.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@
139139
typedef struct
140140
{
141141
uint8_t LastMessageTransaction;
142-
uint8_t Reserved[3];
142+
uint8_t TermChar;
143+
uint8_t Reserved[2];
143144
} TMC_DevINMessageHeader_t;
144145

145146
typedef struct

SW/TestAndMeasurement/gpib.c

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
/**********************************************************************************************************
1717
* STATIC functions
1818
**********************************************************************************************************/
19-
static volatile uint8_t timer0_100mscounter;
19+
volatile uint8_t timer0_100mscounter;
2020
volatile bool timer0_ticked = false; /* flag going high every 100ms */
2121
static uint8_t timer0_div;
2222
static uint8_t s_device_state = GPIB_DEVICE_CONNECTSTATE_UNKNOWN;
@@ -34,6 +34,10 @@ static void timer_init(void)
3434
timer0_100mscounter = 0;
3535
}
3636

37+
uint8_t gpib_get_100ms_timer(void)
38+
{
39+
return timer0_100mscounter;
40+
}
3741

3842
ISR (TIMER0_OVF_vect)
3943
{

SW/TestAndMeasurement/gpib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ bool gpib_gotoLocal(uint8_t addr, gpibtimeout_t ptimeoutfunc);
4848
/* trigger instrument */
4949
bool gpib_trigger(uint8_t addr, gpibtimeout_t ptimeoutfunc);
5050

51+
/* return an 8 bit upcounting timer value with 100ms tick */
52+
extern volatile uint8_t timer0_100mscounter;
5153

5254
#include "gpib_priv.h"
5355

SW/TestAndMeasurement/miniparser.c

Lines changed: 29 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -13,27 +13,30 @@ typedef void(*parser_func_t) (void);
1313
* hierachical parser tree for memory size efficient parsing of commands.
1414
* Yes, this is pretty unreadable, but: code and speed efficient :-)
1515
*/
16-
static const char cmd_parser[] PROGMEM = {0x06, 'a' , 0x0d, 't' , 0x3f, 'v' , 0x6e, '0' ,
17-
0x77, 'r' , 0x8e, 's' , 0x9a, 0x02, 'u' , 0x12, 'd' , 0x39, 0x01, 't' , 0x15, 0x01,
18-
'o' , 0x18, 0x01, 'i' , 0x1b, 0x01, 'd' , 0x1e, 0x02, ' ' , 0x23, '?'|0x80 , 0x03,
16+
static const char cmd_parser[] PROGMEM = {0x06, 'a' , 0x0d, 't' , 0x4c, 'v' , 0x7b, '0' ,
17+
0x84, 'r' , 0x9b, 's' , 0xa7, 0x02, 'u' , 0x12, 'd' , 0x46, 0x01, 't' , 0x15, 0x01,
18+
'o' , 0x18, 0x01, 'i' , 0x1b, 0x01, 'd' , 0x1e, 0x02, ' ' , 0x23, '?'|0x80 , 0x05,
1919
0x02, 'o' , 0x28, 's' , 0x30, 0x02, 'n'|0x80 , 0x00, 'f' , 0x2d, 0x01, 'f'|0x80 ,
20-
0x01, 0x01, 'l' , 0x33, 0x01, 'o' , 0x36, 0x01, 'w'|0x80 , 0x02, 0x01, 'd' , 0x3c,
21-
0x01, 'r'|0x80 , 0x0f, 0x01, 'e' , 0x42, 0x01, 'r' , 0x45, 0x01, 'm' , 0x48, 0x02,
22-
' ' , 0x4d, '?'|0x80 , 0x07, 0x04, 'c' , 0x56, 'l' , 0x59, 'e' , 0x5c, 's' , 0x62,
23-
0x01, 'r'|0x80 , 0x04, 0x01, 'f'|0x80 , 0x05, 0x01, 'o' , 0x5f, 0x01, 'i'|0x80 ,
24-
0x06, 0x01, 't' , 0x65, 0x01, 'o' , 0x68, 0x01, 'r' , 0x6b, 0x01, 'e'|0x80 , 0x08,
25-
0x01, 'e' , 0x71, 0x01, 'r' , 0x74, 0x01, '?'|0x80 , 0x09, 0x02, '0' , 0x7c, '1' ,
26-
0x84, 0x01, '0' , 0x7f, 0x02, '0'|0x80 , 0x0a, '1'|0x80 , 0x0b, 0x01, '0' , 0x87,
27-
0x03, '0'|0x80 , 0x0c, '1'|0x80 , 0x0d, '2'|0x80 , 0x0e, 0x01, 'e' , 0x91, 0x01,
28-
's' , 0x94, 0x01, 'e' , 0x97, 0x01, 't'|0x80 , 0x10, 0x01, 't' , 0x9d, 0x01, 'r' ,
29-
0xa0, 0x01, 'i' , 0xa3, 0x01, 'n' , 0xa6, 0x01, 'g' , 0xa9, 0x02, ' ' , 0xae, '?'|0x80 ,
30-
0x13, 0x02, 's' , 0xb3, 'n' , 0xbf, 0x01, 'h' , 0xb6, 0x01, 'o' , 0xb9, 0x01, 'r' ,
31-
0xbc, 0x01, 't'|0x80 , 0x11, 0x01, 'o' , 0xc2, 0x01, 'r' , 0xc5, 0x01, 'm' , 0xc8,
32-
0x01, 'a' , 0xcb, 0x01, 'l'|0x80 , 0x12 };
20+
0x01, 0x01, 'l' , 0x33, 0x01, 'o' , 0x36, 0x01, 'w' , 0x39, 0x02, '_'|0x80 , 0x02,
21+
'e' , 0x3e, 0x02, 'r'|0x80 , 0x03, 's' , 0x43, 0x01, 't'|0x80 , 0x04, 0x01, 'd' ,
22+
0x49, 0x01, 'r'|0x80 , 0x11, 0x01, 'e' , 0x4f, 0x01, 'r' , 0x52, 0x01, 'm' , 0x55,
23+
0x02, ' ' , 0x5a, '?'|0x80 , 0x09, 0x04, 'c' , 0x63, 'l' , 0x66, 'e' , 0x69, 's' ,
24+
0x6f, 0x01, 'r'|0x80 , 0x06, 0x01, 'f'|0x80 , 0x07, 0x01, 'o' , 0x6c, 0x01, 'i'|0x80 ,
25+
0x08, 0x01, 't' , 0x72, 0x01, 'o' , 0x75, 0x01, 'r' , 0x78, 0x01, 'e'|0x80 , 0x0a,
26+
0x01, 'e' , 0x7e, 0x01, 'r' , 0x81, 0x01, '?'|0x80 , 0x0b, 0x02, '0' , 0x89, '1' ,
27+
0x91, 0x01, '0' , 0x8c, 0x02, '0'|0x80 , 0x0c, '1'|0x80 , 0x0d, 0x01, '0' , 0x94,
28+
0x03, '0'|0x80 , 0x0e, '1'|0x80 , 0x0f, '2'|0x80 , 0x10, 0x01, 'e' , 0x9e, 0x01,
29+
's' , 0xa1, 0x01, 'e' , 0xa4, 0x01, 't'|0x80 , 0x12, 0x01, 't' , 0xaa, 0x01, 'r' ,
30+
0xad, 0x01, 'i' , 0xb0, 0x01, 'n' , 0xb3, 0x01, 'g' , 0xb6, 0x02, ' ' , 0xbb, '?'|0x80 ,
31+
0x15, 0x02, 's' , 0xc0, 'n' , 0xcc, 0x01, 'h' , 0xc3, 0x01, 'o' , 0xc6, 0x01, 'r' ,
32+
0xc9, 0x01, 't'|0x80 , 0x13, 0x01, 'o' , 0xcf, 0x01, 'r' , 0xd2, 0x01, 'm' , 0xd5,
33+
0x01, 'a' , 0xd8, 0x01, 'l'|0x80 , 0x14 };
3334

3435
void cmd_autoid_on(void);
3536
void cmd_autoid_off(void);
36-
void cmd_autoid_slow(void);
37+
void cmd_autoid_slow_(void);
38+
void cmd_autoid_slower(void);
39+
void cmd_autoid_slowest(void);
3740
void cmd_autoid_query(void);
3841
void cmd_term_cr(void);
3942
void cmd_term_lf(void);
@@ -55,7 +58,9 @@ void cmd_string_query(void);
5558
static const parser_func_t cmd_list[] PROGMEM = {
5659
cmd_autoid_on,
5760
cmd_autoid_off,
58-
cmd_autoid_slow,
61+
cmd_autoid_slow_,
62+
cmd_autoid_slower,
63+
cmd_autoid_slowest,
5964
cmd_autoid_query,
6065
cmd_term_cr,
6166
cmd_term_lf,
@@ -85,7 +90,7 @@ void cmd_autoid_off(void)
8590
eeprom_update_if_changed(104, 0x01); // autoId OFF
8691
}
8792

88-
void cmd_autoid_slow(void)
93+
void cmd_autoid_slow_(void)
8994
{
9095
eeprom_update_if_changed(104, 0x02); // autoId SLOW
9196
}
@@ -105,7 +110,11 @@ void cmd_autoid_query(void)
105110
switch(eeprom_read_byte((uint8_t*)104))
106111
{
107112
case 0x04:
113+
set_internal_response((void*)"slowest", 7);
114+
break;
108115
case 0x03:
116+
set_internal_response((void*)"slower", 6);
117+
break;
109118
case 0x02:
110119
set_internal_response((void*)"slow", 4);
111120
break;
@@ -151,7 +160,7 @@ void cmd_term_store(void)
151160

152161
void cmd_ver_query(void)
153162
{
154-
set_internal_response((void*)"V1.9", 4);
163+
set_internal_response((void*)"V2.0", 4);
155164
}
156165

157166
void cmd_0000(void)

SW/TestAndMeasurement/usbgpib.pnproj

Lines changed: 0 additions & 1 deletion
This file was deleted.

SW/TestAndMeasurement/usbgpib.pnps

Lines changed: 0 additions & 1 deletion
This file was deleted.

SW/UsbGpibGUI/UsbGpibGUI.exe

512 Bytes
Binary file not shown.

0 commit comments

Comments
 (0)