Bit-Bang Digital Outputs Example

I figured out how to control the outputs directly like direct port manipulation on the Arduino. Could be useful if you need to roll your own bit-banged library or something like that :wink:

Check out this example code with timing info measured with my Rigol DS1052 50MHz oscilloscope.

//--------------------------
// Simple Bit-Bang Example
// BDub 2013
//--------------------------
uint16_t pin = D7;

void setup() {
    pinMode(pin,OUTPUT);
}

void loop() {
    // Bit-Bang Digital Output D7 at 18MHz = System Clock 72MHz / 4
    // HIGH time = 27.7ns
    // LOW time = 27.7ns
    PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
    PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin;  // LOW
    PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
    PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin;  // LOW
    PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
    PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin;  // LOW
    PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
    PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin;  // LOW
    
    // Wrapped up in function calls slows down to 1.53MHz
    // HIGH time = 332ns
    // LOW time = 320ns
    pinHigh(pin);
    pinLow(pin);
    pinHigh(pin);
    pinLow(pin);
    pinHigh(pin);
    pinLow(pin);
    pinHigh(pin);
    pinLow(pin);
    
    // Some logic added, but wrapping removed slows down to 1.44MHz
    // HIGH time = 360ns
    // LOW time = 336ns
    bool state = HIGH;
    for(int x=0; x<8; x++) {
        state = !state;
        if(state) PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
        else PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin;  // LOW
    }
    
    // Using digitalWrite() slows down to 227kHz
    // HIGH time = 2.28us
    // LOW time = 2.16us
    digitalWrite(pin,HIGH); // This first HIGH time was actually 4.4us,
    digitalWrite(pin,LOW);  // while the LOW time was 2.16us.
    digitalWrite(pin,HIGH); // The next three were actually 2.28us HIGH,
    digitalWrite(pin,LOW);  // and 2.16us LOW.
    digitalWrite(pin,HIGH); //  |   
    digitalWrite(pin,LOW);  //  |
    digitalWrite(pin,HIGH); //  |
    digitalWrite(pin,LOW);  //  |
    
}

void pinHigh(uint16_t pin) {
    PIN_MAP[pin].gpio_peripheral->BSRR = PIN_MAP[pin].gpio_pin; // HIGH
}

void pinLow(uint16_t pin) {
    PIN_MAP[pin].gpio_peripheral->BRR = PIN_MAP[pin].gpio_pin; // LOW
}
8 Likes

Interesting… I’ll do some tests with this when my replacement Core gets in today. Nice job with the measurements! High fugu re-yams?

1 Like

Haha, what the heck are “fugu re-yams”?

2 Likes