Skip to content

Digital barcodes for synchronizing data streams with different hardware clocks

License

Notifications You must be signed in to change notification settings

lachioma/arduino-sync-barcodes

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

16 Commits
 
 
 
 
 
 
 
 

Repository files navigation

Arduino Sync Barcodes

This repository contains Arduino code (arduino-barcodes) for generating TTL barcodes that can be used to synchronize multiple data sources.

The code has been modified from open-ephys/sync-barcodes.
The modifications from the original code include:

  • Simultaneous output on multiple pins using "direct port access" (see also section below).
  • Barcode settings (barcode duration, inter-barcode interval, number of bits, initiation pulse duration, etc.) can now be easily changed to your preference.
  • Several comments have been added for clarity.

Read more about synchronizing multiple data streams:
https://open-ephys.github.io/gui-docs/User-Manual/Plugins/NIDAQmx.html

More about Direct Port Access ("Port manipulation")

N.B. the way port manipulation is implemented depends on the exact microcontroller used by the board. In this case I used Arduino Due, whose microcontroller is SAM3X. With other boards things could work differently (e.g. it will certainly be different for ATmega8 and ATmega168). So what is written here https://www.arduino.cc/en/Reference/PortManipulation does not apply to Arduino Due!

If you use

digitalWrite(OUTPUT_PIN_1, HIGH);
digitalWrite(OUTPUT_PIN_2, HIGH);
digitalWrite(OUTPUT_PIN_3, HIGH);

there will be about 2.5 us (microseconds) of delay between one output and the next one.

Synchronous output on multiple pins can be obtained using "port manipulation".
Take the pinout scheme of the Arduino Due board. You must choose pin numbers that converge to the same port. For example, pins 25-30 on Arduino Due map onto port D.

To initialize the pins:

int OUTPUT_PIN_1   = 25; //PD0
int OUTPUT_PIN_2   = 27; //PD2
int OUTPUT_PIN_3   = 29; //PD6
void setup() {
  pinMode(OUTPUT_PIN_1, OUTPUT); // initialize digital pin (this line is here only for code clarity, not necessary because we use direct port access)
  pinMode(OUTPUT_PIN_2, OUTPUT); // initialize digital pin (this line is here only for code clarity, not necessary because we use direct port access)
  pinMode(OUTPUT_PIN_3, OUTPUT); // initialize digital pin (this line is here only for code clarity, not necessary because we use direct port access)
  REG_PIOD_OWER = 0b00000000000000000000000001000101; 
  REG_PIOD_OER  = 0b00000000000000000000000001000101;

pinMode lines are not needed, but we keep them just to make the code more readable.
REG_PIOX_OWER and REG_PIOX_OER with X = A, B, C, D, E.
PIO_OWER: PIO (Parallel Input Output) Output Write Enable Register - write 1's here to set the pins you want to enable.
PIO_OER:  PIO (Parallel Input Output) Controller Output Enable Register - write 1's here to set pins as OUTPUT.
After 0b there are 32 bits (each port in this microcontroller is 32 bits). The first bit on the right corresponds to port pin 0, increasing leftward.
So by using REG_PIOD_OER = 0b00000000000000000000000001000101; we set PD0, PD2, and PD6 as output pins.

Then, within loop(), just use REG_PIOX_ODSR, instead of digitalWrite

REG_PIOD_ODSR = 0b00000000000000000000000001000101; // sets PD0, PD2, PD6 to HIGH
...
REG_PIOD_ODSR = 0b00000000000000000000000000000000; // sets PD0, PD2, PD6 to LOW

PIO_ODSR allows synchronous writing of the lines in the port (for more info, see 31.5.5 of SAM3X datasheet).

Useful links about Port manipulation on Arduino Due:

Pinout mapping schemes Arduino Due:

About

Digital barcodes for synchronizing data streams with different hardware clocks

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published