Switching between OUTPUT and INPUT_PULLUP using registers
Posted: Tue Nov 11, 2025 2:56 pm
I have written a couple of functions to set pull-ups and switch between GPIO pins between input and although they work on Wokwi, they don't work on a real ESP32. I am curious as to what I may be missing?
The genGpioMask() function is creating the pin mask correctly, setting the appropriate bits corresponding to the pin numbers assigned. If I uncomment the pinMode() code in readyGpibDbus() everything works, which suggests that either gpio_pullup_en() and gpio_pullup_dis() functions or the REG_WRITE statements are not working, or some other setting needs to be applied?
The genGpioMask() function is creating the pin mask correctly, setting the appropriate bits corresponding to the pin numbers assigned. If I uncomment the pinMode() code in readyGpibDbus() everything works, which suggests that either gpio_pullup_en() and gpio_pullup_dis() functions or the REG_WRITE statements are not working, or some other setting needs to be applied?
Code: Select all
struct gpioregister_t {
uint32_t reg0 = 0;
uint32_t reg1 = 0;
};
const uint8_t databus[8] = { DIO1_PIN, DIO2_PIN, DIO3_PIN, DIO4_PIN, DIO5_PIN, DIO6_PIN, DIO7_PIN, DIO8_PIN };
const uint8_t ctrlreg[8] = { IFC_PIN, NDAC_PIN, NRFD_PIN, DAV_PIN, EOI_PIN, REN_PIN, SRQ_PIN, ATN_PIN };
gpioregister_t gpioDbMask;
gpioregister_t gpioCtrlMask;
void printRegMaskBin(gpioregister_t& gpioreg){
Serial.print(gpioreg.reg1, BIN);
Serial.println(gpioreg.reg0, BIN);
}
/***** Generate register bitmask *****/
void genGpioMask(gpioregister_t& gpioreg, const uint8_t buspins[], uint8_t bitmask) {
for (uint8_t i=0; i<8; i++) {
if (bitmask & (1 << i)) {
if (buspins[i] > 31) {
gpioreg.reg1 |= ( 1ULL << (buspins[i]-32) );
}else{
gpioreg.reg0 |= ( 1ULL << buspins[i] );
}
}
}
}
/***** Init GPIO registers *****/
void initGpioRegMasks(){
// Generate masks
genGpioMask(gpioDbMask, databus, 0xFF);
genGpioMask(gpioCtrlMask, ctrlreg, 0xFF);
}
/***** Set pull-ups *****/
/*
* bus to set, mask to set, enable/disable
*/
void gpioSetPullupsMasked(const uint8_t bus[], uint8_t mask, bool enable){
for (uint8_t i=0; i<8; i++) {
if (mask & (1<<i)) {
if (enable) {
if ( (gpio_num_t)bus[i] ){
gpio_set_pull_mode((gpio_num_t)bus[i], GPIO_PULLUP_ONLY);
gpio_pullup_en( (gpio_num_t)bus[i] );
}
}else{
if ( (gpio_num_t)bus[i] ) {
gpio_pullup_dis( (gpio_num_t)bus[i] );
}
}
}
}
}
/**** Set the GPIB data bus to input pullup *****/
void readyGpibDbus(uint8_t state = INPUT_PULLUP) {
// Set pins to OUTPUT
if (state == OUTPUT) {
Serial.println(F("Disabling pull-ups..."));
// Disable pullups
gpioSetPullupsMasked(databus, 0xFF, false);
// for (uint8_t i=0; i<8; i++){
// pinMode(databus[i], OUTPUT);
// }
// Set to output
REG_WRITE( GPIO_ENABLE_W1TS_REG, gpioDbMask.reg0 );
REG_WRITE( GPIO_ENABLE1_W1TS_REG, gpioDbMask.reg1 );
// Set to HIGH
REG_WRITE( GPIO_OUT_W1TS_REG, gpioDbMask.reg0 );
REG_WRITE( GPIO_OUT1_W1TS_REG, gpioDbMask.reg1 );
delayMicroseconds(20);
return;
}
// Set pins to INPUT_PULLUP
REG_WRITE( GPIO_ENABLE_W1TC_REG, gpioDbMask.reg0 );
REG_WRITE( GPIO_ENABLE1_W1TC_REG, gpioDbMask.reg1 );
// Enable pullups
gpioSetPullupsMasked(databus, 0xFF, true);
}
/***** Read the GPIB data bus wires to collect the byte of data *****/
uint8_t readGpibDbus() {
uint64_t gpioall = 0;
// Read the byte of data on the bus`
gpioall = REG_READ(GPIO_IN_REG);
gpioall |= ( (unsigned long long)REG_READ(GPIO_IN1_REG) << 32 );
uint8_t result = 0;
for (uint8_t i=0; i<8; i++) {
if ( gpioall & (1ULL<<databus[i]) ) result = (result | (1U<<i));
}
return ~result;
}