Giter Club home page Giter Club logo

rhythm's Introduction

rhythm firmware

Open Ephys fork of the Intan Technologies Rhythm Verilog HDL code.

The Open Ephys Acquisition Board uses a modified version of Intan's Rhythm firmware and API. While the Open Ephys acquisition board mostly works with the original firmware, we have made a few subtle changes, described below. The Open Ephys GUI uses the standard Intan API with some modifications to communicate with the Acquisition Board.

Summary of modifications

1. LED control

The Open Ephys Acquisition Board contains RGB status LEDs that require a specific driver. Here are the relevant changes made on top of the Rhythm firmware version 1.4 (26 February 2014):

xem6010.ucf:

Add the pin out for the LED string. All LEDs are driven by just one signal:

# LED data out
NET "LED_OUT" LOC="B14" | IOSTANDARD=LVCMOS33;

main.v:

Insert into module main #( in/output definitions :

output wire   LED_OUT
 
Instantiate LED controller for the WS2812 string (see LED controller subpage for info on this module).
This code is still pretty much a place holder - add actually useful information and status display here. 

// Open Ephys board status LEDs
//assign LED_OUT = 1'b0; // use to set to 0

// led controller for
// format is 24 bit red,blue,green, least? significant bit first color cor current led
LED_controller WS2812controller(
.dat_out(LED_OUT), // output to led string
.reset(reset),
.clk(clk1), // 100MHz clock
/* .led1(24'b000000000000000000000000),
.led2(24'b000000000000000000000000),
.led3(24'b000000000000000000000000),
.led4(24'b000000000000000000000000),
.led5(24'b000000000000000000000000),
.led6(24'b000000000000000000000000),
.led7(24'b000000000000000000000000),
.led8(24'b101010101010101010101010)
);
*/
.led1({data_stream_7_en_in ? {led_d1_dat,led_d2_dat} : 16'b00000001 ,8'b00000001}), // 4 SPI cable status LEDs
.led2({data_stream_5_en_in ? {led_c1_dat,led_c2_dat} : 16'b10000000 ,8'b10000000}),
.led3({data_stream_3_en_in ? {led_b1_dat,led_b2_dat} : 16'b00000000 ,8'b00000000}),
.led4({data_stream_1_en_in ? {led_a1_dat,led_a2_dat} : 8'b00000001,8'b00000001,8'b00000001}),
.led5({TTL_in,TTL_in,TTL_in}), // TTL in
.led6({TTL_out,TTL_out,TTL_out}), // TTL out
.led7({8'b00000000,8'b00000000,8'b00000000}), // Ain
.led8({DAC_register_1,DAC_register_2,8'b01000000}) //Aout
);

LED_controller.v

The WS2812 LEDs are driven by a single data line using a timing code consisting of different patterns for 1s and 0s. After 24-bit (8 bits x 3 colors) brightness levels are received by an LED, it passes on all subsequent codes to the next LED in the chain. Once a reset code (gap of >50 us) is sent, the first LED will receive data again, repeating the cycle.

We therefore want to send 24 x 8 codes, wait a bit, then repeat.

Here's a quick description of the state machine used to generate the data driving the 8 LEDs, running as a nested loop off the 100 MHz master clock:

  • An inner loop bit_state checks the led_bit register and goes through 125 states, each clk cycle lasting 0.01 us, it sets the out either to the 1 pattern, 0 pattern, or all zeros for reset
  • The GRB_state (green-red-blue) state loops every time the bit_state is 0; this loops 24 times, setting led_bit to a value from GRB_reg.
  • A third loop increments LED_state every time GRB_state is 0, and loops 8+2 times for 8 LEDs and 2 LED cycles of 30 us each to get the required >50 us of zeros for the reset. It sets LED_reg to a 24-bit color from some source value, or 0 for reset in the last 2 states.

ADC control

Instead of the Analog Devices AD7680 ADC used by Intan, we're using the Texas Instruments DS8325. The usage of the chips is almost identical, but the data timing is a bit different, requiring a small edit in ADC_input.v - instead of populating the register from channel states 4-19, we're populating from 7-22. Everything else can stay the same.

ADC_input.v:

ms_clk11_a: begin
ADC_SCLK <= 1'b1;
case (channel)

7: begin
ADC_register[15] <= ADC_DOUT;
end

8: begin
ADC_register[14] <= ADC_DOUT;
end

9: begin
ADC_register[13] <= ADC_DOUT;
end

10: begin
ADC_register[12] <= ADC_DOUT;
end

11: begin
ADC_register[11] <= ADC_DOUT;
end

12: begin
ADC_register[10] <= ADC_DOUT;
end

13: begin
ADC_register[9] <= ADC_DOUT;
end

14: begin
ADC_register[8] <= ADC_DOUT;
end

15: begin
ADC_register[7] <= ADC_DOUT;
end

16: begin
ADC_register[6] <= ADC_DOUT;
end

17: begin
ADC_register[5] <= ADC_DOUT;
end

18: begin
ADC_register[4] <= ADC_DOUT;
end

19: begin
ADC_register[3] <= ADC_DOUT;
end

20: begin
ADC_register[2] <= ADC_DOUT;
end

21: begin
ADC_register[1] <= ADC_DOUT;
end

22: begin
ADC_register[0] <= ADC_DOUT;
end

endcase
end

rhythm's People

Contributors

aacuevas avatar jsiegle avatar jvoigts avatar shayo avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rhythm's Issues

Implement daisy-chaining

The aq. boards can be daisy-chained with the .1" ribbon cable at the back. Each board has an IN and an OUT pin right now, with a small impedance matching resistor and pull-down.
The simplest way to do this should be to set each board into slave mode or leave it in default.

In default mode, the board sets the OUT pin high as long as data is being acquired.

In slave mode, the user selects a file path, config etc, and starts acquiring data as usual, but the firmware state machine is stopped until the IN pin goes high, and stops again as it goes low.

The main question is whether extra synchronization is needed. If so, then a TTL in/out channel could be used to send periodic sync. signals that we can then use in software to make everything sample perfect.

Digital Events do not seem to be written to disk in a resonable amount of time

Hey Guys,

I am testing out the reliability of a TTL pulse (100ms long) that is being sent to the Digital in (channel 1) of the RHD2000 EVALUATION board.

I get the following odd situation.

A few seconds after sending the pulse I STOP acquisition with open ephys gui. The all_channels.events file is then loaded using load_open_ephys_data.

Sometimes I see only 0 events others
1 event (channel 1 rising edge)
and still other 2 events (rising and falling edge, the time between events seems right)

In the cases where I only got 1 event I have restart acquisition. After wait long enough (sometimes it can be 10's of seconds) It seems that the 2nd event (channel 1 falling edge) will be logged to disk. The timestamp seems to be write even though the logging to disk may be an undetermined time after the event occurs.
This has happened when acquisition is restarted while appending to the same folder, I haven't yet seen the same behavior when a new folder is started but haven't tested exhaustively.

Display proper data on status LEDs

For now we're just displaying the raw data (subsampling bits for 16->8 bit) whenever the SPI is running:

.led1({SPI_running ? {led_a1_dat,led_a2_dat} : 16'b00000000 ,8'b00000000}), 
.led2({SPI_running ? {led_b1_dat,led_b2_dat} : 16'b00000000 ,8'b00000000}), 
.led3(24'b0), 
.led4(24'b0), 
.led5(24'b0), 
.led6(24'b0), 
.led7(24'b0), 
.led8(24'b0)

We should add displays for TTL and Analog in/out, as well as changing the headstage inputs to enable only when the software has recognized the headstage.

XEM7310 bitfiles

I recently bought, as recommended, the XEM7310 as the XEM6310 will be discontinued soon. However, when running the rhd2000 bitfile the following error persists when trying to configure the FPGA: "FPGA configuration failed: done did note go high". Looking through several search channels, I couldn't find anywhere specific installation documentation or possible errors, especially when it comes to the XEM7310.

Feature request: precise TTL output control from the Open Ephys aquisition board

I currently use old custom software (https://github.com/paulmthompson/Intan.jl) to control the Intan version of the acquisition board to generate pulse trains. I had to do some verilog modifications (similar to what the RHS system uses) so that I could have the FPGA generate precisely timed TTLs with custom frequency, pulse width etc.

Soon I am going to be using a different rig with a Open Ephys acquisition board. I believe OpenEphys currently lacks this functionality, correct? Consequently, I am going to have to adapt my previous custom verilog code to use the OpenEphys board.

Would you be interested if I made a pull request of this feature? I can do the verilog modifications here in this repository and generate the bitfile but I might need some help making the OpenEphys plugin.

USB3 glitching issues

(Originally comments on OpenEphys wiki)
I've gotten the Rhythm Interface largely working on XEM6310-LX150, while referencing the OpenEphys USB3 Rhythm verilog design.

One thing I'm noticing, and also pointed out by Intan Evaluation Software v1.5, is bytes-dropping in USB2 (and in my case, USB3) transfers. Intan's solution, in the updated rhd2000evalboard.cpp::readAdditionDataWords(), is to simply ignore the sample frame in which the byte drop happens, and then reads additional bytes (number of bytes per sample frame - the number of dropped bytes) to complete the frame.

This is hard to achieve with USB3 block-throttled transfer (since USB3 regular pipeouts are unreliable), since bytes transfered as to be multiples of at least 16 bytes. I can think of a few rather hacky ways, where I would stitch together data read out later with the previous ones, but I'm curious about whether you have encountered similar bytes-dropping in your USB3 development..judging from the plugin-GUI repo, I don't see any glitch-handling...

My Verilog code is here, the modified Intan Eval software is here .

Enable channel subsampling at >30Khz

It could be useful to add a function that allows users to select a (probably fixed) subset of channels in order to speed up the sample rate at the expense of channel count.
The time between samples on a RHD32 is 950ns, so a maximum sample rate is 1.05MS/s.

This gives 1050/(Nchans+3) kHz rate, so we get the following integer rate options:
32ch - 30kHz
22ch - 42kHz
18ch - 50kHz
12ch - 70kHz

The simplest way this could be implemented would be through a simple switch that modifies the state machine to reset to ch0 after some number of channels.

The most elegant solution would be to simply expand the sample rate drop down menu and add labels that indicate that above 30 only a subset of channels are sampled.
Useful sample rates are probably the existing 30kHz, and with subsampling, 42 and 50kHz?

adapt ADC control to work with the TI ADS8325

We're now using the ADS8325 instead of the analog devices AD7680 that intan uses on their eval board.

changes needed, copied from caleb's email: Data is available on the rising edge after the 7th falling edge (compared with 4th falling edge) - after the CS line goes low. If I'm understanding the verilog correctly, there are now 7 clock cycles between each conversion, so there should be space to shift
that. The order of the bits (MSB to LSB) is the same, and the polarity
of CS is the same (high to low).

Interfacing LabVIEW FPGA modules with Intan Verilog code

I'm not sure exactly where on the wiki to start this conversation, but I'm here compiling a few links on LabVIEW FPGA compilation. It's a relatively mature ecosystem that National Instruments has created, with quite a lot of resources.

I'm a newcomer to FPGA programming, but am quite fascinated by it. About all I'm bringing to the table at this point is interest and willingness.

A rough outline of the workflow
http://www.ni.com/white-paper/9381/en/

Integrating existing Verilog code into a LabVIEW FPGA project is possible:
http://digital.ni.com/public.nsf/allkb/7269557B205B1E1A86257640000910D3

In case it's appealing, there is a C API to supported FPGAs:
http://www.ni.com/white-paper/9036/en

Xilinx says that LabVIEW supports the Spartan-6, which is the device on the Opal Kelly XEM6010 board.
http://www.xilinx.com/products/intellectual-property/ni_labview.htm

Opal Kelly specifically mentions the availability of a DLL which (presumably) would allow LabVIEW to communicate to the device.
http://www.opalkelly.com/products/

OE board's LEDs should default to off

When the Rhythm FPGA component is dragged to the processing chain, the LEDs on the OE board automatically turn on. The user must click the LED button to turn them off. They are very bright. If an animal is present, they become a potentially unwanted optical stimulus. The user should have to opt in to the LEDs turning on.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.