Skip to content

Functionality to stream data from the XSMU [WIP] #2

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 30 commits into
base: master
Choose a base branch
from

Conversation

gitansh95
Copy link
Contributor

2.4.0 (Streamer)

Nature       : Feature
Requested by : Quazar Research

Status       : In Progress

Description

The SMU is to stream voltmeter data at a specified frequency. This requires following features to be implemented.

1) Dynamically change baudrate to suit data stream.

	-- CHANGE_BAUD

2) Start recording

	-- START_REC : Starts recording of timed data into internal buffer.

3) Transfer recorded data chunks to computer

	-- REC_SIZE : Queries number of available data points in buffer

	-- REC_DATA : Transfers requested number of data points to driver.

5) Stop recording

	-- STOP_REC : Stops recording gracefully.

6)

	-- KEEP_ALIVE : Stops recording if keep alive packets are not received, i.e. driver is dead.

@gitansh95 gitansh95 changed the title Functionality to stream data from the XSMU Functionality to stream data from the XSMU [WIP] Sep 20, 2017
@gitansh95 gitansh95 self-assigned this Sep 20, 2017
@gitansh95
Copy link
Contributor Author

Status


The SMU is to stream voltmeter data at a specified frequency. This requires following features to be implemented.

1) Dynamically change baudrate to suit data stream -- CHANGE_BAUD

    - Class `CommPacket_changeBaud` as a general communication packet for communication of the above command.

    - Classes `CommResponse_changeBaud` and `CommRequest_changeBaud` inherit the class `CommPacket_changeBaud`. `CommRequest_changeBaud` is sent from the Driver to the Firmware, when the command to change baudrate is sent. `CommResponse_changeBaud` is sent as aknowledgement from the Firmware to the Driver. Baudrate can only be set to a few standard values. Incase the baudrate specified is other than the standard values, no action is taken and a `No Operation` response is sent by the firmware to the driver.

    - Functions `setBaudRate() and `restoreBaud()` to change the UART baudrate when `CommRequest_changeBaud` packet is recieved (on Firmware side)

    - Function `setBaudRate()` to change FTDI baudrate when CommResponse_changeBaud packet is recieved. (on Driver Side)

    - Corresponding function in XSMU module's library (`libxsmu`). Also added the function to swig interface file, that makes it available in the module's python library.

    - A python test file `changeBaud.py` that tests this function.

2) Start recording -- START_REC

    - Similar communication packets as above, `CommPacket_startRec`, `CommRequest_startRec` and `CommResponse_startRec`.

    - `Acquisition` class, that is responsible for acquiring data from the ADC. `Application` class has 2 subclasses:
        a.`Queue` : Inherits from `std::queue`. Datastructure responsible for providing orderly storage, push and pop functions (among others) for the data from ADC.

        b. `AD7734_Streamer` : Inherits from `AD7734`. Provides `start()` and `stop()` functions to initialize in continous data streaming mode, specifies ADC channel to recieves data from, allows interrupts from `RDY` pin of ADC.

    - When `CommRequest_startRec` is recieved by the firmware, it calls the `start()` function of the `AD7734_Streamer` which:
        a. Configures the ADC (AD7734) to stream data in a continuous fashion to the microcontroller using an SPI interface.

        b. Configures the signal from the `RDY` pin (number 25) of the ADC to act as an external interrupt. Every time a datapoint is sent by the ADC, the interrupt triggers the Interrupt Service Routine, which pushes the datapoint into a queue in the microcontroller's RAM.

        c. Configures the channel number of the ADC to acquire from. (Currently hardcoded to channel 1 - VM). Data is now stored as available from the ADC into the controller's RAM.

	- When the above recording has successfully been started, the Firmware sends back a `CommResponse_startRec` acknowledgement to the Driver. When `CommResponse_startRec` is recieved by the Driver, it activates the `_rec` flag in the Driver which leads to transfer of recorded data from the microcontroller's RAM to the computer as described in section 7.

3) Query the number of datapoints stored in the microcontroller's RAM -- REC_SIZE

	- Communication packets `CommPacket_recSize`, `CommRequest_recSize` and `CommResponse_recSize`

	- Two queues _active_queue and _standby_queue (in firmware). Data from ADC keeps getting stored into the Active queue (interrupt driven). When Driver asks for number of datapoints, the number of datapoints in the standby queue are transmitted back (`CommResponse_recSize`). If standby queue is empty, active and standby queues are swapped, and then the number of datapoints in the standby queue are transmitted back

4) Transfer recorded data chunks to computer -- REC_DATA

	- Communication packets `CommPacket_recData`, `CommRequest_recData` and `CommResponse_recData`

	- When `CommRequest_recData` (along with requested number of datapoints) is recieved by Firmware, it transfers the requested number of datapoints from Standby queue into `CommResponse_recData` packet and transmits it back to the Driver.

	- This data transfered is int16_t (raw ADC value) and not a voltage. It is stored in a queue (`_dataq_24`).

	- The functions XX_setRange() save the active calibration table (depending on the range of current/voltage) in software. This active calibration table is used to convert the raw adc values stored in (`_dataq_24`) to voltage/current values (now stored in `_dataq`)

	- Function `get_data()` is responsible for transmitting the voltage/current data from `_dataq` to the user. Once transmitted to the user, a datapoint is removed from both `_dataq` and `_dataq_24`.

5) Stop recording -- STOP_REC

   - - Communication packets `CommPacket_StopRec`, `CommRequest_StopRec` and `CommResponse_StopRec`

   - When `CommRequest_StopRec` is recieved by the Firmware, it deactivates the ADC (stops streaming data). It then transmits `CommResponse_StopRec` back to the Driver as an acknowledgement that streaming has now been stopped.

   - When the Driver recieves the `CommResponse_StopRec` packet, it unsets the `_rec`  flag which results in the Driver ceasing to send requests to the Firmware for streamed data (as described in section 7).


6) Keep Alive -- KEEP_ALIVE

   - Keep Alive packets tell the Firmware that the Driver is listening for data. As a result the Firmware keeps collecting and streaming data. Keep alive packets are sent with a `lease_time_ms`, which specifies that the Firmware assume that the Driver is listening for atleast that period of time from which the packet was recieved by the Firmware.

   - The Firmware stops recording if keep alive packets are not received, i.e. if driver is dead.

   - Keep Alive packets are sent every one third of the `lease_time_ms` duration. (as described in section 7)

7) A Thread has been implemented in the Driver, which sends a KEEP_ALIVE packet to the firmware every lease_time_ms/3 seconds, and if `_rec` flag is set, sends REC_SIZE request, followed by REC_DATA requests until data transfer the number of datapoints returned by REC_SIZE response have been transmitted.

This thread is asynchronous in nature, and is launched when the SMU connects to the computer. The thread comes to an end when the SMU is disconnected from the computer.

@gitansh95
Copy link
Contributor Author

gitansh95 commented Sep 29, 2017

@kchat79 @nishant90git
Commit : 5aa2361

  • Added stl/memory and stl/bits/unique_ptr.h files from QDA project
  • Added #include <memory> to Application.h (where std::unique_ptr is used)

When I make these changes, I get the following error while make ihx:

Application.o: In function `main':
/usr/lib/avr/include/util/delay.h:163: undefined reference to `operator delete(void*)'
/usr/lib/avr/include/util/delay.h:163: undefined reference to `operator new(unsigned int)'
Application.o: In function `main':
/home/gitansh95/work/git/gitansh-XPLORE-firmware/XSMU-2.4.0/code/app/src/Application.cxx:79: undefined reference to `Acquisition::Acquisition()'
/home/gitansh95/work/git/gitansh-XPLORE-firmware/XSMU-2.4.0/code/app/src/Application.cxx:79: undefined reference to `operator delete(void*)'
/home/gitansh95/work/git/gitansh-XPLORE-firmware/XSMU-2.4.0/code/app/src/Application.cxx:79: undefined reference to `Acquisition::start()'
Application.o: In function `main':
/usr/lib/avr/include/util/delay.h:163: undefined reference to `Acquisition::stop()'
Application.o: In function `main':
/home/gitansh95/work/git/gitansh-XPLORE-firmware/XSMU-2.4.0/code/app/src/Application.cxx:79: undefined reference to `operator delete(void*)'
/home/gitansh95/work/git/gitansh-XPLORE-firmware/XSMU-2.4.0/code/app/src/Application.cxx:79: undefined reference to `atexit'
collect2: error: ld returned 1 exit status

I take this to mean that I have not provided definitions for new and delete operators. I also tried including <new> to Application.h and Acquisition.cxx, but the error remains. Please help.

@kchat79
Copy link

kchat79 commented Oct 2, 2017 via email

@gitansh95
Copy link
Contributor Author

The following definitions for operator new are already defined in file code/stl/new.

inline void* operator new (unsigned int size, void* at)
{
	return at;
}

inline void* operator new[] (unsigned int size, void* at)
{
	return at;
}

And these are being used in various places (eg. QP4).

Should I overwrite these definitions with the one you have provided, or do these have to coexist somehow?

@kchat79
Copy link

kchat79 commented Oct 3, 2017 via email

1. recData returns zero for all datapoints
2. Acquisiion applet instance (_acq) not implemented in Application.cxx (Removed for testing)
3. Documentation to be added
2. AD7734_Streamer not implemented yet.

Known bugs : No ADC streamer class, recData sends all datapoints as '0'
…eeps adding it to _active_queue

2. Acquisition::data_ready() returns false is both _active_queue and _standby_queue are empty; true otherwise.

Known bugs :
a. _adc->start(ADC_CHN), _adc_stop(), and _adc->readData(ADC_DATA_REGISTER|ADC_CHN) cause the XSMU to reset.
b. recData returns all datapoints as zero.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants