From 3034bd457601a1ba3344c57ea22b6f4c28714a14 Mon Sep 17 00:00:00 2001 From: Twilight-Logic Date: Wed, 14 Feb 2024 18:54:15 +0000 Subject: [PATCH] Added ESP32 layout --- src/AR488/AR488.ino | 315 ++++++++------- src/AR488/AR488_Config.h | 108 +++-- src/AR488/AR488_Eeprom.cpp | 4 +- src/AR488/AR488_Eeprom.h | 2 +- src/AR488/AR488_GPIBbus.cpp | 766 +++++++++++++++++++----------------- src/AR488/AR488_GPIBbus.h | 273 +++++++------ src/AR488/AR488_Layouts.cpp | 401 +++++-------------- src/AR488/AR488_Layouts.h | 396 +++++++++---------- 8 files changed, 1060 insertions(+), 1205 deletions(-) diff --git a/src/AR488/AR488.ino b/src/AR488/AR488.ino index 4b73a8b..0f1f2a8 100644 --- a/src/AR488/AR488.ino +++ b/src/AR488/AR488.ino @@ -14,7 +14,7 @@ #include "AR488_Eeprom.h" -/***** FWVER "AR488 GPIB controller, ver. 0.51.20, 16/12/2023" *****/ +/***** FWVER "AR488 GPIB controller, ver. 0.51.26, 24/12/2023" *****/ /* Arduino IEEE-488 implementation by John Chajecki @@ -182,6 +182,7 @@ static const char cmdHelp[] PROGMEM = { "repeat:C Repeat a given command and return result\n" "setvstr:C DEPRECATED - see id verstr\n" "srqauto:C Automatically conduct serial poll when SRQ is asserted\n" + "tct:C Signal remote device to take control\n" "ton:C Put controller in talk-only mode (send data only)\n" "verbose:C Verbose (human readable) mode\n" "xdiag:C Bus diagnostics (see the doc)\n" @@ -228,6 +229,8 @@ bool readWithEndByte = false; // Read with specified terminator character bool isQuery = false; // Direct instrument command is a query uint8_t tranBrk = 0; // Transmission break on 1=++, 2=EOI, 3=ATN 4=UNL uint8_t endByte = 0; // Termination character +bool isProm = false; // Promiscuous mode flag +bool isSpoll = false; // Serial poll flag // Escaped character flag bool isEsc = false; // Charcter escaped @@ -239,8 +242,6 @@ bool isRO = false; // Talk only mode flag uint8_t isTO = 0; -bool isProm = false; - // Data send mode flags bool dataBufferFull = false; // Flag when parse buffer is full @@ -261,8 +262,6 @@ uint8_t runMacro = 0; // Send response to *idn? bool sendIdn = false; -// Xon/Xoff flag (off by default) -//bool xonxoff = false; /***** ^^^^^^^^^^^^^^^^^^^^^^^^ *****/ /***** COMMON VARIABLES SECTION *****/ @@ -283,26 +282,23 @@ void setup() { wdt_disable(); #endif - // Turn off internal LED (set OUPTUT/LOW) + // Turn off internal LED (set OUPTUT/LOW) - Arduinos have a separate power LED #ifdef LED_BUILTIN pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); #endif - -#ifdef PIN_REMOTE - pinMode(PIN_REMOTE, OUTPUT); - digitalWrite(PIN_REMOTE, LOW); +// For RPI we turn on the built-in LED as a power indicator +#ifdef ARDUINO_ARCH_RP2040 + pinMode(LED_BUILTIN, OUTPUT); + digitalWrite(LED_BUILTIN, HIGH); #endif - - // Using AVR board with PCINT interrupts -/* -#ifdef USE_INTERRUPTS - // Turn on interrupts on port - interruptsEn(); +#ifdef REMOTE_SIGNAL_PIN + pinMode(REMOTE_SIGNAL_PIN, OUTPUT); + digitalWrite(REMOTE_SIGNAL_PIN, LOW); #endif -*/ + // Initialise parse buffer flushPbuf(); @@ -340,27 +336,6 @@ void setup() { #endif - // Using MCP23017 (I2C) expander chip -#ifdef AR488_MCP23017 - // Start I2C - Wire.begin(); - // OPtional: Set the I2C bus clock frequency in Hertz (optional - 10000 [slow], 100000 [standard], 400000 [fast], 3400000 [fast plus]) - // Check processor documentation for which modes are supported -// Wire.setClock(100000); - - // Set expander configuration register - // (Bit 1=0 sets active low for Int A) - // (Bit 3 is not relevant for the 23017) - // (Bit 7=0 sets registers to be in same bank) - mcpByteWrite(MCPCON, 0b00000000); - - // Enable MCP23017 interrupts - mcpInterruptsEn(); - // Attach interrupt handler to Arduino board pin for MCP23S17 to signal interrupt has occurred - attachInterrupt(digitalPinToInterrupt(MCP_INTERRUPT), mcpIntHandler, FALLING); -#endif - - // Un-comment for diagnostic purposes /* #if defined(__AVR_ATmega32U4__) @@ -500,12 +475,10 @@ if (lnRdy>0){ sendToInstrument(pBuf, pbPtr); // Auto-read data from GPIB bus following any command if (gpibBus.cfg.amode == 1) { - // delay(10); errFlg = gpibBus.receiveData(dataPort, gpibBus.cfg.eoi, false, 0); } // Auto-receive data from GPIB bus following a query command if (gpibBus.cfg.amode == 2 && isQuery) { - // delay(10); errFlg = gpibBus.receiveData(dataPort, gpibBus.cfg.eoi, false, 0); isQuery = false; } @@ -545,22 +518,18 @@ if (lnRdy>0){ tonMode(); }else if (isRO) { lonMode(); - }else if (gpibBus.isAsserted(ATN)) { + }else if (gpibBus.isAsserted(ATN_PIN)) { // dataPort.println(F("Attention signal detected")); attnRequired(); // dataPort.println(F("ATN loop finished")); +// }else{ +// if (lnRdy == 2) sendToInstrument(pBuf, pbPtr); } // Can't send in LON mode so just clear the buffer if (isProm) { if (lnRdy == 2) flushPbuf(); } - -/* - else{ - if (lnRdy == 2) sendToInstrument(pBuf, pbPtr); - } -*/ } // Reset line ready flag @@ -652,12 +621,7 @@ void errBadCmd() { uint8_t parseInput(char c) { uint8_t r = 0; -/* - if (xonxoff){ - // Send XOFF when buffer around 80% full - if (pbPtr < (PBSIZE*0.8)) dataPort.print(0x13); - } -*/ + // Read until buffer full if (pbPtr < PBSIZE) { if (isVerb && c!=LF) dataPort.print(c); // Humans like to see what they are typing... @@ -747,7 +711,6 @@ uint8_t parseInput(char c) { }else{ // Buffer contains data and is full, so process the buffer (send data via GPIB) dataBufferFull = true; // Signal to GPIB object that more data will follow (suppress GPIB addressing) -// gpibBus.setDataContinuity(true); r = 2; } } @@ -863,6 +826,7 @@ static cmdRec cmdHidx [] = { { "srq", 2, (void(*)(char*)) srq_h }, { "srqauto", 2, srqa_h }, { "status", 1, stat_h }, + { "tct", 2, tct_h }, { "ton", 1, ton_h }, { "unl", 2, (void(*)(char*)) unlisten_h }, { "unt", 2, (void(*)(char*)) untalk_h }, @@ -881,7 +845,7 @@ void showPrompt() { /****** Send data to instrument *****/ -/* Processes the parse buffer whenever a full CR or LF +/* Processes the parse buffer when full or CR/LF detected * and sends data to the instrument */ void sendToInstrument(char *buffr, uint8_t dsize) { @@ -894,19 +858,22 @@ void sendToInstrument(char *buffr, uint8_t dsize) { // Is this an instrument query command (string ending with ?) if (buffr[dsize-1] == '?') isQuery = true; - // Has controller already addressed the device? - if not then address it - if (!gpibBus.haveAddressedDevice()) gpibBus.addressDevice(gpibBus.cfg.paddr, LISTEN); + if (gpibBus.isController()) { + // Has controller already addressed the device? - if not then address it + if (!gpibBus.haveAddressedDevice()) gpibBus.addressDevice(gpibBus.cfg.paddr, LISTEN); + } // Send string to instrument gpibBus.sendData(buffr, dsize); - // Address device - if (dataBufferFull) { - dataBufferFull = false; - }else{ + // If controller then unaddress device + if (gpibBus.isController() && dataBufferFull == false) { gpibBus.unAddressDevice(); } + // Clear buffer full flag + if (dataBufferFull) dataBufferFull = false; + #ifdef DEBUG_SEND_TO_INSTR DB_PRINT(F("done."),""); #endif @@ -1351,7 +1318,7 @@ void clr_h() { /***** Send local lockout command *****/ void llo_h(char *params) { // NOTE: REN *MUST* be asserted (LOW) - if (digitalRead(REN)==LOW) { + if (digitalRead(REN_PIN)==LOW) { // For 'all' send LLO to the bus without addressing any device // Devices will show REM as soon as they are addressed and need to be released with LOC if (params != NULL) { @@ -1375,7 +1342,7 @@ void llo_h(char *params) { /***** Send Go To Local (GTL) command *****/ void loc_h(char *params) { // REN *MUST* be asserted (LOW) - if (digitalRead(REN)==LOW) { + if (digitalRead(REN_PIN)==LOW) { if (params != NULL) { if (strncmp(params, "all", 3) == 0) { // Send request to clear all devices to local @@ -1479,6 +1446,10 @@ void rst_h() { if (isVerb) { dataPort.println(F("Reset FAILED.")); }; +#elif defined (ESP32) + ESP.restart(); +#elif defined(ARDUINO_ARCH_RP2040) + rp2040.reboot(); #else // Otherwise restart program (soft reset) asm volatile (" jmp 0"); @@ -1491,8 +1462,7 @@ void spoll_h(char *params) { char *param; uint8_t addrs[15]; uint8_t sb = 0; - uint8_t r; - // uint8_t i = 0; + enum gpibHandshakeStates state; uint8_t j = 0; uint16_t addrval = 0; bool all = false; @@ -1586,14 +1556,20 @@ void spoll_h(char *params) { return; } - // Set GPIB control to controller active listner state (ATN unasserted) + // Set GPIB control to controller active listner state (ATN unasserted), clear databus and set to input gpibBus.setControls(CLAS); + gpibBus.clearDataBus(); // Read the response byte (usually device status) using handshake - suppress EOI detection - r = gpibBus.readByte(&sb, false, &eoiDetected); + state = gpibBus.readByte(&sb, false, &eoiDetected); // If we successfully read a byte - if (!r) { + if (state == HANDSHAKE_COMPLETE) { + + // Set GPIB control back to controller active talk state (ATN asserted) + gpibBus.setControls(CTAS); + + // Process response if (j == 30) { // If all, return specially formatted response: SRQ:addr,status // but only when RQS bit set @@ -1615,7 +1591,10 @@ void spoll_h(char *params) { i = j; } } else { - if (isVerb) dataPort.println(F("Failed to retrieve status byte")); + if (isVerb) { + dataPort.print(F("Failed to retrieve status byte from ")); + dataPort.println(addrval); + } } } } @@ -1648,16 +1627,6 @@ void spoll_h(char *params) { // Set GPIB control to controller idle state gpibBus.setControls(CIDS); - // Set SRQ to status of SRQ line. Should now be unasserted but, if it is - // still asserted, then another device may be requesting service so another - // serial poll will be called from the main loop -/* FLAG NO LONGER USED = NOW CHECKING STATUS OF LINE - if (digitalRead(SRQ) == LOW) { - isSRQ = true; - } else { - isSRQ = false; - } -*/ if (isVerb) dataPort.println(F("Serial poll completed.")); } @@ -1667,7 +1636,7 @@ void spoll_h(char *params) { void srq_h() { //NOTE: LOW=0=asserted, HIGH=1=unasserted // dataPort.println(!digitalRead(SRQ)); - dataPort.println(gpibBus.isAsserted(SRQ)); + dataPort.println(gpibBus.isAsserted(SRQ_PIN)); } @@ -1814,9 +1783,6 @@ void eor_h(char *params) { /***** Parallel Poll Handler *****/ -/* - * Device must be set to respond on DIO line 1 - 8 - */ void ppoll_h() { uint8_t sb = 0; @@ -1824,12 +1790,16 @@ void ppoll_h() { // Start in controller idle state gpibBus.setControls(CIDS); delayMicroseconds(20); + // Assert ATN and EOI - gpibBus.setControlVal(0b00000000, 0b10010000, 0); - // setGpibState(0b10010000, 0b00000000, 0b10010000); + gpibBus.setTransmitMode(TM_SEND); + gpibBus.assertSignal( ATN_BIT | EOI_BIT ); + gpibBus.setTransmitMode(TM_RECV); delayMicroseconds(20); + // Read data byte from GPIB bus without handshake sb = readGpibDbus(); + // Return to controller idle state (ATN and EOI unasserted) gpibBus.setControls(CIDS); @@ -1850,13 +1820,13 @@ void ren_h(char *params) { uint16_t val; if (params != NULL) { if (notInRange(params, 0, 1, val)) return; - digitalWrite(REN, (val ? LOW : HIGH)); + digitalWrite(REN_PIN, (val ? LOW : HIGH)); if (isVerb) { dataPort.print(F("REN: ")); dataPort.println(val ? "REN asserted" : "REN un-asserted") ; }; } else { - dataPort.println(digitalRead(REN) ? 0 : 1); + dataPort.println(digitalRead(REN_PIN) ? 0 : 1); } #endif } @@ -1877,9 +1847,10 @@ void verb_h() { void setvstr_h(char *params) { uint8_t plen; char idparams[64]; + const char *vstr = "verstr "; plen = strlen(params); memset(idparams, '\0', 64); - strncpy(idparams, "verstr ", 7); + strlcpy(idparams, vstr, sizeof(vstr)); if (plen>47) plen = 47; // Ignore anything over 47 characters strncat(idparams, params, plen); @@ -1926,7 +1897,6 @@ void ton_h(char *params) { uint16_t toval; if (params != NULL) { if (notInRange(params, 0, 2, toval)) return; -// isTO = val ? true : false; isTO = (uint8_t)toval; if (isTO>0) { isRO = false; // Read-only mode must be disabled in TO mode! @@ -2020,6 +1990,37 @@ void repeat_h(char *params) { } +/***** Take Control command *****/ +void tct_h(char *params){ + uint16_t val; + bool tctfail = false; + if (params != NULL) { + if (notInRange(params, 0, 30, val)) return; + if (val == gpibBus.cfg.caddr) { + errBadCmd(); + if (isVerb) dataPort.println(F("That is my address! Please provide the address of a remote device.")); + return; + } + + tctfail = gpibBus.sendTCT(val); + + if (isVerb) { + dataPort.print(F("Sending TCT to device at address ")); + dataPort.print(val); + } + + if (tctfail) { + if (isVerb) dataPort.println(F(" failed!")); + return; + }else{ + if (isVerb) dataPort.println(F(" succeeded.")); + gpibBus.startDeviceMode(); + if (isVerb) dataPort.println(F("Switched to device mode.")); + } + } +} + + /***** Run a macro *****/ void macro_h(char *params) { #ifdef USE_MACROS @@ -2064,6 +2065,14 @@ void xdiag_h(char *params){ // Get first parameter (mode = 0 or 1) param = strtok(params, " \t"); + +#ifdef DEBUG_LAYOUT + if ( strncmp(param, "pins", 4) ==0) { + pinout(); + return; + } +#endif + if (param != NULL) { if (strlen(param)<4){ mode = atoi(param); @@ -2089,7 +2098,7 @@ void xdiag_h(char *params){ gpibBus.setDataVal(0); break; case 1: - // Set to required state + // Set to required state (setControlVal function need to set all 8 signals) gpibBus.setControlVal(0xFF, 0xFF, 1); // Set direction (all pins as outputs) gpibBus.setControlVal(~byteval, 0xFF, 0); // Set state (asserted=LOW so must invert value) // Reset after 10 seconds @@ -2107,22 +2116,29 @@ void xdiag_h(char *params){ } -/***** Enable Xon/Xoff handshaking for data transmission *****/ -/* -void xonxoff_h(char *params){ - uint16_t val; - if (params != NULL) { - if (notInRange(params, 0, 1, val)) return; - xonxoff = val ? true : false; - if (isVerb) { - dataPort.print(F("Xon/Xoff: ")); - dataPort.println(val ? "ON" : "OFF") ; - } - } else { - dataPort.println(xonxoff); - } +#ifdef DEBUG_LAYOUT +void pinout(){ + // Data pins + DB_PRINT(F("DIO1: "), DIO1_PIN); + DB_PRINT(F("DIO2: "), DIO2_PIN); + DB_PRINT(F("DIO3: "), DIO3_PIN); + DB_PRINT(F("DIO4: "), DIO4_PIN); + DB_PRINT(F("DIO5: "), DIO5_PIN); + DB_PRINT(F("DIO6: "), DIO6_PIN); + DB_PRINT(F("DIO7: "), DIO7_PIN); + DB_PRINT(F("DIO8: "), DIO8_PIN); + // Control pins + DB_PRINT(F("IFC: "), IFC_PIN); + DB_PRINT(F("NDAC: "), NDAC_PIN); + DB_PRINT(F("NRFD: "), NRFD_PIN); + DB_PRINT(F("DAV: "), DAV_PIN); + DB_PRINT(F("EOI: "), EOI_PIN); + DB_PRINT(F("SRQ: "), SRQ_PIN); + DB_PRINT(F("REN: "), REN_PIN); + DB_PRINT(F("ATN: "), ATN_PIN); } -*/ +#endif + /***** Set device ID *****/ @@ -2199,8 +2215,9 @@ void id_h(char *params) { return; } void addr_h(char *params); if (strncasecmp(keyword, "serial", 6)==0) { + unsigned long int serialnum = gpibBus.cfg.serial; memset(serialStr, '\0', 10); - snprintf(serialStr, 10, "%09lu", gpibBus.cfg.serial); // Max str length = 10-1 i.e 9 digits + null terminator + snprintf(serialStr, 10, "%09lu", serialnum); // Max str length = 10-1 i.e 9 digits + null terminator dataPort.println(serialStr); return; } @@ -2314,7 +2331,6 @@ void attnRequired() { const uint8_t cmdbuflen = 35; uint8_t cmdbytes[5] = {0}; uint8_t db = 0; -// uint8_t rstat = 0; bool eoiDetected = false; uint8_t gpibcmd = 0; uint8_t bytecnt = 0; @@ -2336,21 +2352,12 @@ void attnRequired() { /***** ATN read loop *****/ // Read bytes received while ATN is asserted - while ( (gpibBus.isAsserted(ATN)) && (bytecnt 0 ) break; - // Untalk or unlisten -/* + while ( (gpibBus.isAsserted(ATN_PIN)) && (bytecnt"),""); #endif + // Send the status byte gpibBus.sendStatus(); #ifdef DEBUG_DEVICE_ATN - DB_PRINT(F("Status sent: "), gpibBus.cfg.stat); + DB_PRINT(F("Status sent: "), (stat & ~0x40)); #endif - // Check if SRQ bit is set and clear it - if (gpibBus.cfg.stat & 0x40) { - gpibBus.setStatus(gpibBus.cfg.stat & ~0x40); +} + + +/***** Take control *****/ +void device_tct_h(){ #ifdef DEBUG_DEVICE_ATN - DB_PRINT(F("SRQ bit cleared."),""); + DB_PRINT(F("Take control (TCT) request received from controller."),""); +#endif + gpibBus.startControllerMode(); +#ifdef DEBUG_DEVICE_ATN + DB_PRINT(F("Switched to controller mode."), ""); #endif - } } @@ -2667,13 +2692,13 @@ bool device_unt_h(){ #ifdef REMOTE_SIGNAL_PIN /***** Enabled remote mode *****/ void device_llo_h(){ - digitalWrite(PIN_REMOTE, HIGH); + digitalWrite(REMOTE_SIGNAL_PIN, HIGH); } /***** Disable remote mode *****/ void device_gtl_h(){ - digitalWrite(PIN_REMOTE, LOW); + digitalWrite(REMOTE_SIGNAL_PIN, LOW); } #endif @@ -2681,23 +2706,23 @@ void device_gtl_h(){ void lonMode(){ uint8_t db = 0; - uint8_t r = 0; + enum gpibHandshakeStates state; bool eoiDetected = false; - // Set bus for device read mode + // Set bus for device listner active mode gpibBus.setControls(DLAS); while (isRO) { - r = gpibBus.readByte(&db, false, &eoiDetected); - if (r == 0) dataPort.write(db); + state = gpibBus.readByte(&db, false, &eoiDetected); + if (state == HANDSHAKE_COMPLETE) dataPort.write(db); // Check whether there are charaters waiting in the serial input buffer and call handler if (dataPort.available()) { lnRdy = serialIn_h(); - // We have a command return to main loop and execute it + // We have a command so return to main loop and execute it if (lnRdy==1) break; // Clear the buffer to prevent it getting blocked @@ -2716,7 +2741,7 @@ void lonMode(){ /***** Talk only mpode *****/ void tonMode(){ - // Set bus for device read mode + // Set bus for device taker active mode gpibBus.setControls(DTAS); while (isTO>0) { diff --git a/src/AR488/AR488_Config.h b/src/AR488/AR488_Config.h index 0a11c6a..40770cb 100644 --- a/src/AR488/AR488_Config.h +++ b/src/AR488/AR488_Config.h @@ -7,7 +7,7 @@ /***** Firmware version *****/ -#define FWVER "AR488 GPIB controller, ver. 0.51.20, 15/12/2023" +#define FWVER "AR488 GPIB controller, ver. 0.51.26, 24/12/2023" @@ -45,7 +45,6 @@ #define AR488_UNO //#define AR488_NANO //#define AR488_MCP23S17 - //#define AR488_MCP23017 /*** MEGA 32U4 based boards (Micro, Leonardo) ***/ #elif __AVR_ATmega32U4__ @@ -60,13 +59,28 @@ //#define AR488_MEGA2560_E1 //#define AR488_MEGA2560_E2 // #define AR488_MCP23S17 - //#define AR488_MCP23017 /***** Panduino Mega 644 or Mega 1284 board *****/ #elif defined(__AVR_ATmega644P__) || defined(__AVR_ATmega1284P__) /* Board/layout selection */ #define AR488_MEGA644P_MCGRAW - + +/***** ESP 32 VROOM-32 *****/ +#elif defined(ESP32) + #define NON_ARDUINO + #define ESP32_WROOM_32 + +/***** RPI PIco and Pico W *****/ +//#elif defined(ARDUINO_ARCH_RP2040) +// #define NON_ARDUINO +// #define RPI_PICO + +//#elif defined(ARDUINO_NANO_RP2040_CONNECT) + +//#elif defined(ARDUINO_ARCH_MBED_NANO) + +//#elif defined(ARDUINO_ARCH_MBED_RP2040) + #endif // Board/layout selection @@ -93,7 +107,7 @@ #endif /***** Debug port *****/ -//#define DEBUG_ENABLE +#define DEBUG_ENABLE #ifdef DEBUG_ENABLE // Serial port device #define DB_SERIAL_PORT Serial @@ -121,11 +135,11 @@ /***** SUPPORT FOR PERIPHERAL CHIPS *****/ /* * This sections priovides configuration to enable/disable support - * for SN7516x, MCP23S17 and MCP23017 chips. + * for SN7516x chips and the MCP23S17 GPIO expander. */ -/***** Enable MCP23S17 chip *****/ +/***** Enable MCP23S17 GPIO expander chip *****/ /* * This version uses the SPI interface with speeds up to 10MHz max * Note: Use #define MCP23S17 as the layout definition @@ -137,18 +151,6 @@ #endif -/***** Enable MCP23017 chip *****/ -/* - * This version uses the I2C interface with speeds of 100kHz, 400kHz and 1,7MHz - * Pull up resistors (4.7k) are required on the SDA and SCL pins - * Note: Use #define MCP23017 as the layout definition - */ -#ifdef AR488_MCP23017 - #define MCP_ADDRESS 1 - #define MCP_INTERRUPT 3 -#endif - - /***** Enable SN7516x chips *****/ /* * Uncomment to enable the use of SN7516x GPIB tranceiver ICs. @@ -174,30 +176,7 @@ */ -/***** Pin State Detection *****/ -/* - * With UNO. NANO and MEGA boards with pre-defined layouts, - * USE_INTERRUPTS can and should be used. - * With the AR488_CUSTOM layout and unknown boards, USE_INTERRUPTS must - * be commented out. Interrupts are used on pre-defined AVR board layouts - * and will respond faster, however in-loop checking for state of pin states - * can be supported with any board layout. - */ -/* -#ifdef __AVR__ - // For supported boards use interrupt handlers - #if defined (AR488_UNO) || defined (AR488_NANO) || defined (AR488_MEGA2560) || defined (AR488_MEGA32U4) - #ifndef AR488_CUSTOM - #ifndef AR488_MCP23S17 - #define USE_INTERRUPTS - #endif - #endif - #endif -#endif -*/ - - -/***** Local/remote signal (LED) *****/ +/***** Device mode local/remote signal (LED) *****/ //#define REMOTE_SIGNAL_PIN 7 @@ -221,7 +200,6 @@ - /***** DEBUG LEVEL OPTIONS *****/ /* * Configure debug level options @@ -244,8 +222,8 @@ //#define DEBUG_GPIB_ADDRESSING // GPIBbus::sendMA(), GPIBbus::sendMLA(), GPIBbus::sendUNT(), GPIBbus::sendUNL() //#define DEBUG_GPIB_DEVICE // GPIBbus::unAddressDevice(), GPIBbus::addressDevice - // GPIB layout module - //#define DEBUG_LAYOUTS + // GPIB layout + #define DEBUG_LAYOUT // EEPROM module //#define DEBUG_EEPROM // EEPROM @@ -263,28 +241,30 @@ /*******************************/ /***** AR488 CUSTOM LAYOUT *****/ /***** vvvvvvvvvvvvvvvvvvv *****/ + #ifdef AR488_CUSTOM -#define DIO1 A0 /* GPIB 1 */ -#define DIO2 A1 /* GPIB 2 */ -#define DIO3 A2 /* GPIB 3 */ -#define DIO4 A3 /* GPIB 4 */ -#define DIO5 A4 /* GPIB 13 */ -#define DIO6 A5 /* GPIB 14 */ -#define DIO7 4 /* GPIB 15 */ -#define DIO8 5 /* GPIB 16 */ - -#define IFC 8 /* GPIB 9 */ -#define NDAC 9 /* GPIB 8 */ -#define NRFD 10 /* GPIB 7 */ -#define DAV 11 /* GPIB 6 */ -#define EOI 12 /* GPIB 5 */ - -#define SRQ 2 /* GPIB 10 */ -#define REN 3 /* GPIB 17 */ -#define ATN 7 /* GPIB 11 */ +#define DIO1_PIN A0 /* GPIB 1 */ +#define DIO2_PIN A1 /* GPIB 2 */ +#define DIO3_PIN A2 /* GPIB 3 */ +#define DIO4_PIN A3 /* GPIB 4 */ +#define DIO5_PIN A4 /* GPIB 13 */ +#define DIO6_PIN A5 /* GPIB 14 */ +#define DIO7_PIN 4 /* GPIB 15 */ +#define DIO8_PIN 5 /* GPIB 16 */ + +#define IFC_PIN 8 /* GPIB 9 */ +#define NDAC_PIN 9 /* GPIB 8 */ +#define NRFD_PIN 10 /* GPIB 7 */ +#define DAV_PIN 11 /* GPIB 6 */ +#define EOI_PIN 12 /* GPIB 5 */ + +#define SRQ_PIN 2 /* GPIB 10 */ +#define REN_PIN 3 /* GPIB 17 */ +#define ATN_PIN 7 /* GPIB 11 */ #endif + /***** ^^^^^^^^^^^^^^^^^^^ *****/ /***** AR488 CUSTOM LAYOUT *****/ /*******************************/ diff --git a/src/AR488/AR488_Eeprom.cpp b/src/AR488/AR488_Eeprom.cpp index ad93ac0..8d402bf 100644 --- a/src/AR488/AR488_Eeprom.cpp +++ b/src/AR488/AR488_Eeprom.cpp @@ -2,7 +2,7 @@ #include #include "AR488_Eeprom.h" -/***** AR488_Eeprom.cpp, ver. 0.00.06, 16/06/2021 *****/ +/***** AR488_Eeprom.cpp, ver. 0.00.07, 21/12/2023 *****/ /* * EEPROM functions implementation */ @@ -130,6 +130,8 @@ void epViewData(Stream& outputStream) { uint16_t addr = 0; uint8_t dbuf[16]; char cnt[4]= {'\0'}; + char oct[4] = {'\0'}; + // Load EEPROM data from Flash EEPROM.begin(EESIZE); diff --git a/src/AR488/AR488_Eeprom.h b/src/AR488/AR488_Eeprom.h index e626396..ec9702c 100644 --- a/src/AR488/AR488_Eeprom.h +++ b/src/AR488/AR488_Eeprom.h @@ -4,7 +4,7 @@ #include "AR488_Config.h" //#include -/***** AR488_Eeprom.h, ver. 0.00.06, 16/06/2021 *****/ +/***** AR488_Eeprom.h, ver. 0.00.07, 21/12/2023 *****/ /* * EEPROM SIZES: diff --git a/src/AR488/AR488_GPIBbus.cpp b/src/AR488/AR488_GPIBbus.cpp index f0411b2..a2967bc 100644 --- a/src/AR488/AR488_GPIBbus.cpp +++ b/src/AR488/AR488_GPIBbus.cpp @@ -3,29 +3,20 @@ #include "AR488_Config.h" #include "AR488_GPIBbus.h" -/***** AR488_GPIB.cpp, ver. 0.51.20, 16/12/2023 *****/ +/***** AR488_GPIB.cpp, ver. 0.51.25, 21/12/2023 *****/ /****** Process status values *****/ -#define OK false +#define OK false #define ERR true /***** Control characters *****/ -#define ESC 0x1B // the USB escape char -#define CR 0xD // Carriage return -#define LF 0xA // Newline/linefeed -#define PLUS 0x2B // '+' character +#define ESC 0x1B // the USB escape char +#define CR 0xD // Carriage return +#define LF 0xA // Newline/linefeed +#define PLUS 0x2B // '+' character -/***** Serial/debugStream port *****/ -/* -#ifdef AR_SERIAL_ENABLE - extern Stream& dataStream; -#endif -#ifdef DB_SERIAL_ENABLE - extern Stream& debugStream; -#endif -*/ /***************************************/ /***** GPIB CLASS PUBLIC FUNCTIONS *****/ @@ -35,53 +26,46 @@ /********** PUBLIC FUNCTIONS **********/ /***** Class constructor *****/ -GPIBbus::GPIBbus(){ +GPIBbus::GPIBbus() { // Default configuration values setDefaultCfg(); cstate = 0; -// addressingSuppressed = false; -// dataContinuity = false; deviceAddressed = false; -// deviceAddressedState = DIDS; } /***** Start the bus in controller or device mode depending on config *****/ -void GPIBbus::begin(){ +void GPIBbus::begin() { if (isController()) { startControllerMode(); - }else{ + } else { startDeviceMode(); } } -/***** Stops active mode and brings control and data bus to inactive state *****/ -void GPIBbus::stop(){ +/***** Stops active mode and bring control and data bus to inactive state *****/ +void GPIBbus::stop() { cstate = 0; // Set control bus to idle state (all lines input_pullup) - // Input_pullup - setGpibState(0b00000000, 0b11111111, 1); - // All lines HIGH - setGpibState(0b11111111, 0b11111111, 0); + clearAllSignals(); // Set data bus to default state (all lines input_pullup) readyGpibDbus(); } - /***** Initialise the interface *****/ -void GPIBbus::setDefaultCfg(){ - // Set default values ({'\0'} sets version string array to null) - cfg = {false, false, 2, 0, 1, 0, 0, 0, 0, 1200, 0, {'\0'}, 0, {'\0'}, 0, 0}; +void GPIBbus::setDefaultCfg() { + // Set default controller mode values ({'\0'} sets version string array to null) + cfg = { false, false, 2, 0, 1, 0, 0, 0, 0, 1200, 0, { '\0' }, 0, { '\0' }, 0, 0 }; } /***** Set bus into Device mode *****/ -void GPIBbus::startDeviceMode(){ +void GPIBbus::startDeviceMode() { // Stop current mode stop(); - delayMicroseconds(200); // Allow settling time + delayMicroseconds(200); // Allow settling time // Start device mode cfg.cmode = 1; // Set GPIB control bus to device idle mode @@ -92,12 +76,12 @@ void GPIBbus::startDeviceMode(){ /***** Set interface into Controller mode *****/ -void GPIBbus::startControllerMode(){ +void GPIBbus::startControllerMode() { // Send request to clear all devices on bus to local mode sendAllClear(); // Stop current mode stop(); - delayMicroseconds(200); // Allow settling time + delayMicroseconds(200); // Allow settling time // Start controller mode cfg.cmode = 2; // Set GPIB control bus to controller idle mode @@ -111,38 +95,90 @@ void GPIBbus::startControllerMode(){ } +/***** Set the interface mode *****/ +void GPIBbus::setOperatingMode(enum operatingModes mode) { + uint8_t outputs = 0; + switch (mode) { + case OP_IDLE: + setGpibState(0, CTRL_BITS, 1); // All control signals to inputs + setGpibState(CTRL_BITS, CTRL_BITS, 0); // All control signal states to INPUT_PULLUP + break; + case OP_CTRL: + outputs = (IFC_BIT | REN_BIT | ATN_BIT); // Signal IFC, REN and ATN, listen to SRQ + setGpibState(outputs, CTRL_BITS, 1); // Set control inputs and outputs (0=input, 1=output) + setGpibState(CTRL_BITS, CTRL_BITS, 0); // Set control signal states: outputs to unasserted/HIGH, inputs to 1 (INPUT_PULLUP) + break; + case OP_DEVI: + outputs = (SRQ_BIT); // Signal SRQ, listen to IFC, REN and ATN + clearSignal(REN_BIT); + setGpibState(outputs, CTRL_BITS, 1); // Set control inputs and outputs (0=input, 1=output) + setGpibState(CTRL_BITS, CTRL_BITS, 0); // Set control signal states: outputs to unasserted/HIGH, inputs to 1 (INPUT_PULLUP) + break; + } +} + + +/***** Set the transmission mode *****/ +void GPIBbus::setTransmitMode(enum transmitModes mode) { + uint8_t outputs = 0; + switch (mode) { + case TM_IDLE: + setGpibState(0, HSHK_BITS, 1); // All handshake signals to inputs + setGpibState(HSHK_BITS, HSHK_BITS, 0); // All handshake signal states to INPUT_PULLUP + break; + case TM_RECV: + outputs = (NRFD_BIT | NDAC_BIT); // Signal NRFD and NDAC, listen to DAV and EOI + setGpibState(outputs, HSHK_BITS, 1); // Set handshake inputs and outputs (0=input, 1=output) + outputs = ~outputs & HSHK_BITS; + setGpibState(outputs, HSHK_BITS, 0); // Set handshake signal states: outputs to asserted/LOW, GPIO inputs to 1 (INPUT_PULLUP) + break; + case TM_SEND: + outputs = (DAV_BIT | EOI_BIT); // Signal DAV and EOI, listen to NRFD and NDAC + setGpibState(outputs, HSHK_BITS, 1); // Set handshake inputs and outputs (0=input, 1=output) + setGpibState(HSHK_BITS, HSHK_BITS, 0); // Set handshake signal states: outputs to unasserted/HIGH, GPIO inputs to 1 (INPUT_PULLUP) + break; + } +} + + +/***** Assert an individual or group of signals *****/ +void GPIBbus::assertSignal(uint8_t sig) { + // Note: GPIO pin direction assumed set by mode + setGpibState(0, sig, 0); // Set all signals permitted by mask to LOW (asserted) +} + + +/***** Clear (unassert) an individual or group of signals *****/ +void GPIBbus::clearSignal(uint8_t sig) { + // Note: GPIO pin direction assumed set by mode + setGpibState(sig, sig, 0); // Set all signals permitted by mask to HIGH (unasserted) +} + + +/***** Clear all GPIB control signals *****/ +void GPIBbus::clearAllSignals() { + setGpibState(0, ALL_BITS, 1); // Set all signals to inputs + setGpibState(ALL_BITS, ALL_BITS, 0); // Set all GPIO pins to INPUT_PULLUP +} + + /***** Return current cinterface mode *****/ -bool GPIBbus::isController(){ +bool GPIBbus::isController() { if (cfg.cmode == 2) return true; return false; } /***** Detect selected pin state *****/ -bool GPIBbus::isAsserted(uint8_t gpibsig){ -#if defined(AR488_MCP23S17) || defined(AR488_MCP23017) +bool GPIBbus::isAsserted(uint8_t gpibsig) { +#ifdef AR488_MCP23S17 uint8_t mcpPinAssertedReg = 0; - // Use MCP function to get MCP23S17 or MCP23017 pin state. - // If interrupt flagged then update mcpPinAssertedReg register -// if (isMcpIntFlagSet()){ -//dataPort.println(F("Interrupt flagged - pin state checked")); - // Clear mcpIntA flag -// clearMcpIntFlag(); - // Get inverse of pin status at interrupt (0 = true [asserted]; 1 = false [unasserted]) - // Calling getMcpIntAPinState clears the interrupt -// mcpPinAssertedReg = ~getMcpIntAPinState(); - mcpPinAssertedReg = ~getMcpIntAReg(); -//dataPort.print(F("mcpPinAssertedReg: ")); -//dataPort.println(mcpPinAssertedReg, BIN); -// } - return (mcpPinAssertedReg & (1<"),""); - DB_PRINT(F("Before loop flags:"),""); + DB_PRINT(F("Start listen ->"), ""); + DB_PRINT(F("Before loop flags:"), ""); DB_PRINT(F("TRNb: "), txBreak); DB_PRINT(F("rEOI: "), readWithEoi); // DB_PRINT(F("ATN: "), (isAsserted(ATN ? 1 : 0)); @@ -499,18 +549,18 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte // Perform read of data (r=0: data read OK; r>0: GPIB read error); while (state == HANDSHAKE_COMPLETE) { - // Tranbreak > 0 indicates break condition + // txBreak > 0 indicates break condition if (txBreak) break; // ATN asserted - if (isAsserted(ATN)) break; + if (isAsserted(ATN_PIN)) break; // Read the next character on the GPIB bus state = readByte(&bytes[0], readWithEoi, &eoiDetected); // If IFC or ATN asserted then break here - if ( (state == IFC_ASSERTED) || (state == ATN_ASSERTED) ) break; + if ((state == IFC_ASSERTED) || (state == ATN_ASSERTED)) break; // If successfully received character if (state == HANDSHAKE_COMPLETE) { @@ -527,11 +577,11 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte // EOI detection enabled and EOI detected? if (readWithEoi) { if (eoiDetected) break; - }else{ + } else { // Has a termination sequence been found ? if (detectEndByte) { if (bytes[0] == endByte) break; - }else{ + } else { if (isTerminatorDetected(bytes, eor)) break; } } @@ -539,7 +589,7 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte // Shift last three bytes in memory bytes[2] = bytes[1]; bytes[1] = bytes[0]; - }else{ + } else { // Stop (error or timeout) break; } @@ -547,17 +597,17 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte #ifdef DEBUG_GPIBbus_RECEIVE DB_RAW_PRINTLN(); - DB_PRINT(F("After loop flags:"),""); -// DB_PRINT(F("ATN: "), (isAsserted(ATN ? 1 : 0)); + DB_PRINT(F("After loop flags:"), ""); + // DB_PRINT(F("ATN: "), (isAsserted(ATN ? 1 : 0)); DB_PRINT(F("TMO: "), r); DB_PRINT(F("Bytes read: "), x); - DB_PRINT(F("<- End listen."),""); + DB_PRINT(F("<- End listen."), ""); #endif // Detected that EOI has been asserted if (eoiDetected) { #ifdef DEBUG_GPIBbus_RECEIVE - DB_PRINT(F("EOI detected!"),""); + DB_PRINT(F("EOI detected!"), ""); #endif // If eot_enabled then add EOT character if (cfg.eot_en) dataStream.print(cfg.eot_ch); @@ -565,9 +615,9 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte // Verbose timeout error #ifdef DEBUG_GPIBbus_RECEIVE - if ( state != HANDSHAKE_COMPLETE) { - DB_PRINT(F("Timeout waiting for sender!"),""); - DB_PRINT(F("Timeout waiting for transfer to complete!"),""); + if (state != HANDSHAKE_COMPLETE) { + DB_PRINT(F("Timeout waiting for sender!"), ""); + DB_PRINT(F("Timeout waiting for transfer to complete!"), ""); } #endif @@ -577,7 +627,7 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte // Untalk bus and unlisten controller if (unAddressDevice()) { #ifdef DEBUG_GPIBbus_RECEIVE - DB_PRINT(F("Failed to untalk bus"),""); + DB_PRINT(F("Failed to untalk bus"), ""); #endif } @@ -593,26 +643,25 @@ bool GPIBbus::receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte if (txBreak) txBreak = false; #ifdef DEBUG_GPIBbus_RECEIVE - DB_PRINT(F("done."),""); + DB_PRINT(F("done."), ""); #endif if (state == HANDSHAKE_COMPLETE) { return OK; - }else{ + } else { return ERR; } - } /***** Send a series of characters as data to the GPIB bus *****/ void GPIBbus::sendData(char *data, uint8_t dsize) { -// bool err = false; + // bool err = false; uint8_t tc; enum gpibHandshakeStates state; - switch(cfg.eos) { + switch (cfg.eos) { case 1: case 2: tc = 1; @@ -630,10 +679,10 @@ void GPIBbus::sendData(char *data, uint8_t dsize) { } else { setControls(DTAS); } - + #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("write data mode is set."),""); - DB_PRINT(F("Begin send loop ->"),""); + DB_PRINT(F("write data mode is set."), ""); + DB_PRINT(F("Begin send loop ->"), ""); #endif // Write the data string @@ -642,15 +691,15 @@ void GPIBbus::sendData(char *data, uint8_t dsize) { if (cfg.eoi) { // Send all characters if (tc) { - state = writeByte( data[i], NO_EOI); // Send EOI with terminator - }else{ - state = writeByte( data[i], (i == (dsize-1)) ); // Send EOI on last character + state = writeByte(data[i], NO_EOI); // Send EOI with terminator + } else { + state = writeByte(data[i], (i == (dsize - 1))); // Send EOI on last character } } else { // Otherwise ignore non-escaped CR, LF and ESC if ((data[i] != CR) && (data[i] != LF) && (data[i] != ESC)) state = writeByte(data[i], NO_EOI); } - + #ifdef DEBUG_GPIBbus_SEND DB_RAW_PRINT(data[i]); #endif @@ -659,22 +708,22 @@ void GPIBbus::sendData(char *data, uint8_t dsize) { } #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("<- End of send loop."),""); + DB_PRINT(F("<- End of send loop."), ""); #endif // Terminators and EOI - if ( (state == HANDSHAKE_COMPLETE) && tc ) { - switch (cfg.eos) { + if ((state == HANDSHAKE_COMPLETE) && tc) { + switch (cfg.eos) { case 1: writeByte(CR, cfg.eoi); #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("appended CR"), (cfg.eoi ? " with EOI" : "") ); + DB_PRINT(F("appended CR"), (cfg.eoi ? " with EOI" : "")); #endif break; case 2: writeByte(LF, cfg.eoi); #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("appended LF"),(cfg.eoi ? " with EOI" : "") ); + DB_PRINT(F("appended LF"), (cfg.eoi ? " with EOI" : "")); #endif break; case 3: @@ -683,23 +732,22 @@ void GPIBbus::sendData(char *data, uint8_t dsize) { writeByte(CR, NO_EOI); writeByte(LF, cfg.eoi); #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("appended CRLF"), (cfg.eoi ? " with EOI" : "") ); + DB_PRINT(F("appended CRLF"), (cfg.eoi ? " with EOI" : "")); #endif } } - if (cfg.cmode == 2) { // Controller mode + if (cfg.cmode == 2) { // Controller mode // Controller - set lines to idle setControls(CIDS); - }else{ // Device mode + } else { // Device mode // Set control lines to idle setControls(DIDS); } #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("done."),""); + DB_PRINT(F("done."), ""); #endif - } @@ -720,7 +768,7 @@ void GPIBbus::sendData(char *data, uint8_t dsize) { /***** Signal to break a GPIB transmission *****/ -void GPIBbus::signalBreak(){ +void GPIBbus::signalBreak() { txBreak = true; } @@ -740,147 +788,151 @@ void GPIBbus::setControls(uint8_t state) { // Controller states case CINI: // Initialisation - // Set pin direction - setGpibState(0b10111000, 0b11111111, 1); - // Set pin state - setGpibState(0b11011111, 0b11111111, 0); + setOperatingMode(OP_CTRL); + setTransmitMode(TM_IDLE); + assertSignal(REN_BIT); #ifdef SN7516X - digitalWrite(SN7516X_TE,LOW); - #ifdef SN7516X_DC - digitalWrite(SN7516X_DC,LOW); - #endif - #ifdef SN7516X_SC - digitalWrite(SN7516X_SC,HIGH); - #endif -#endif + digitalWrite(SN7516X_TE, LOW); +#ifdef SN7516X_DC + digitalWrite(SN7516X_DC, LOW); +#endif +#ifdef SN7516X_SC + digitalWrite(SN7516X_SC, HIGH); +#endif +#endif #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Initialised GPIB control mode"),""); + DB_PRINT(F("Initialised GPIB control mode"), ""); #endif break; + case CIDS: // Controller idle state - setGpibState(0b10111000, 0b10011110, 1); - setGpibState(0b11011111, 0b10011110, 0); + setTransmitMode(TM_IDLE); + clearSignal(ATN_BIT); #ifdef SN7516X - digitalWrite(SN7516X_TE,LOW); -#endif + digitalWrite(SN7516X_TE, LOW); +#endif #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines to idle state"),""); + DB_PRINT(F("Set GPIB lines to idle state"), ""); #endif break; + case CCMS: // Controller active - send commands - setGpibState(0b10111001, 0b10011111, 1); - setGpibState(0b01011111, 0b10011111, 0); + setTransmitMode(TM_SEND); + assertSignal(ATN_BIT); #ifdef SN7516X - digitalWrite(SN7516X_TE,HIGH); -#endif + digitalWrite(SN7516X_TE, HIGH); +#endif #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines for sending a command"),""); + DB_PRINT(F("Set GPIB lines for sending a command"), ""); #endif break; + case CLAS: // Controller - read data bus // Set state for receiving data - setGpibState(0b10100110, 0b10011110, 1); - setGpibState(0b11011000, 0b10011110, 0); + setTransmitMode(TM_RECV); + clearSignal(ATN_BIT); #ifdef SN7516X - digitalWrite(SN7516X_TE,LOW); -#endif + digitalWrite(SN7516X_TE, LOW); +#endif #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines for reading data"),""); + DB_PRINT(F("Set GPIB lines for reading data"), ""); #endif break; + case CTAS: // Controller - write data bus - setGpibState(0b10111001, 0b10011110, 1); - setGpibState(0b11011111, 0b10011110, 0); + setTransmitMode(TM_SEND); + clearSignal(ATN_BIT); #ifdef SN7516X - digitalWrite(SN7516X_TE,HIGH); -#endif + digitalWrite(SN7516X_TE, HIGH); +#endif #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines for writing data"),""); + DB_PRINT(F("Set GPIB lines for writing data"), ""); #endif break; + /* Bits control lines as follows: 8-ATN, 7-SRQ, 6-REN, 5-EOI, 4-DAV, 3-NRFD, 2-NDAC, 1-IFC */ // Listener states case DINI: // Listner initialisation + + #ifdef SN7516X - digitalWrite(SN7516X_TE,HIGH); - #ifdef SN7516X_DC - digitalWrite(SN7516X_DC,HIGH); - #endif - #ifdef SN7516X_SC - digitalWrite(SN7516X_SC,LOW); - #endif -#endif - setGpibState(0b00000000, 0b11111111, 1); - setGpibState(0b11111111, 0b11111111, 0); + digitalWrite(SN7516X_TE, HIGH); +#ifdef SN7516X_DC + digitalWrite(SN7516X_DC, HIGH); +#endif +#ifdef SN7516X_SC + digitalWrite(SN7516X_SC, LOW); +#endif +#endif + clearAllSignals(); + setOperatingMode(OP_DEVI); // Set data bus to idle state readyGpibDbus(); #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Initialised GPIB listener mode"),""); + DB_PRINT(F("Initialised GPIB listener mode"), ""); #endif break; + case DIDS: // Device idle state #ifdef SN7516X - digitalWrite(SN7516X_TE,HIGH); -#endif - setGpibState(0b00000000, 0b00001110, 1); - setGpibState(0b11111111, 0b00001110, 0); + digitalWrite(SN7516X_TE, HIGH); +#endif + setTransmitMode(TM_IDLE); // Set data bus to idle state readyGpibDbus(); #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines to idle state"),""); + DB_PRINT(F("Set GPIB lines to idle state"), ""); #endif break; + case DLAS: // Device listner active (actively listening - can handshake) #ifdef SN7516X - digitalWrite(SN7516X_TE,LOW); -#endif - setGpibState(0b00000110, 0b00011110, 1); - setGpibState(0b11111001, 0b00011110, 0); + digitalWrite(SN7516X_TE, LOW); +#endif + setTransmitMode(TM_RECV); #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines to idle state"),""); + DB_PRINT(F("Set GPIB lines to idle state"), ""); #endif break; + case DTAS: // Device talker active (sending data) #ifdef SN7516X - digitalWrite(SN7516X_TE,HIGH); -#endif - setGpibState(0b00011000, 0b00011110, 1); - setGpibState(0b11111001, 0b00011110, 0); + digitalWrite(SN7516X_TE, HIGH); +#endif + setTransmitMode(TM_SEND); #ifdef DEBUG_GPIBbus_CONTROL - DB_PRINT(F("Set GPIB lines for listening as addresed device"),""); + DB_PRINT(F("Set GPIB lines for listening as addresed device"), ""); #endif break; #ifdef DEBUG_GPIBbus_CONTROL default: // Should never get here! - // setGpibState(0b00000110, 0b10111001, 0b11111111); - DB_PRINT(F("Unknown GPIB state requested!"),""); + DB_PRINT(F("Unknown GPIB state requested!"), ""); #endif } // Save state cstate = state; - } /***** Set GPI control state using numeric input (xdiag_h) *****/ -void GPIBbus::setControlVal(uint8_t value, uint8_t mask, uint8_t mode){ +void GPIBbus::setControlVal(uint8_t value, uint8_t mask, uint8_t mode) { setGpibState(value, mask, mode); } /***** Set GPIB data bus to specific value (xdiag_h) *****/ -void GPIBbus::setDataVal(uint8_t value){ +void GPIBbus::setDataVal(uint8_t value) { setGpibDbus(value); } @@ -895,7 +947,7 @@ bool GPIBbus::unAddressDevice() { // Clear flag deviceAddressed = false; #ifdef DEBUG_GPIBbus_DEVICE - DB_PRINT(F("done."),""); + DB_PRINT(F("done."), ""); #endif return OK; } @@ -906,10 +958,10 @@ bool GPIBbus::unAddressDevice() { * talk: false=listen; true=talk; */ bool GPIBbus::addressDevice(uint8_t addr, bool talk) { -// uint8_t saddr = 0; + // uint8_t saddr = 0; if (sendCmd(GC_UNL)) return ERR; #ifdef DEBUG_GPIBbus_DEVICE - DB_PRINT(F("addressDevice: "),addr); + DB_PRINT(F("addressDevice: "), addr); #endif if (talk) { // Device to talk, controller to listen @@ -929,36 +981,36 @@ bool GPIBbus::addressDevice(uint8_t addr, bool talk) { /* * true = device addressed; false = device is not addressed */ -bool GPIBbus::haveAddressedDevice(){ +bool GPIBbus::haveAddressedDevice() { return deviceAddressed; } /***** Device is addressed to listen? *****/ -bool GPIBbus::isDeviceAddressedToListen(){ -// if (deviceAddressedState == DLAS) return true; +bool GPIBbus::isDeviceAddressedToListen() { + // if (deviceAddressedState == DLAS) return true; if (cstate == DLAS) return true; return false; } /***** Device is addressed to talk? *****/ -bool GPIBbus::isDeviceAddressedToTalk(){ -// if (deviceAddressedState == DTAS) return true; +bool GPIBbus::isDeviceAddressedToTalk() { + // if (deviceAddressedState == DTAS) return true; if (cstate == DTAS) return true; return false; } /***** Device is not addressed? *****/ -bool GPIBbus::isDeviceInIdleState(){ +bool GPIBbus::isDeviceInIdleState() { if (cstate == DIDS) return true; return false; } -/***** Clear the data bus - set to listen state *****/ -void GPIBbus::clearDataBus(){ +/***** Clear the data bus and set to listen state *****/ +void GPIBbus::clearDataBus() { readyGpibDbus(); } @@ -975,60 +1027,59 @@ enum gpibHandshakeStates GPIBbus::readByte(uint8_t *db, bool readWithEoi, bool * const unsigned long timeval = cfg.rtmo; enum gpibHandshakeStates gpibState = HANDSHAKE_START; - bool atnStat = isAsserted(ATN); // Capture state of ATN + bool atnStat = isAsserted(ATN_PIN); // Capture state of ATN *eoi = false; // Wait for interval to expire - while ( (unsigned long)(currentMillis - startMillis) < timeval ) { + while ((unsigned long)(currentMillis - startMillis) < timeval) { if (cfg.cmode == 1) { // If IFC has been asserted then abort - if (isAsserted(IFC)) { + if (isAsserted(IFC_PIN)) { #ifdef DEBUG_GPIBbus_RECEIVE - DB_PRINT(F("IFC detected]"),""); + DB_PRINT(F("IFC detected]"), ""); #endif gpibState = IFC_ASSERTED; break; } // ATN unasserted during handshake - not ready yet so abort (and exit ATN loop) - if ( atnStat && !isAsserted(ATN) ){ + if (atnStat && !isAsserted(ATN_PIN)) { gpibState = ATN_ASSERTED; break; } - } - if (gpibState == HANDSHAKE_START){ + if (gpibState == HANDSHAKE_START) { // Unassert NRFD (we are ready for more data) - setGpibState(0b00000100, 0b00000100, 0); + clearSignal(NRFD_BIT); gpibState = WAIT_FOR_DATA; } - if (gpibState == WAIT_FOR_DATA){ + if (gpibState == WAIT_FOR_DATA) { // Wait for DAV to go LOW indicating talker has finished setting data lines.. - if (getGpibPinState(DAV) == LOW) { + if (getGpibPinState(DAV_PIN) == LOW) { // Assert NRFD (Busy reading data) - setGpibState(0b00000000, 0b00000100, 0); + assertSignal(NRFD_BIT); gpibState = READ_DATA; } } if (gpibState == READ_DATA) { // Check for EOI signal - if (readWithEoi && isAsserted(EOI)) *eoi = true; + if (readWithEoi && isAsserted(EOI_PIN)) *eoi = true; // read from DIO *db = readGpibDbus(); // Unassert NDAC signalling data accepted - setGpibState(0b00000010, 0b00000010, 0); + clearSignal(NDAC_BIT); gpibState = DATA_ACCEPTED; } if (gpibState == DATA_ACCEPTED) { // Wait for DAV to go HIGH indicating data no longer valid (i.e. transfer complete) - if (getGpibPinState(DAV) == HIGH) { + if (getGpibPinState(DAV_PIN) == HIGH) { // Re-assert NDAC - handshake complete, ready to accept data again - setGpibState(0b00000000, 0b00000010, 0); + assertSignal(NDAC_BIT); gpibState = HANDSHAKE_COMPLETE; break; } @@ -1036,20 +1087,18 @@ enum gpibHandshakeStates GPIBbus::readByte(uint8_t *db, bool readWithEoi, bool * // Increment time currentMillis = millis(); - } // Otherwise return stage #ifdef DEBUG_GPIBbus_RECEIVE - if ( (gpibState == HANDSHAKE_STARTED) || (gpibState == UNASSERTED_NDAC) ) { - DB_PRINT(F("DAV timout!"),""); - }else{ + if ((gpibState == HANDSHAKE_STARTED) || (gpibState == UNASSERTED_NDAC)) { + DB_PRINT(F("DAV timout!"), ""); + } else { DB_PRINT(F("Handshake error!")); } #endif return gpibState; - } @@ -1060,24 +1109,24 @@ enum gpibHandshakeStates GPIBbus::writeByte(uint8_t db, bool isLastByte) { enum gpibHandshakeStates gpibState = HANDSHAKE_START; // Wait for interval to expire - while ( (unsigned long)(currentMillis - startMillis) < timeval ) { + while ((unsigned long)(currentMillis - startMillis) < timeval) { if (cfg.cmode == 1) { // If IFC has been asserted then abort - if (isAsserted(IFC)) { + if (isAsserted(IFC_PIN)) { setControls(DLAS); #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("IFC detected!"),""); + DB_PRINT(F("IFC detected!"), ""); #endif gpibState = IFC_ASSERTED; break; } // If ATN has been asserted we need to abort and listen - if (isAsserted(ATN)) { + if (isAsserted(ATN_PIN)) { setControls(DLAS); #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("ATN detected!"),""); + DB_PRINT(F("ATN detected!"), ""); #endif gpibState = ATN_ASSERTED; break; @@ -1086,38 +1135,38 @@ enum gpibHandshakeStates GPIBbus::writeByte(uint8_t db, bool isLastByte) { // Wait for NDAC to go LOW (indicating that devices (stage==4) || (stage==8) ) are at attention) if (gpibState == HANDSHAKE_START) { - if (getGpibPinState(NDAC) == LOW) gpibState = WAIT_FOR_RECEIVER_READY; + if (getGpibPinState(NDAC_PIN) == LOW) gpibState = WAIT_FOR_RECEIVER_READY; } // Wait for NRFD to go HIGH (indicating that receiver is ready) - if (gpibState == WAIT_FOR_RECEIVER_READY){ - if (getGpibPinState(NRFD) == HIGH) gpibState = PLACE_DATA; + if (gpibState == WAIT_FOR_RECEIVER_READY) { + if (getGpibPinState(NRFD_PIN) == HIGH) gpibState = PLACE_DATA; } - if (gpibState == PLACE_DATA){ + if (gpibState == PLACE_DATA) { // Place data on the bus setGpibDbus(db); if (cfg.eoi && isLastByte) { // If EOI enabled and this is the last byte then assert DAV and EOI #ifdef DEBUG_GPIBbus_SEND - DB_PRINT(F("Asserting EOI..."),""); + DB_PRINT(F("Asserting EOI..."), ""); #endif - setGpibState(0b00000000, 0b00011000, 0); - }else{ + assertSignal(DAV_BIT | EOI_BIT); + } else { // Assert DAV (data is valid - ready to collect) - setGpibState(0b00000000, 0b00001000, 0); + assertSignal(DAV_BIT); } gpibState = DATA_READY; } - if (gpibState == DATA_READY){ + if (gpibState == DATA_READY) { // Wait for NRFD to go LOW (receiver accepting data) - if (getGpibPinState(NRFD) == LOW) gpibState = RECEIVER_ACCEPTING; + if (getGpibPinState(NRFD_PIN) == LOW) gpibState = RECEIVER_ACCEPTING; } - if (gpibState == RECEIVER_ACCEPTING){ + if (gpibState == RECEIVER_ACCEPTING) { // Wait for NDAC to go HIGH (data accepted) - if (getGpibPinState(NDAC) == HIGH) { + if (getGpibPinState(NDAC_PIN) == HIGH) { gpibState = HANDSHAKE_COMPLETE; break; } @@ -1125,17 +1174,16 @@ enum gpibHandshakeStates GPIBbus::writeByte(uint8_t db, bool isLastByte) { // Increment time currentMillis = millis(); - } // Handshake complete - if (gpibState == HANDSHAKE_COMPLETE){ + if (gpibState == HANDSHAKE_COMPLETE) { if (cfg.eoi && isLastByte) { // If EOI enabled and this is the last byte then un-assert both DAV and EOI - setGpibState(0b00011000, 0b00011000, 0); - }else{ + clearSignal(DAV_BIT | EOI_BIT); + } else { // Unassert DAV - setGpibState(0b00001000, 0b00001000, 0); + clearSignal(DAV_BIT); } // Reset the data bus setGpibDbus(0); @@ -1146,19 +1194,19 @@ enum gpibHandshakeStates GPIBbus::writeByte(uint8_t db, bool isLastByte) { #ifdef DEBUG_GPIBbus_SEND switch (gpibState) { case HANDSHAKE_START: - DB_PRINT(F("NDAC LO timeout!"),""); + DB_PRINT(F("NDAC LO timeout!"), ""); break; case WAIT_FOR_RECEIVER_READY: - DB_PRINT(F("NRFD HI timout!"),""); + DB_PRINT(F("NRFD HI timout!"), ""); break; case DATA_READY: - DB_PRINT(F("NRFD LO timout!"),""); + DB_PRINT(F("NRFD LO timout!"), ""); break; case RECEIVER_ACCEPTING: - DB_PRINT(F("NDAC HI timout!"),""); + DB_PRINT(F("NDAC HI timout!"), ""); break; default: - DB_PRINT(F("Handshake error!"),""); + DB_PRINT(F("Handshake error!"), ""); } #endif @@ -1183,61 +1231,45 @@ enum gpibHandshakeStates GPIBbus::writeByte(uint8_t db, bool isLastByte) { /***** Check for terminator *****/ -bool GPIBbus::isTerminatorDetected(uint8_t bytes[3], uint8_t eorSequence){ +bool GPIBbus::isTerminatorDetected(uint8_t bytes[3], uint8_t eorSequence) { // Look for specified terminator (CR+LF by default) switch (eorSequence) { case 0: - // CR+LF terminator - if (bytes[0]==LF && bytes[1]==CR) return true; - break; + // CR+LF terminator + if (bytes[0] == LF && bytes[1] == CR) return true; + break; case 1: - // CR only as terminator - if (bytes[0]==CR) return true; - break; + // CR only as terminator + if (bytes[0] == CR) return true; + break; case 2: - // LF only as terminator - if (bytes[0]==LF) return true; - break; + // LF only as terminator + if (bytes[0] == LF) return true; + break; case 3: - // No terminator (will rely on timeout) - break; + // No terminator (will rely on timeout) + break; case 4: - // Keithley can use LF+CR instead of CR+LF - if (bytes[0]==CR && bytes[1]==LF) return true; - break; + // Keithley can use LF+CR instead of CR+LF + if (bytes[0] == CR && bytes[1] == LF) return true; + break; case 5: - // Solarton (possibly others) can also use ETX (0x03) - if (bytes[0]==0x03) return true; - break; + // Solarton (possibly others) can also use ETX (0x03) + if (bytes[0] == 0x03) return true; + break; case 6: - // Solarton (possibly others) can also use CR+LF+ETX (0x03) - if (bytes[0]==0x03 && bytes[1]==LF && bytes[2]==CR) return true; - break; + // Solarton (possibly others) can also use CR+LF+ETX (0x03) + if (bytes[0] == 0x03 && bytes[1] == LF && bytes[2] == CR) return true; + break; default: - // Use CR+LF terminator by default - if (bytes[0]==LF && bytes[1]==CR) return true; - break; + // Use CR+LF terminator by default + if (bytes[0] == LF && bytes[1] == CR) return true; + break; } return false; } -/***** Set the SRQ signal *****/ -void GPIBbus::setSrqSig() { - // Set SRQ line to OUTPUT HIGH (asserted) - setGpibState(0b01000000, 0b01000000, 1); - setGpibState(0b00000000, 0b01000000, 0); -} - - -/***** Clear the SRQ signal *****/ -void GPIBbus::clrSrqSig() { - // Set SRQ line to INPUT_PULLUP (un-asserted) - setGpibState(0b00000000, 0b01000000, 1); - setGpibState(0b01000000, 0b01000000, 0); -} - - /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ /***** GPIB CLASS PRIVATE FUNCTIONS *****/ /****************************************/ diff --git a/src/AR488/AR488_GPIBbus.h b/src/AR488/AR488_GPIBbus.h index 6838366..68c750d 100644 --- a/src/AR488/AR488_GPIBbus.h +++ b/src/AR488/AR488_GPIBbus.h @@ -7,12 +7,12 @@ #include "AR488_ComPorts.h" #ifdef EN_STORAGE - #ifdef EN_TEK_4924 - #include "AR488_Store_Tek_4924.h" - #endif +#ifdef EN_TEK_4924 +#include "AR488_Store_Tek_4924.h" +#endif #endif -/***** AR488_GPIBbus.cpp, ver. 0.51.20, 16/12/2023 *****/ +/***** AR488_GPIBbus.cpp, ver. 0.51.25, 21/12/2023 *****/ /*********************************************/ @@ -23,49 +23,48 @@ /***** Debug Port *****/ #ifdef DB_SERIAL_ENABLE - extern Stream& debugStream; - /* Configured in Config.h */ - //#define DEBUG_GPIBbus_RECEIVE - //#define DEBUG_GPIBbus_SEND - //#define DEBUG_GPIBbus_CONTROL - //#define SN7516X - /* Configured in Config.h */ +extern Stream &debugStream; +/* Configured in Config.h */ +//#define DEBUG_GPIBbus_RECEIVE +//#define DEBUG_GPIBbus_SEND +//#define DEBUG_GPIBbus_CONTROL +//#define SN7516X +/* Configured in Config.h */ #endif /***** Universal Multiline commands (apply to all devices) *****/ +#define GC_GTL 0x01 +#define GC_SDC 0x04 +#define GC_PPC 0x05 +#define GC_GET 0x08 +#define GC_TCT 0x09 #define GC_LLO 0x11 #define GC_DCL 0x14 #define GC_PPU 0x15 #define GC_SPE 0x18 #define GC_SPD 0x19 +#define GC_LAD 0x20 #define GC_UNL 0x3F +#define GC_UNT 0x5F #define GC_TAD 0x40 #define GC_PPE 0x60 #define GC_PPD 0x70 -#define GC_UNT 0x5F -// Address commands -#define GC_LAD 0x20 -// Addressed commands -#define GC_GTL 0x01 -#define GC_SDC 0x04 -#define GC_PPC 0x05 -#define GC_GET 0x08 /***** GPIB control states *****/ // Controller mode -#define CINI 0x01 // Controller idle state -#define CIDS 0x02 // Controller idle state -#define CCMS 0x03 // Controller command state -#define CTAS 0x04 // Controller talker active state -#define CLAS 0x05 // Controller listner active state +#define CINI 0x01 // Controller idle state +#define CIDS 0x02 // Controller idle state +#define CCMS 0x03 // Controller command state +#define CTAS 0x04 // Controller talker active state +#define CLAS 0x05 // Controller listner active state // Listner/device mode -#define DINI 0x06 // Device initialise state -#define DIDS 0x07 // Device idle state -#define DLAS 0x08 // Device listener active (listening/receiving) -#define DTAS 0x09 // Device talker active (sending) state +#define DINI 0x06 // Device initialise state +#define DIDS 0x07 // Device idle state +#define DLAS 0x08 // Device listener active (listening/receiving) +#define DTAS 0x09 // Device talker active (sending) state /***** Addressing direction *****/ @@ -77,7 +76,6 @@ #define WITH_EOI true - /***** Handshake states *****/ enum gpibHandshakeStates { // Common @@ -97,6 +95,33 @@ enum gpibHandshakeStates { }; +#define IFC_BIT (1 << 0) +#define NDAC_BIT (1 << 1) +#define NRFD_BIT (1 << 2) +#define DAV_BIT (1 << 3) +#define EOI_BIT (1 << 4) +#define REN_BIT (1 << 5) +#define SRQ_BIT (1 << 6) +#define ATN_BIT (1 << 7) +#define CTRL_BITS (0xE1) +#define HSHK_BITS (0x1E) +#define ALL_BITS (0xFF) + + +enum operatingModes { + OP_IDLE, + OP_CTRL, + OP_DEVI +}; + + +enum transmitModes { + TM_IDLE, + TM_RECV, + TM_SEND +}; + + /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ /***** GPIB COMMAND & STATUS DEFINITIONS *****/ /*********************************************/ @@ -109,106 +134,104 @@ enum gpibHandshakeStates { class GPIBbus { - public: - - /***** Controller configuration *****/ - union GPIBconf{ - struct{ - bool eot_en; // Enable/disable append EOT char to string received from GPIB bus before sending to USB - bool eoi; // Assert EOI on last data char written to GPIB - 0-disable, 1-enable - uint8_t cmode; // Controller/device mode (0=unset, 1=device, 2=controller) - uint8_t caddr; // This interface address - uint8_t paddr; // Primary address to use when addressing device - uint8_t saddr; // Secondary address to use when addressing device - uint8_t eos; // EOS (end of send to GPIB) characters [0=CRLF, 1=CR, 2=LF, 3=None] - uint8_t stat; // Status byte to return in response to a serial poll - uint8_t amode; // Auto mode setting (0=off; 1=Prologix; 2=onquery; 3=continuous); - int rtmo; // Read timout (read_tmo_ms) in milliseconds - 0-3000 - value depends on instrument - char eot_ch; // EOT character to append to USB output when EOI signal detected - char vstr[48]; // Custom version string - uint8_t eor; // EOR (end of receive from GPIB instrument) characters [0=CRLF, 1=CR, 2=LF, 3=None, 4=LFCR, 5=ETX, 6=CRLF+ETX, 7=SPACE] - char sname[16]; // Interface short name - uint32_t serial; // Serial number - uint8_t idn; // Send ID in response to *idn? 0=disable, 1=send name; 2=send name+serial - }; - uint8_t db[GPIB_CFG_SIZE]; +public: + + /***** Controller configuration *****/ + union GPIBconf { + struct { + bool eot_en; // Enable/disable append EOT char to string received from GPIB bus before sending to USB + bool eoi; // Assert EOI on last data char written to GPIB - 0-disable, 1-enable + uint8_t cmode; // Controller/device mode (0=unset, 1=device, 2=controller) + uint8_t caddr; // This interface address + uint8_t paddr; // Primary address to use when addressing device + uint8_t saddr; // Secondary address to use when addressing device + uint8_t eos; // EOS (end of send to GPIB) characters [0=CRLF, 1=CR, 2=LF, 3=None] + uint8_t stat; // Status byte to return in response to a serial poll + uint8_t amode; // Auto mode setting (0=off; 1=Prologix; 2=onquery; 3=continuous); + int rtmo; // Read timout (read_tmo_ms) in milliseconds - 0-3000 - value depends on instrument + char eot_ch; // EOT character to append to USB output when EOI signal detected + char vstr[48]; // Custom version string + uint8_t eor; // EOR (end of receive from GPIB instrument) characters [0=CRLF, 1=CR, 2=LF, 3=None, 4=LFCR, 5=ETX, 6=CRLF+ETX, 7=SPACE] + char sname[16]; // Interface short name + uint32_t serial; // Serial number + uint8_t idn; // Send ID in response to *idn? 0=disable, 1=send name; 2=send name+serial }; + uint8_t db[GPIB_CFG_SIZE]; + }; + + union GPIBconf cfg; + + uint8_t cstate = 0; + + GPIBbus(); + + void begin(); + void stop(); + + void setDefaultCfg(); + + void startControllerMode(); + void startDeviceMode(); + + void setOperatingMode(enum operatingModes mode); + void setTransmitMode(enum transmitModes mode); + void assertSignal(uint8_t sig); + void clearSignal(uint8_t sig); + void clearAllSignals(); + + + bool isController(); + + void sendIFC(); + bool sendLLO(); + bool sendGTL(); + bool sendGET(uint8_t addr); + bool sendSDC(); + bool sendTCT(uint8_t addr); + void sendAllClear(); + + bool sendUNT(); + bool sendUNL(); + bool sendMTA(); + bool sendMLA(); + bool sendMSA(uint8_t addr); + + bool isAsserted(uint8_t gpibsig); + void setControls(uint8_t state); + void sendStatus(); + + void setStatus(uint8_t statusByte); + bool sendCmd(uint8_t cmdByte); + enum gpibHandshakeStates readByte(uint8_t *db, bool readWithEoi, bool *eoi); + enum gpibHandshakeStates writeByte(uint8_t db, bool isLastByte); + bool receiveData(Stream &dataStream, bool detectEoi, bool detectEndByte, uint8_t endByte); + void sendData(char *data, uint8_t dsize); + void clearDataBus(); + void setControlVal(uint8_t value, uint8_t mask, uint8_t mode); + void setDataVal(uint8_t); + + bool isDeviceAddressedToListen(); + bool isDeviceAddressedToTalk(); + bool isDeviceInIdleState(); + + void signalBreak(); + + bool addressDevice(uint8_t addr, bool dir); + bool unAddressDevice(); + bool haveAddressedDevice(); + +private: + + bool txBreak; // Signal to break the GPIB transmission + bool deviceAddressed; + bool isTerminatorDetected(uint8_t bytes[3], uint8_t eorSequence); - union GPIBconf cfg; - -// WORK REQUIRED! - bool txBreak; // Signal to break the GPIB transmission -// WORK REQUIRED! - - uint8_t cstate = 0; - - GPIBbus(); - - void begin(); - void stop(); - - void setDefaultCfg(); - - void startControllerMode(); - void startDeviceMode(); - bool isController(); - - void sendIFC(); - bool sendLLO(); - bool sendGTL(); - bool sendGET(uint8_t addr); - bool sendSDC(); - void sendAllClear(); - - bool sendUNT(); - bool sendUNL(); - bool sendMTA(); - bool sendMLA(); - bool sendMSA(uint8_t addr); - - bool isAsserted(uint8_t gpibsig); - void setControls(uint8_t state); - void sendStatus(); - - void setStatus(uint8_t statusByte); - bool sendCmd(uint8_t cmdByte); - enum gpibHandshakeStates readByte(uint8_t *db, bool readWithEoi, bool *eoi); - enum gpibHandshakeStates writeByte(uint8_t db, bool isLastByte); - bool receiveData(Stream& dataStream, bool detectEoi, bool detectEndByte, uint8_t endByte); - void sendData(char *data, uint8_t dsize); - void clearDataBus(); - void setControlVal(uint8_t value, uint8_t mask, uint8_t mode); - void setDataVal(uint8_t); - -// void setDeviceAddressedState(uint8_t stat); - bool isDeviceAddressedToListen(); - bool isDeviceAddressedToTalk(); - bool isDeviceInIdleState(); - - void signalBreak(); - - bool addressDevice(uint8_t addr, bool dir); - bool unAddressDevice(); - bool haveAddressedDevice(); - - private: - - bool deviceAddressed; -// uint8_t deviceAddressedState; - -// bool writeByteHandshake(uint8_t db); -// boolean waitOnPinState(uint8_t state, uint8_t pin, int interval); - bool isTerminatorDetected(uint8_t bytes[3], uint8_t eorSequence); - void setSrqSig(); - void clrSrqSig(); - - // Interrupt flag for MCP23S17 -#if defined(AR488_MCP23S17) || defined(AR488_MCP23017) -// extern volatile bool mcpIntA; // MCP23x17 interrupt handler + // Interrupt flag for MCP23S17 +#ifdef AR488_MCP23S17 +// extern volatile bool mcpIntA; // MCP23S17 interrupt handler // uint8_t mcpPinAssertedReg = 0; #endif - }; -#endif // AR488_GPIBbus_H +#endif // AR488_GPIBbus_H diff --git a/src/AR488/AR488_Layouts.cpp b/src/AR488/AR488_Layouts.cpp index 796cc56..c9d1435 100644 --- a/src/AR488/AR488_Layouts.cpp +++ b/src/AR488/AR488_Layouts.cpp @@ -3,14 +3,14 @@ #include "AR488_Config.h" #include "AR488_Layouts.h" -/***** AR488_Hardware.cpp, ver. 0.51.18, 26/02/2023 *****/ +/***** AR488_Hardware.cpp, ver. 0.51.26, 24/12/2023 *****/ /* * Hardware layout function definitions */ /* -volatile bool isATN = false; // has ATN been asserted? -volatile bool isSRQ = false; // has SRQ been asserted? +volatile bool isATN_PIN = false; // has ATN_PIN been asserted? +volatile bool isSRQ_PIN = false; // has SRQ_PIN been asserted? */ /*********************************/ @@ -54,19 +54,19 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Uno/Nano pin to Port/bit to direction/state byte map: - IFC 8 PORTB bit 0 byte bit 0 - NDAC 9 PORTB bit 1 byte bit 1 - NRFD 10 PORTB bit 2 byte bit 2 - DAV 11 PORTB bit 3 byte bit 3 - EOI 12 PORTB bit 4 byte bit 4 - SRQ 2 PORTD bit 2 byte bit 6 - REN 3 PORTD bit 3 byte bit 5 - ATN 7 PORTD bit 8 byte bit 7 + IFC_PIN 8 PORTB bit 0 byte bit 0 + NDAC_PIN 9 PORTB bit 1 byte bit 1 + NRFD_PIN 10 PORTB bit 2 byte bit 2 + DAV_PIN 11 PORTB bit 3 byte bit 3 + EOI_PIN 12 PORTB bit 4 byte bit 4 + SRQ_PIN 2 PORTD bit 2 byte bit 6 + REN_PIN 3 PORTD bit 3 byte bit 5 + ATN_PIN 7 PORTD bit 8 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -138,20 +138,20 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Mega 2560 Layout D pin to Port/bit to direction/state byte map: - IFC 17 PORTH bit 0 byte bit 0 - NDAC 16 PORTH bit 1 byte bit 1 - NRFD 6 PORTH bit 3 byte bit 2 - DAV 7 PORTH bit 4 byte bit 3 - EOI 8 PORTH bit 5 byte bit 4 - REN 9 PORTH bit 6 byte bit 5 + IFC_PIN 17 PORTH bit 0 byte bit 0 + NDAC_PIN 16 PORTH bit 1 byte bit 1 + NRFD_PIN 6 PORTH bit 3 byte bit 2 + DAV_PIN 7 PORTH bit 4 byte bit 3 + EOI_PIN 8 PORTH bit 5 byte bit 4 + REN_PIN 9 PORTH bit 6 byte bit 5 // These require pcint - SRQ 10 PORTB bit 4 byte bit 6 - ATN 11 PORTB bit 5 byte bit 7 + SRQ_PIN 10 PORTB bit 4 byte bit 6 + ATN_PIN 11 PORTB bit 5 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -254,20 +254,20 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Mega 2560 Layout E1 pin to Port/bit to direction/state byte map: - IFC 48 PORTL bit 1 byte bit 0 - NDAC 46 PORTL bit 3 byte bit 1 - NRFD 44 PORTL bit 5 byte bit 2 - DAV 42 PORTL bit 7 byte bit 3 - EOI 40 PORTG bit 1 byte bit 4 - REN 38 PORTD bit 7 byte bit 5 + IFC_PIN 48 PORTL bit 1 byte bit 0 + NDAC_PIN 46 PORTL bit 3 byte bit 1 + NRFD_PIN 44 PORTL bit 5 byte bit 2 + DAV_PIN 42 PORTL bit 7 byte bit 3 + EOI_PIN 40 PORTG bit 1 byte bit 4 + REN_PIN 38 PORTD bit 7 byte bit 5 // These require pcint - SRQ 50 PORTB bit 3 byte bit 6 - ATN 52 PORTB bit 1 byte bit 7 + SRQ_PIN 50 PORTB bit 3 byte bit 6 + ATN_PIN 52 PORTB bit 1 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -289,10 +289,10 @@ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { // Set PORTs using mask to avoid affecting bits that should not be affected // and calculated and masked port byte - // PORT B - bits 7 & 6 (ATN + SRQ) - // PORT D - bit 5 (REN) - // PORT G - bit 4 (EOI) - // PORT L - bits 1,3,5,7 (IFC, NDAC, NRFD, DAV) + // PORT B - bits 7 & 6 (ATN_PIN + SRQ_PIN) + // PORT D - bit 5 (REN_PIN) + // PORT G - bit 4 (EOI_PIN) + // PORT L - bits 1,3,5,7 (IFC_PIN, NDAC_PIN, NRFD_PIN, DAV_PIN) // Set registers: register = (register & ~bitmask) | (value & bitmask) // Mask: 0=unaffected; 1=to be changed @@ -389,20 +389,20 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Mega 2560 Layout E2 pin to Port/bit to direction/state byte map: - IFC 48 PORTL bit 1 byte bit 0 - NDAC 46 PORTL bit 3 byte bit 1 - NRFD 44 PORTL bit 5 byte bit 2 - DAV 42 PORTL bit 7 byte bit 3 - EOI 40 PORTG bit 1 byte bit 4 - REN 38 PORTD bit 7 byte bit 5 + IFC_PIN 48 PORTL bit 1 byte bit 0 + NDAC_PIN 46 PORTL bit 3 byte bit 1 + NRFD_PIN 44 PORTL bit 5 byte bit 2 + DAV_PIN 42 PORTL bit 7 byte bit 3 + EOI_PIN 40 PORTG bit 1 byte bit 4 + REN_PIN 38 PORTD bit 7 byte bit 5 // These require pcint - SRQ 50 PORTB bit 3 byte bit 6 - ATN 52 PORTB bit 1 byte bit 7 + SRQ_PIN 50 PORTB bit 3 byte bit 6 + ATN_PIN 52 PORTB bit 1 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -420,9 +420,9 @@ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { // Set PORTs using mask to avoid affecting bits that should not be affected // and calculated and masked port byte - // PORT B - bits 0 & 2 (ATN + SRQ) - // PORT G - bits 0 & 2 (EOI, REN) - // PORT L - bits 0,2,4,6 (IFC, NDAC, NRFD, DAV) + // PORT B - bits 0 & 2 (ATN_PIN + SRQ_PIN) + // PORT G - bits 0 & 2 (EOI_PIN, REN_PIN) + // PORT L - bits 0,2,4,6 (IFC_PIN, NDAC_PIN, NRFD_PIN, DAV_PIN) // Set registers: register = (register & ~bitmask) | (value & bitmask) // Mask: 0=unaffected; 1=to be changed @@ -464,7 +464,7 @@ void readyGpibDbus() { PORTD |= 0b10000001; // PORTD bits 7,0 input_pullup // Read the byte of data on the bus - // DIO8 -> PORTD bit 7, DIO7 -> PORTE bit 5, DIO6-DIO1 -> PORTB bit 451326 + // DIO8_PIN -> PORTD bit 7, DIO7_PIN -> PORTE bit 5, DIO6_PIN-DIO1_PIN -> PORTB bit 451326 } @@ -495,22 +495,22 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines *****/ /* - * Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + * Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction * Arduino Pro Micro pin to Port/bit to direction/state byte map: - * IFC 4 PORTD bit 4 byte bit 0 - * NDAC A3 PORTF bit 4 byte bit 1 - * NRFD A2 PORTF bit 5 byte bit 2 - * DAV A1 PORTF bit 6 byte bit 3 - * EOI A0 PORTF bit 7 byte bit 4 - * REN 5 PORTC bit 6 byte bit 5 - * SRQ 7 PORTE bit 6 byte bit 6 - * ATN 2 PORTD bit 1 byte bit 7 + * IFC_PIN 4 PORTD bit 4 byte bit 0 + * NDAC_PIN A3 PORTF bit 4 byte bit 1 + * NRFD_PIN A2 PORTF bit 5 byte bit 2 + * DAV_PIN A1 PORTF bit 6 byte bit 3 + * EOI_PIN A0 PORTF bit 7 byte bit 4 + * REN_PIN 5 PORTC bit 6 byte bit 5 + * SRQ_PIN 7 PORTE bit 6 byte bit 6 + * ATN_PIN 2 PORTD bit 1 byte bit 7 * * It would be more efficient (and easier to read the code) if the bits in the above - * control word were assigned by name to match suitable port bits : then NDAC,NRFD and DAV + * control word were assigned by name to match suitable port bits : then NDAC_PIN,NRFD_PIN and DAV_PIN * could be positioned at bits 4,5,6 to be placed in port F without shifting. */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -519,7 +519,7 @@ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { if (mask & 0b00011110) { - // PORTF - NDAC, NRFD, DAV and EOI bits 1-4 rotated into bits 4-7 + // PORTF - NDAC_PIN, NRFD_PIN, DAV_PIN and EOI_PIN bits 1-4 rotated into bits 4-7 uint8_t portFb = (bits & 0x1e) << 3; uint8_t portFm = (mask & 0x1e) << 3; @@ -540,13 +540,13 @@ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { if (mask & 0b11100001) { - // PORTC - REN bit 5 rotated into bit 6 + // PORTC - REN_PIN bit 5 rotated into bit 6 uint8_t portCb = (bits & 0x20) << 1; uint8_t portCm = (mask & 0x20) << 1; - // PORTD - IFC bit 0 rotated into bit 4 and ATN bit 7 rotated into 1 + // PORTD - IFC_PIN bit 0 rotated into bit 4 and ATN_PIN bit 7 rotated into 1 uint8_t portDb = ((bits & 0x01) << 4) | ((bits & 0x80) >> 6); uint8_t portDm = ((mask & 0x01) << 4) | ((mask & 0x80) >> 6); - // PORT E - SRQ bit 6 in bit 6 + // PORT E - SRQ_PIN bit 6 in bit 6 uint8_t portEb = (bits & 0x40); uint8_t portEm = (mask & 0x40); @@ -628,31 +628,31 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Leonardo R3 pin to Port/bit to direction/state byte map: - IFC 8 PORTB bit 4 byte bit 0 - NDAC 9 PORTB bit 5 byte bit 1 - NRFD 10 PORTB bit 6 byte bit 2 - DAV 11 PORTB bit 7 byte bit 3 - EOI 12 PORTD bit 6 byte bit 4 - SRQ 2 PORTD bit 1 byte bit 6 - REN 3 PORTD bit 0 byte bit 5 - ATN 7 PORTE bit 6 byte bit 7 + IFC_PIN 8 PORTB bit 4 byte bit 0 + NDAC_PIN 9 PORTB bit 5 byte bit 1 + NRFD_PIN 10 PORTB bit 6 byte bit 2 + DAV_PIN 11 PORTB bit 7 byte bit 3 + EOI_PIN 12 PORTD bit 6 byte bit 4 + SRQ_PIN 2 PORTD bit 1 byte bit 6 + REN_PIN 3 PORTD bit 0 byte bit 5 + ATN_PIN 7 PORTE bit 6 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { // PORTB - use bits 0 to 3, rotate bits 4 positions left to set bits 4-7 on register (pins 8-12) uint8_t portBb = ((bits & 0x0F) << 4); uint8_t portBm = ((mask & 0x0F) << 4); - // PORTD - use bit 4, rotate left 2 positions to set bit 6 on register (EOI) - // PORTD - use bit 5, rotate right 5 positions to set bit 0 on register (REN) - // PORTD - use bit 6, rotate right 5 positions to set bit 1 on register (SRQ) + // PORTD - use bit 4, rotate left 2 positions to set bit 6 on register (EOI_PIN) + // PORTD - use bit 5, rotate right 5 positions to set bit 0 on register (REN_PIN) + // PORTD - use bit 6, rotate right 5 positions to set bit 1 on register (SRQ_PIN) uint8_t portDb = ((bits & 0x10) << 2) + ((bits & 0x20) >> 5) + ((bits & 0x40) >> 5); uint8_t portDm = ((mask & 0x10) << 2) + ((mask & 0x20) >> 5) + ((mask & 0x40) >> 5); - // PORTE - use bit 7, rotate left 1 position to set bit 6 on register (ATN) + // PORTE - use bit 7, rotate left 1 position to set bit 6 on register (ATN_PIN) uint8_t portEb = ((bits & 0x80) >> 1); uint8_t portEm = ((mask & 0x80) >> 1); @@ -748,19 +748,19 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction MCP23S17 pin to Port/bit to direction/state byte map: - IFC 0 PORTA bit 0 byte bit 0 - NDAC 1 PORTA bit 1 byte bit 1 - NRFD 2 PORTA bit 2 byte bit 2 - DAV 3 PORTA bit 3 byte bit 3 - EOI 4 PORTA bit 4 byte bit 4 - REN 5 PORTA bit 5 byte bit 5 - SRQ 6 PORTA bit 6 byte bit 6 - ATN 7 PORTA bit 7 byte bit 7 + IFC_PIN 0 PORTA bit 0 byte bit 0 + NDAC_PIN 1 PORTA bit 1 byte bit 1 + NRFD_PIN 2 PORTA bit 2 byte bit 2 + DAV_PIN 3 PORTA bit 3 byte bit 3 + EOI_PIN 4 PORTA bit 4 byte bit 4 + REN_PIN 5 PORTA bit 5 byte bit 5 + SRQ_PIN 6 PORTA bit 6 byte bit 6 + ATN_PIN 7 PORTA bit 7 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -872,7 +872,7 @@ uint8_t getGpibPinState(uint8_t pin){ void mcpInterruptsEn(){ // Set to interrupt mode for compare to previous mcpByteWrite(MCPINTCONA, 0b00000000); - // Enable interrupt to detect pin state change on pins 4, 6 and 7 (EOI, SRQ and ATN) + // Enable interrupt to detect pin state change on pins 4, 6 and 7 (EOI_PIN, SRQ_PIN and ATN_PIN) mcpByteWrite(MCPINTENA, 0b11010000); } @@ -883,212 +883,6 @@ void mcpInterruptsEn(){ -/******************************************/ -/***** MCP23017 EXPANDER (I2C) LAYOUT *****/ -/***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ -#ifdef AR488_MCP23017 - -//uint8_t mcpPinAssertedReg = 0; -uint8_t mcpIntAReg = 0; - - -// MCP23017 hardware config -//const uint8_t chipSelect = MCP_SELECTPIN; -const uint8_t mcpHwAddr = MCP_ADDRESS; // MCP hardware address (must be between 0 and 7) -const uint8_t mcpI2Caddr = 0x20 | mcpHwAddr; // MCP I2C address - - -/***** Arduino interrput handler *****/ -/* - * Signals that IntA was asserted on the MCP chip - */ -bool mcpIntA = false; - - -/***** Set the GPIB data bus to input pullup *****/ -void readyGpibDbus() { - // Set data pins to input - mcpByteWrite(MCPDIRB, 0b11111111); // Port direction: 0 = output; 1 = input; - mcpByteWrite(MCPPUB, 0b11111111); // 1 = Pullup resistors enabled -} - - -/***** Read the GPIB data bus wires to collect the byte of data *****/ -uint8_t readGpibDbus() { - // Read the byte of data on the bus - return ~mcpByteRead(MCPPORTB); -} - - -/***** Set the GPIB data bus to output and with the requested byte *****/ -void setGpibDbus(uint8_t db) { - // Set data pins as outputs - mcpByteWrite(MCPDIRB, 0b00000000); // Port direction: 0 = output; 1 = input; - - // GPIB states are inverted - db = ~db; - - // Set data bus - mcpByteWrite(MCPPORTB, db); -} - - -/***** Set the direction and state of the GPIB control lines ****/ -/* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC - bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; - mask (mask) : 0=unaffected, 1=enabled - mode (mode) : 0=set pin state, 1=set pin direction - MCP23S17 pin to Port/bit to direction/state byte map: - IFC 0 PORTA bit 0 byte bit 0 - NDAC 1 PORTA bit 1 byte bit 1 - NRFD 2 PORTA bit 2 byte bit 2 - DAV 3 PORTA bit 3 byte bit 3 - EOI 4 PORTA bit 4 byte bit 4 - REN 5 PORTA bit 5 byte bit 5 - SRQ 6 PORTA bit 6 byte bit 6 - ATN 7 PORTA bit 7 byte bit 7 -*/ - -void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { - - uint8_t portAb = bits; - uint8_t portAm = mask; - - uint8_t regByte = 0; - uint8_t regMod = 0; - - - // Set registers: register = (register & ~bitmask) | (value & bitmask) - // Mask: 0=unaffected; 1=to be changed - - switch (mode) { - case 0: - // Set pin states using mask - regByte = mcpByteRead(MCPPORTA); - regMod = (regByte & ~portAm) | (portAb & portAm); - mcpByteWrite(MCPPORTA, regMod); - break; - - case 1: - // Set pin direction registers using mask - regByte = ~mcpByteRead(MCPDIRA); // Note: on MCP23S17 0 = output, 1 = input - regMod = (regByte & ~portAm) | (portAb & portAm); - mcpByteWrite(MCPDIRA, ~regMod); // Note: on MCP23S17 0 = output, 1 = input - break; - - } -} - - -/***** MCP23017 interrupt handler *****/ -/* - * Interrput pin on Arduino configure with attachInterrupt - */ -void mcpIntHandler() { -// mcpIntA = true; -// mcpPinAssertedReg = 0; -// Serial.println(F("MCP Interrupt triggered")); - mcpIntAReg = mcpByteRead(MCPINTCAPA); -} - - -uint8_t getMcpIntAReg(){ - return mcpIntAReg; -} - - -/***** Arduino backward compatibility *****/ -static inline void wiresend(uint8_t db, TwoWire *theWire) { -#if ARDUINO >= 100 - theWire->write((uint8_t)db); -#else - theWire->send(db); -#endif -} - -static inline uint8_t wirerecv(TwoWire *theWire) { -#if ARDUINO >= 100 - return theWire->read(); -#else - return theWire->receive(); -#endif -} -/***** Arduino backward compatibility *****/ - - -/***** Read from the MCP23017 *****/ -/* - * reg : register we want to read , e.g. MCPPORTA or MCPPORTB - */ -uint8_t mcpByteRead(uint8_t reg){ - uint8_t db = 0; - Wire.beginTransmission(mcpI2Caddr); -Serial.print(F("Rx addr: ")); -Serial.print(mcpI2Caddr, HEX); - wiresend(reg, &Wire); - Wire.endTransmission(); - Wire.requestFrom(mcpI2Caddr, (uint8_t)1); - db = wirerecv(&Wire); -uint8_t dbinv = ~db; -Serial.print(F("\tRCV: ")); -Serial.println(dbinv, HEX); -// return wirerecv(&Wire); - return db; -} - - -/***** Write to the MCP23017 *****/ -void mcpByteWrite(uint8_t reg, uint8_t db){ -Serial.print(F("Tx addr: ")); -Serial.print(mcpI2Caddr, HEX); - Wire.beginTransmission(mcpI2Caddr); - wiresend(reg, &Wire); - wiresend(db, &Wire); - Wire.endTransmission(); -Serial.print(F("\tWRT: ")); -Serial.print(db, HEX); -uint8_t dbinv = ~db; -Serial.print(F("\tWRTinv: ")); -Serial.println(dbinv, HEX); -} - - -/***** Read status of control port pins *****/ -/* - * Pin value between 0 and 7 - * Control bus = port A) - */ -uint8_t mcpDigitalRead(uint8_t pin) { - // If the pin value is larger than 7 then do nothing and return - // Zero or larger value is implied by the variable type - if (pin > 7) return 0x0; - // Read the port A pin state, extract and return HIGH/LOW state for the requested pin - return mcpByteRead(MCPPORTA) & (1 << pin) ? HIGH : LOW; -} - - -/***** Get the status of an MCP23017 pin) *****/ -uint8_t getGpibPinState(uint8_t pin){ - return mcpDigitalRead(pin); -} - - -/***** Configure pins that will generate an interrupt *****/ -void mcpInterruptsEn(){ - // Set to interrupt mode for compare to previous - mcpByteWrite(MCPINTCONA, 0b00000000); - // Enable interrupt to detect pin state change on pins 4, 6 and 7 (EOI, SRQ and ATN) - mcpByteWrite(MCPINTENA, 0b11010000); -} - -#endif //AR488_MCP23017 -/***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ -/***** MCP23017 EXPANDER (I2C) LAYOUT *****/ -/******************************************/ - - - /***************************************************/ /***** PANDUINO/MIGHTYCORE MCGRAW BOARD LAYOUT *****/ /***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ @@ -1138,19 +932,19 @@ uint8_t reverseBits(uint8_t dbyte) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN bits (databits) : State - 0=LOW, 1=HIGH/INPUT_PULLUP; Direction - 0=input, 1=output; mask (mask) : 0=unaffected, 1=enabled mode (mode) : 0=set pin state, 1=set pin direction Arduino Uno/Nano pin to Port/bit to direction/state byte map: - IFC 22 PORTC bit 6 byte bit 0 - NDAC 21 PORTC bit 5 byte bit 1 - NRFD 20 PORTC bit 4 byte bit 2 - DAV 19 PORTC bit 3 byte bit 3 - EOI 18 PORTC bit 2 byte bit 4 - SRQ 23 PORTC bit 7 byte bit 6 - REN 24 PORTA bit 0 byte bit 5 - ATN 31 PORTA bit 7 byte bit 7 + IFC_PIN 22 PORTC bit 6 byte bit 0 + NDAC_PIN 21 PORTC bit 5 byte bit 1 + NRFD_PIN 20 PORTC bit 4 byte bit 2 + DAV_PIN 19 PORTC bit 3 byte bit 3 + EOI_PIN 18 PORTC bit 2 byte bit 4 + SRQ_PIN 23 PORTC bit 7 byte bit 6 + REN_PIN 24 PORTA bit 0 byte bit 5 + ATN_PIN 31 PORTA bit 7 byte bit 7 */ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { @@ -1191,16 +985,15 @@ void setGpibState(uint8_t bits, uint8_t mask, uint8_t mode) { /*************************************/ /***** CUSTOM PIN LAYOUT SECTION *****/ /***** vvvvvvvvvvvvvvvvvvvvvvvvv *****/ -#ifdef AR488_CUSTOM +#if defined (AR488_CUSTOM) || defined (NON_ARDUINO) -uint8_t databus[8] = { DIO1, DIO2, DIO3, DIO4, DIO5, DIO6, DIO7, DIO8 }; +uint8_t databus[8] = { DIO1_PIN, DIO2_PIN, DIO3_PIN, DIO4_PIN, DIO5_PIN, DIO6_PIN, DIO7_PIN, DIO8_PIN }; -uint8_t ctrlbus[8] = { IFC, NDAC, NRFD, DAV, EOI, REN, SRQ, ATN }; +uint8_t ctrlbus[8] = { IFC_PIN, NDAC_PIN, NRFD_PIN, DAV_PIN, EOI_PIN, REN_PIN, SRQ_PIN, ATN_PIN }; /***** Set the GPIB data bus to input pullup *****/ void readyGpibDbus() { - uint8_t db = 0; for (uint8_t i=0; i<8; i++){ pinMode(databus[i], INPUT_PULLUP); } @@ -1230,7 +1023,7 @@ void setGpibDbus(uint8_t db) { /***** Set the direction and state of the GPIB control lines ****/ /* - Bits control lines as follows: 7-ATN, 6-SRQ, 5-REN, 4-EOI, 3-DAV, 2-NRFD, 1-NDAC, 0-IFC + Bits control lines as follows: 7-ATN_PIN, 6-SRQ_PIN, 5-REN_PIN, 4-EOI_PIN, 3-DAV_PIN, 2-NRFD_PIN, 1-NDAC_PIN, 0-IFC_PIN state: 0=LOW; 1=HIGH/INPUT_PULLUP dir : 0=input; 1=output; mode: 0=set pin state; 1=set pin direction diff --git a/src/AR488/AR488_Layouts.h b/src/AR488/AR488_Layouts.h index efa61dc..f83ecb3 100644 --- a/src/AR488/AR488_Layouts.h +++ b/src/AR488/AR488_Layouts.h @@ -5,28 +5,19 @@ #include "AR488_Config.h" -#ifdef DEBUG_LAYOUTS - extern Stream& debugStream; -#endif -/***** AR488_Hardware.h, ver. 0.51.18, 26/02/2023 *****/ +/***** AR488_Hardware.h, ver. 0.51.26, 24/12/2023 *****/ /* * Hardware pin layout definitions */ + /*************************************/ /***** CUSTOM PIN LAYOUT SECTION *****/ /***** vvvvvvvvvvvvvvvvvvvvvvvvv *****/ #ifdef AR488_CUSTOM -/* -// Use only pinhooks for custom mode -// (We don't know which pin interrupts will be required) -#ifdef USE_INTERRUPTS - #undef USE_INTERRUPTS -// #define USE_PINHOOKS -#endif -*/ +/***** Configured in AR488_Config.h *****/ #endif /***** ^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ @@ -41,25 +32,25 @@ #if defined(AR488_UNO) || defined(AR488_NANO) -/***** NOTE: UNO/NANO pinout last updated 21/09/2019 *****/ -#define DIO1 A0 /* GPIB 1 : PORTC bit 0 */ -#define DIO2 A1 /* GPIB 2 : PORTC bit 1 */ -#define DIO3 A2 /* GPIB 3 : PORTC bit 2 */ -#define DIO4 A3 /* GPIB 4 : PORTC bit 3 */ -#define DIO5 A4 /* GPIB 13 : PORTC bit 4 */ -#define DIO6 A5 /* GPIB 14 : PORTC bit 5 */ -#define DIO7 4 /* GPIB 15 : PORTD bit 4 */ -#define DIO8 5 /* GPIB 16 : PORTD bit 5 */ +/***** NOTE: UNO/NANO pinout *****/ +#define DIO1_PIN A0 /* GPIB 1 : PORTC bit 0 */ +#define DIO2_PIN A1 /* GPIB 2 : PORTC bit 1 */ +#define DIO3_PIN A2 /* GPIB 3 : PORTC bit 2 */ +#define DIO4_PIN A3 /* GPIB 4 : PORTC bit 3 */ +#define DIO5_PIN A4 /* GPIB 13 : PORTC bit 4 */ +#define DIO6_PIN A5 /* GPIB 14 : PORTC bit 5 */ +#define DIO7_PIN 4 /* GPIB 15 : PORTD bit 4 */ +#define DIO8_PIN 5 /* GPIB 16 : PORTD bit 5 */ -#define IFC 8 /* GPIB 9 : PORTB bit 0 */ -#define NDAC 9 /* GPIB 8 : PORTB bit 1 */ -#define NRFD 10 /* GPIB 7 : PORTB bit 2 */ -#define DAV 11 /* GPIB 6 : PORTB bit 3 */ -#define EOI 12 /* GPIB 5 : PORTB bit 4 */ +#define IFC_PIN 8 /* GPIB 9 : PORTB bit 0 */ +#define NDAC_PIN 9 /* GPIB 8 : PORTB bit 1 */ +#define NRFD_PIN 10 /* GPIB 7 : PORTB bit 2 */ +#define DAV_PIN 11 /* GPIB 6 : PORTB bit 3 */ +#define EOI_PIN 12 /* GPIB 5 : PORTB bit 4 */ -#define SRQ 2 /* GPIB 10 : PORTD bit 2 */ -#define REN 3 /* GPIB 17 : PORTD bit 3 */ -#define ATN 7 /* GPIB 11 : PORTD bit 7 */ +#define SRQ_PIN 2 /* GPIB 10 : PORTD bit 2 */ +#define REN_PIN 3 /* GPIB 17 : PORTD bit 3 */ +#define ATN_PIN 7 /* GPIB 11 : PORTD bit 7 */ #endif @@ -75,24 +66,24 @@ #ifdef AR488_MEGA2560_D // NOTE: MEGA2560 pinout last updated 28/07/2019 -#define DIO1 A0 /* GPIB 1 : PORTF bit 0 */ -#define DIO2 A1 /* GPIB 2 : PORTF bit 1 */ -#define DIO3 A2 /* GPIB 3 : PORTF bit 2 */ -#define DIO4 A3 /* GPIB 4 : PORTF bit 3 */ -#define DIO5 A4 /* GPIB 13 : PORTF bit 4 */ -#define DIO6 A5 /* GPIB 14 : PORTF bit 5 */ -#define DIO7 A6 /* GPIB 15 : PORTF bit 4 */ -#define DIO8 A7 /* GPIB 16 : PORTF bit 5 */ - -#define IFC 17 /* GPIB 9 : PORTH bit 0 */ -#define NDAC 16 /* GPIB 8 : PORTH bit 1 */ -#define NRFD 6 /* GPIB 7 : PORTH bit 3 */ -#define DAV 7 /* GPIB 6 : PORTH bit 4 */ -#define EOI 8 /* GPIB 5 : PORTH bit 5 */ -#define REN 9 /* GPIB 17 : PORTD bit 6 */ - -#define SRQ 10 /* GPIB 10 : PORTB bit 4 */ -#define ATN 11 /* GPIB 11 : PORTB bit 5 */ +#define DIO1_PIN_PIN A0 /* GPIB 1 : PORTF bit 0 */ +#define DIO2_PIN A1 /* GPIB 2 : PORTF bit 1 */ +#define DIO3_PIN A2 /* GPIB 3 : PORTF bit 2 */ +#define DIO4_PIN A3 /* GPIB 4 : PORTF bit 3 */ +#define DIO5_PIN A4 /* GPIB 13 : PORTF bit 4 */ +#define DIO6_PIN A5 /* GPIB 14 : PORTF bit 5 */ +#define DIO7_PIN A6 /* GPIB 15 : PORTF bit 4 */ +#define DIO8_PIN A7 /* GPIB 16 : PORTF bit 5 */ + +#define IFC_PIN 17 /* GPIB 9 : PORTH bit 0 */ +#define NDAC_PIN 16 /* GPIB 8 : PORTH bit 1 */ +#define NRFD_PIN 6 /* GPIB 7 : PORTH bit 3 */ +#define DAV_PIN 7 /* GPIB 6 : PORTH bit 4 */ +#define EOI_PIN 8 /* GPIB 5 : PORTH bit 5 */ +#define REN_PIN 9 /* GPIB 17 : PORTD bit 6 */ + +#define SRQ_PIN 10 /* GPIB 10 : PORTB bit 4 */ +#define ATN_PIN 11 /* GPIB 11 : PORTB bit 5 */ #endif // AR488_MEGA2560_D /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ @@ -107,24 +98,24 @@ #ifdef AR488_MEGA2560_E1 // NOTE: MEGA2560 pinout last updated 28/07/2019 -#define DIO1 30 /* GPIB 1 : PORTC bit 1 */ -#define DIO2 32 /* GPIB 2 : PORTC bit 3 */ -#define DIO3 34 /* GPIB 3 : PORTC bit 5 */ -#define DIO4 36 /* GPIB 4 : PORTC bit 7 */ -#define DIO5 22 /* GPIB 13 : PORTA bit 6 */ -#define DIO6 24 /* GPIB 14 : PORTA bit 4 */ -#define DIO7 26 /* GPIB 15 : PORTA bit 2 */ -#define DIO8 28 /* GPIB 16 : PORTA bit 0 */ - -#define IFC 48 /* GPIB 9 : PORTD bit 7 */ -#define NDAC 46 /* GPIB 8 : PORTG bit 1 */ -#define NRFD 44 /* GPIB 7 : PORTL bit 7 */ -#define DAV 42 /* GPIB 6 : PORTL bit 5 */ -#define EOI 40 /* GPIB 5 : PORTL bit 3 */ -#define REN 38 /* GPIB 17 : PORTL bit 1 */ - -#define SRQ 50 /* GPIB 10 : PORTB bit 1 */ -#define ATN 52 /* GPIB 11 : PORTB bit 3 */ +#define DIO1_PIN 30 /* GPIB 1 : PORTC bit 1 */ +#define DIO2_PIN 32 /* GPIB 2 : PORTC bit 3 */ +#define DIO3_PIN 34 /* GPIB 3 : PORTC bit 5 */ +#define DIO4_PIN 36 /* GPIB 4 : PORTC bit 7 */ +#define DIO5_PIN 22 /* GPIB 13 : PORTA bit 6 */ +#define DIO6_PIN 24 /* GPIB 14 : PORTA bit 4 */ +#define DIO7_PIN 26 /* GPIB 15 : PORTA bit 2 */ +#define DIO8_PIN 28 /* GPIB 16 : PORTA bit 0 */ + +#define IFC_PIN 48 /* GPIB 9 : PORTD bit 7 */ +#define NDAC_PIN 46 /* GPIB 8 : PORTG bit 1 */ +#define NRFD_PIN 44 /* GPIB 7 : PORTL bit 7 */ +#define DAV_PIN 42 /* GPIB 6 : PORTL bit 5 */ +#define EOI_PIN 40 /* GPIB 5 : PORTL bit 3 */ +#define REN_PIN 38 /* GPIB 17 : PORTL bit 1 */ + +#define SRQ_PIN 50 /* GPIB 10 : PORTB bit 1 */ +#define ATN_PIN 52 /* GPIB 11 : PORTB bit 3 */ #endif // AR488_MEGA2560_E1 /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ @@ -139,24 +130,24 @@ #ifdef AR488_MEGA2560_E2 // NOTE: MEGA2560 pinout last updated 28/07/2019 -#define DIO1 37 /* GPIB 1 : PORTA bit 1 */ -#define DIO2 35 /* GPIB 2 : PORTA bit 3 */ -#define DIO3 33 /* GPIB 3 : PORTA bit 5 */ -#define DIO4 31 /* GPIB 4 : PORTA bit 7 */ -#define DIO5 29 /* GPIB 13 : PORTC bit 6 */ -#define DIO6 27 /* GPIB 14 : PORTC bit 4 */ -#define DIO7 25 /* GPIB 15 : PORTC bit 2 */ -#define DIO8 23 /* GPIB 16 : PORTC bit 0 */ - -#define IFC 49 /* GPIB 9 : PORTG bit 0 */ -#define NDAC 47 /* GPIB 8 : PORTG bit 2 */ -#define NRFD 45 /* GPIB 7 : PORTL bit 6 */ -#define DAV 43 /* GPIB 6 : PORTL bit 4 */ -#define EOI 41 /* GPIB 5 : PORTL bit 2 */ -#define REN 39 /* GPIB 17 : PORTL bit 0 */ - -#define SRQ 51 /* GPIB 10 : PORTB bit 0 */ -#define ATN 53 /* GPIB 11 : PORTB bit 2 */ +#define DIO1_PIN 37 /* GPIB 1 : PORTA bit 1 */ +#define DIO2_PIN 35 /* GPIB 2 : PORTA bit 3 */ +#define DIO3_PIN 33 /* GPIB 3 : PORTA bit 5 */ +#define DIO4_PIN 31 /* GPIB 4 : PORTA bit 7 */ +#define DIO5_PIN 29 /* GPIB 13 : PORTC bit 6 */ +#define DIO6_PIN 27 /* GPIB 14 : PORTC bit 4 */ +#define DIO7_PIN 25 /* GPIB 15 : PORTC bit 2 */ +#define DIO8_PIN 23 /* GPIB 16 : PORTC bit 0 */ + +#define IFC_PIN 49 /* GPIB 9 : PORTG bit 0 */ +#define NDAC_PIN 47 /* GPIB 8 : PORTG bit 2 */ +#define NRFD_PIN 45 /* GPIB 7 : PORTL bit 6 */ +#define DAV_PIN 43 /* GPIB 6 : PORTL bit 4 */ +#define EOI_PIN 41 /* GPIB 5 : PORTL bit 2 */ +#define REN_PIN 39 /* GPIB 17 : PORTL bit 0 */ + +#define SRQ_PIN 51 /* GPIB 10 : PORTB bit 0 */ +#define ATN_PIN 53 /* GPIB 11 : PORTB bit 2 */ #endif // AR488_MEGA2560_E2 /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ @@ -170,23 +161,23 @@ /***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ #ifdef AR488_MEGA32U4_MICRO -#define DIO1 3 /* GPIB 1 : PORTD bit 0 data pins assigned for minimum shifting */ -#define DIO2 15 /* GPIB 2 : PORTB bit 1 */ -#define DIO3 16 /* GPIB 3 : PORTB bit 2 */ -#define DIO4 14 /* GPIB 4 : PORTB bit 3 */ -#define DIO5 8 /* GPIB 13 : PORTB bit 4 */ -#define DIO6 9 /* GPIB 14 : PORTB bit 5 */ -#define DIO7 10 /* GPIB 15 : PORTB bit 6 */ -#define DIO8 6 /* GPIB 16 : PORTD bit 7 */ - -#define IFC 4 /* GPIB 9 : PORTD bit 4 */ -#define NDAC A3 /* GPIB 8 : PORTF bit 4 fast control pins assigned to same port */ -#define NRFD A2 /* GPIB 7 : PORTF bit 5 */ -#define DAV A1 /* GPIB 6 : PORTF bit 6 */ -#define EOI A0 /* GPIB 5 : PORTF bit 7 */ -#define REN 5 /* GPIB 17 : PORTC bit 6 */ -#define SRQ 7 /* GPIB 10 : PORTE bit 6 */ -#define ATN 2 /* GPIB 11 : PORTD bit 1 */ +#define DIO1_PIN 3 /* GPIB 1 : PORTD bit 0 data pins assigned for minimum shifting */ +#define DIO2_PIN 15 /* GPIB 2 : PORTB bit 1 */ +#define DIO3_PIN 16 /* GPIB 3 : PORTB bit 2 */ +#define DIO4_PIN 14 /* GPIB 4 : PORTB bit 3 */ +#define DIO5_PIN 8 /* GPIB 13 : PORTB bit 4 */ +#define DIO6_PIN 9 /* GPIB 14 : PORTB bit 5 */ +#define DIO7_PIN 10 /* GPIB 15 : PORTB bit 6 */ +#define DIO8_PIN 6 /* GPIB 16 : PORTD bit 7 */ + +#define IFC_PIN 4 /* GPIB 9 : PORTD bit 4 */ +#define NDAC_PIN A3 /* GPIB 8 : PORTF bit 4 fast control pins assigned to same port */ +#define NRFD_PIN A2 /* GPIB 7 : PORTF bit 5 */ +#define DAV_PIN A1 /* GPIB 6 : PORTF bit 6 */ +#define EOI_PIN A0 /* GPIB 5 : PORTF bit 7 */ +#define REN_PIN 5 /* GPIB 17 : PORTC bit 6 */ +#define SRQ_PIN 7 /* GPIB 10 : PORTE bit 6 */ +#define ATN_PIN 2 /* GPIB 11 : PORTD bit 1 */ #endif // AR488_MEGA32U4_MICRO /***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ @@ -201,24 +192,24 @@ #ifdef AR488_MEGA32U4_LR3 /***** NOTE: LEONARDO R3 pinout last updated 06/04/2020 *****/ -#define DIO1 A0 /* GPIB 1 : PORTF bit 7 */ -#define DIO2 A1 /* GPIB 2 : PORTF bit 6 */ -#define DIO3 A2 /* GPIB 3 : PORTF bit 5 */ -#define DIO4 A3 /* GPIB 4 : PORTF bit 4 */ -#define DIO5 A4 /* GPIB 13 : PORTF bit 3 */ -#define DIO6 A5 /* GPIB 14 : PORTF bit 2 */ -#define DIO7 4 /* GPIB 15 : PORTD bit 4 */ -#define DIO8 5 /* GPIB 16 : PORTC bit 6 */ - -#define IFC 8 /* GPIB 9 : PORTB bit 4 */ -#define NDAC 9 /* GPIB 8 : PORTB bit 5 */ -#define NRFD 10 /* GPIB 7 : PORTB bit 6 */ -#define DAV 11 /* GPIB 6 : PORTD bit 6 */ -#define EOI 12 /* GPIB 5 : PORTC bit 7 */ - -#define SRQ 2 /* GPIB 10 : PORTD bit 1 */ -#define REN 3 /* GPIB 17 : PORTD bit 0 */ -#define ATN 7 /* GPIB 11 : PORTE bit 6 */ +#define DIO1_PIN A0 /* GPIB 1 : PORTF bit 7 */ +#define DIO2_PIN A1 /* GPIB 2 : PORTF bit 6 */ +#define DIO3_PIN A2 /* GPIB 3 : PORTF bit 5 */ +#define DIO4_PIN A3 /* GPIB 4 : PORTF bit 4 */ +#define DIO5_PIN A4 /* GPIB 13 : PORTF bit 3 */ +#define DIO6_PIN A5 /* GPIB 14 : PORTF bit 2 */ +#define DIO7_PIN 4 /* GPIB 15 : PORTD bit 4 */ +#define DIO8_PIN 5 /* GPIB 16 : PORTC bit 6 */ + +#define IFC_PIN 8 /* GPIB 9 : PORTB bit 4 */ +#define NDAC_PIN 9 /* GPIB 8 : PORTB bit 5 */ +#define NRFD_PIN 10 /* GPIB 7 : PORTB bit 6 */ +#define DAV_PIN 11 /* GPIB 6 : PORTD bit 6 */ +#define EOI_PIN 12 /* GPIB 5 : PORTC bit 7 */ + +#define SRQ_PIN 2 /* GPIB 10 : PORTD bit 1 */ +#define REN_PIN 3 /* GPIB 17 : PORTD bit 0 */ +#define ATN_PIN 7 /* GPIB 11 : PORTE bit 6 */ uint8_t reverseBits(uint8_t dbyte); @@ -236,15 +227,18 @@ uint8_t reverseBits(uint8_t dbyte); #include -/***** NOTE: MCP23S17 pinout last updated 03/05/2021 *****/ -#define IFC 0 /* GPIB 9 : PORTA bit 0 */ -#define NDAC 1 /* GPIB 8 : PORTA bit 1 */ -#define NRFD 2 /* GPIB 7 : PORTA bit 2 */ -#define DAV 3 /* GPIB 6 : PORTA bit 3 */ -#define EOI 4 /* GPIB 5 : PORTA bit 4 */ -#define REN 5 /* GPIB 17 : PORTA bit 5 */ -#define SRQ 6 /* GPIB 10 : PORTA bit 6 */ -#define ATN 7 /* GPIB 11 : PORTA bit 7 */ +/***** NOTE: MCP23S17 pinout *****/ +#define IFC_PIN 0 /* GPIB 9 : PORTA bit 0 */ +#define NDAC_PIN 1 /* GPIB 8 : PORTA bit 1 */ +#define NRFD_PIN 2 /* GPIB 7 : PORTA bit 2 */ +#define DAV_PIN 3 /* GPIB 6 : PORTA bit 3 */ +#define EOI_PIN 4 /* GPIB 5 : PORTA bit 4 */ +#define REN_PIN 5 /* GPIB 17 : PORTA bit 5 */ +#define SRQ_PIN 6 /* GPIB 10 : PORTA bit 6 */ +#define ATN_PIN 7 /* GPIB 11 : PORTA bit 7 */ + +/***** NOTE: DIO1-DIO8 pins are assigned to ping 0 - 7 on port B *****/ + /***** MCP23S17 defines *****/ // Direction registers @@ -288,92 +282,98 @@ uint8_t getMcpIntAReg(); -/***********************************************/ -/***** MCP23017 IC (I2C) LAYOUT DEFINITION *****/ -/***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ -#ifdef AR488_MCP23017 +/********************************************************/ +/***** PANDUINO/MIGHTYCORE MCGRAW LAYOUT DEFINITION *****/ +/***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ +#ifdef AR488_MEGA644P_MCGRAW -#include +#define DIO1_PIN 10 /* GPIB 1 */ +#define DIO2_PIN 11 /* GPIB 2 */ +#define DIO3_PIN 12 /* GPIB 3 */ +#define DIO4_PIN 13 /* GPIB 4 */ +#define DIO5_PIN 14 /* GPIB 13 */ +#define DIO6_PIN 15 /* GPIB 14 */ +#define DIO7_PIN 16 /* GPIB 15 */ +#define DIO8_PIN 17 /* GPIB 16 */ + +#define IFC_PIN 22 /* GPIB 9 */ +#define NDAC_PIN 21 /* GPIB 8 */ +#define NRFD_PIN 20 /* GPIB 7 */ +#define DAV_PIN 19 /* GPIB 6 */ +#define EOI_PIN 18 /* GPIB 5 */ + +#define SRQ_PIN 23 /* GPIB 10 */ +#define REN_PIN 24 /* GPIB 17 */ +#define ATN_PIN 31 /* GPIB 11 */ -/***** NOTE: MCP23017 pinout last updated 03/05/2021 *****/ -#define IFC 0 /* GPIB 9 : PORTA bit 0 */ -#define NDAC 1 /* GPIB 8 : PORTA bit 1 */ -#define NRFD 2 /* GPIB 7 : PORTA bit 2 */ -#define DAV 3 /* GPIB 6 : PORTA bit 3 */ -#define EOI 4 /* GPIB 5 : PORTA bit 4 */ -#define REN 5 /* GPIB 17 : PORTA bit 5 */ -#define SRQ 6 /* GPIB 10 : PORTA bit 6 */ -#define ATN 7 /* GPIB 11 : PORTA bit 7 */ +#endif // AR488_MEGA644P_MCGRAW +/***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ +/***** PANDUINO/MIGHTYCORE MCGRAW LAYOUT DEFINITION *****/ +/********************************************************/ -/***** MCP23S17 defines *****/ -// Direction registers -#define MCPDIRA 0x00 -#define MCPDIRB 0x01 -// Configuration register -#define MCPCON (0x0A) -// Pullup state register -#define MCPPUA 0x0C -#define MCPPUB 0x0D +/***********************************/ +/***** ESP32 LAYOUT DEFINITION *****/ +/***** vvvvvvvvvvvvvvvvvvvvvvv *****/ +#ifdef ESP32_WROOM_32 -// Port Register -#define MCPPORTA 0x12 -#define MCPPORTB 0x13 +#define DIO1_PIN 32 /* GPIB 1 */ +#define DIO2_PIN 33 /* GPIB 2 */ +#define DIO3_PIN 25 /* GPIB 3 */ +#define DIO4_PIN 26 /* GPIB 4 */ +#define DIO5_PIN 27 /* GPIB 13 */ +#define DIO6_PIN 14 /* GPIB 14 */ +#define DIO7_PIN 4 /* GPIB 15 */ +#define DIO8_PIN 13 /* GPIB 16 */ -// Interrupt registers -#define MCPINTENA 0x04 // Enable pin for interrupt on change (GPINTEN) -#define MCPINTCONA 0x08 // Configure interrupt: 0 = compare against previous; 1 = compare against DEFVAL -#define MCPINTFA 0x0E // Flag that interrupt ocurred on pin (read-only) -#define MCPINTCAPA 0x10 // Read the status of the pin (read-only) -//#define MCPINTPINA 2 // Pin assigned to catch MCP23S17 INTA on the Arduino controller +#define IFC_PIN 23 /* GPIB 9 */ +#define NDAC_PIN 22 /* GPIB 8 */ +#define NRFD_PIN 21 /* GPIB 7 */ +#define DAV_PIN 19 /* GPIB 6 */ +#define EOI_PIN 18 /* GPIB 5 */ -// MCP opcodes -#define MCPWRITE 0b01000000 -#define MCPREAD 0b01000001 +#define SRQ_PIN 5 /* GPIB 10 */ +#define REN_PIN 17 /* GPIB 17 */ +#define ATN_PIN 16 /* GPIB 11 */ -uint8_t mcpByteRead(uint8_t reg); -void mcpByteWrite(uint8_t reg, uint8_t db); -uint8_t mcpDigitalRead(uint8_t pin); -void mcpInterruptsEn(); -void mcpIntHandler(); -uint8_t getMcpIntAReg(); +#endif // ESP32_WROOM_32 +/***** ^^^^^^^^^^^^^^^^^^^^^^^ *****/ +/***** ESP32 LAYOUT DEFINITION *****/ +/***********************************/ -#endif // AR488_MCP23017 -/***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ -/***** MCP23017 IC (I2C) LAYOUT DEFINITION *****/ -/***********************************************/ +/*************************************/ +/***** PI PICO LAYOUT DEFINITION *****/ +/***** vvvvvvvvvvvvvvvvvvvvvvvvv *****/ -/********************************************************/ -/***** PANDUINO/MIGHTYCORE MCGRAW LAYOUT DEFINITION *****/ -/***** vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv *****/ -#ifdef AR488_MEGA644P_MCGRAW +//#ifdef RPI_PICO -#define DIO1 10 /* GPIB 1 */ -#define DIO2 11 /* GPIB 2 */ -#define DIO3 12 /* GPIB 3 */ -#define DIO4 13 /* GPIB 4 */ -#define DIO5 14 /* GPIB 13 */ -#define DIO6 15 /* GPIB 14 */ -#define DIO7 16 /* GPIB 15 */ -#define DIO8 17 /* GPIB 16 */ - -#define IFC 22 /* GPIB 9 */ -#define NDAC 21 /* GPIB 8 */ -#define NRFD 20 /* GPIB 7 */ -#define DAV 19 /* GPIB 6 */ -#define EOI 18 /* GPIB 5 */ - -#define SRQ 23 /* GPIB 10 */ -#define REN 24 /* GPIB 17 */ -#define ATN 31 /* GPIB 11 */ +//#define DIO1_PIN 6 /* GPIB 1 */ +//#define DIO2_PIN 7 /* GPIB 2 */ +//#define DIO3_PIN 8 /* GPIB 3 */ +//#define DIO4_PIN 9 /* GPIB 4 */ +//#define DIO5_PIN 10 /* GPIB 13 */ +//#define DIO6_PIN 11 /* GPIB 14 */ +//#define DIO7_PIN 12 /* GPIB 15 */ +//#define DIO8_PIN 13 /* GPIB 16 */ -#endif // AR488_MEGA644P_MCGRAW -/***** ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ *****/ -/***** PANDUINO/MIGHTYCORE MCGRAW LAYOUT DEFINITION *****/ -/********************************************************/ +//#define IFC_PIN 14 /* GPIB 9 */ +//#define NDAC_PIN 15 /* GPIB 8 */ +//#define NRFD_PIN 16 /* GPIB 7 */ +//#define DAV_PIN 17 /* GPIB 6 */ +//#define EOI_PIN 18 /* GPIB 5 */ + +//#define SRQ_PIN 19 /* GPIB 10 */ +//#define REN_PIN 20 /* GPIB 17 */ +//#define ATN_PIN 21 /* GPIB 11 */ + +//#endif // RPI_PICO + +/***** ^^^^^^^^^^^^^^^^^^^^^^^ *****/ +/***** ESP32 LAYOUT DEFINITION *****/ +/***********************************/