Jump to content
  • 0

Analog Discovery 3 - SPI Slave + SPI Master Script


injection

Question

Hello everyone,

I’m working on a project where I need to implement a safety mechanism test using SPI communication, and I could really use some help. I’m using the Analog Discovery 3 for this task.

Objective:

  • SPI Channel 1 (configured as a slave) will receive data.
  • If the incoming data matches a specific pattern, I want to modify this data.
  • Then, the modified data should be transmitted on SPI Channel 2 (configured as a master).

What I Have So Far:

I’ve managed to set up basic SPI communication, but I’m having trouble figuring out how to implement this dual-channel setup, where one channel reads as a slave and the other transmits as a master after modifying the data.

Specifics:

  • SPI Channel 1 (Slave): Should continuously listen for incoming data.
  • Data Matching: When specific data (e.g., 0x00 0x01 0x01 0x00 0x01 0xF4) is received on the slave channel, I need to modify the last byte (e.g., change 0xF4 to 0xF5).
  • SPI Channel 2 (Master): The modified data should then be sent out from the master channel.

Has anyone implemented something similar using Analog Discovery 3? Could you provide guidance or sample scripts on how to configure both channels (one as slave, one as master), handle the data modification, and write the data to another channel?

Any advice, example scripts, or resources would be greatly appreciated!

 

// Initialize SPI communication
var CH1_cs = 0;  // Chip select for Channel 1 (slave)
var CH2_cs = 1;  // Chip select for Channel 2 (master)

Protocol.SPI.Receiver(CH1_cs); // Start receiver for Channel 1 (slave)
    

// Loop for continuous operation
while(wait()){ 
    // Receive data on Channel 1 (slave)
    var rg = Protocol.SPI.Receive(CH1_cs); // Receiving data from SPI slave channel
    var c = rg.length;
    if(!c) continue;
    
    // Build MOSI string for comparison
    var szMosi = "MOSI: ";
    var mosiValues = [];
    
    for(var i = 0; i < c; i+=2){
        // Convert to hex and pad with leading zero if necessary
        var mosiHex = rg[i].toString(16).toUpperCase();
        if(mosiHex.length < 2) mosiHex = '0' + mosiHex;
        
        mosiValues.push(mosiHex);
        szMosi += " 0x" + mosiHex;
    }
    
    print(szMosi);
    
    // Check if MOSI is exactly "0x00 0x01 0x01 0x00 0x01 0xF4"
    if(mosiValues.join(' ') === "00 01 01 00 01 F4") {
        print("Matching data found. Changing last value to 0xF5...");
        
        // Modify the last MOSI value from 0xF4 to 0xF5
        rg[rg.length - 2] = 0xF5; // Modify the MOSI part of the data
        
        // Send the modified data through Channel 2 (master)
        //Protocol.SPI.Transmit(rg, CH2_cs); // Master transmits on Channel 2
        //Protocol.SPI.Write(8,[0x00,0x01,0x01,0x00,0x01,0xF4])
        
        // Print the modified data
        var modifiedMosi = "MOSI: ";
        for(var i = 0; i < c; i+=2){
            var mosiHex = rg[i].toString(16).toUpperCase();
            if(mosiHex.length < 2) mosiHex = '0' + mosiHex;
            modifiedMosi += " 0x" + mosiHex;
        }
        print("Modified " + modifiedMosi);
    }
    
    print("---");
}

image.png.bf04a420fa5b0f3e31e10c6cd29c52b0.png

Link to comment
Share on other sites

4 answers to this question

Recommended Posts

  • 0
48 minutes ago, attila said:

Hi @injection

Only one protocol can be used at a time in a device. The master and slave SPI can only operate in sequence, switching between these two or any others.

Thanks for your reply attila.

In that case with single device, I need to do configuration as Slave, read data, switch configuration to Master and forward it?

What if I use 2x devices? In that case is it possible to have Slave running in one device, master in the second one and share data between it?

Is there an example for something close to the configuration switching? 

I was also trying with SDK python, but here I cant read anything.

from ctypes import *
import math
import sys
import time
import numpy

if sys.platform.startswith("win"):
    dwf = cdll.LoadLibrary("dwf.dll")
elif sys.platform.startswith("darwin"):
    dwf = cdll.LoadLibrary("/Library/Frameworks/dwf.framework/dwf")
else:
    dwf = cdll.LoadLibrary("libdwf.so")

hdwf = c_int()

rgbTX = (c_ubyte*8)(0,1,2,3,4,5,6,7)
rgbRX = (c_ubyte*8)()

print("Opening first device")
dwf.FDwfDeviceOpen(c_int(-1), byref(hdwf))
# device configuration of index 3 (4th) for Analog Discovery has 16kS digital-in/out buffer
# dwf.FDwfDeviceConfigOpen(c_int(-1), c_int(3), byref(hdwf))

if hdwf.value == 0:
    print("failed to open device")
    szerr = create_string_buffer(512)
    dwf.FDwfGetLastErrorMsg(szerr)
    print(str(szerr.value))
    quit()

print("Configuring SPI CH1")
# Configure the first SPI channel (DIO 0 - CS , DIO 1 - SCK, DIO 2 - MISO)
dwf.FDwfDigitalSpiModeSet(hdwf, c_int(1))  # Mode 1
dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e6))  # 1 MHz frequency
dwf.FDwfDigitalSpiClockSet(c_int(1))  # DIO 1 for clock (SCK)
# idxDQ – specify data index to set, 0 = DQ0_MOSI_SISO, 1 = DQ1_MISO, 2 = DQ2, 3 = DQ3
# idxChannel – DIO channel to use for SPI data
dwf.FDwfDigitalSpiDataSet(hdwf, c_int(1), c_int(2))  # 1 DQ1_MISO = DIO-2
dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(0), c_int(1))  # CS: DIO-0, idle high
dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1))  # 1 MSB first

print("Configuring SPI CH2")
# Configure the first SPI channel (DIO 3 - CS , DIO 4 - SCK, DIO 5 - MOSI)
dwf.FDwfDigitalSpiModeSet(hdwf, c_int(1))  # Mode 1
dwf.FDwfDigitalSpiFrequencySet(hdwf, c_double(1e6))  # 1 MHz frequency
dwf.FDwfDigitalSpiClockSet(c_int(4))  # DIO 4 for clock (SCK)
# idxDQ – specify data index to set, 0 = DQ0_MOSI_SISO, 1 = DQ1_MISO, 2 = DQ2, 3 = DQ3
# idxChannel – DIO channel to use for SPI data
dwf.FDwfDigitalSpiDataSet(hdwf, c_int(0), c_int(5))  # 0 DQ0_MOSI_SISO = DIO-5
dwf.FDwfDigitalSpiSelectSet(hdwf, c_int(3), c_int(1))  # CS: DIO-3, idle high
dwf.FDwfDigitalSpiOrderSet(hdwf, c_int(1))  # 1 MSB first

while True:
    dwf.FDwfDigitalSpiRead(hdwf, c_int(1), c_int(8), rgbRX, c_int(len(rgbRX)))
    # Convert each byte in rgbRX to a hexadecimal string with leading zeros
    hex_values = ['0x{:02X}'.format(x) for x in numpy.fromiter(rgbRX, dtype=numpy.uint8)]
    # Join the hex values into a single string separated by spaces
    print("RX: " + ' '.join(hex_values))

    dwf.FDwfDigitalSpiWrite(hdwf, c_int(0), c_int(8), rgbTX, c_int(len(rgbTX)))
    # Convert each byte in rgbRX to a hexadecimal string with leading zeros
    hex_values = ['0x{:02X}'.format(x) for x in numpy.fromiter(rgbTX, dtype=numpy.uint8)]
    # Join the hex values into a single string separated by spaces
    # print("TX: " + ' '.join(hex_values))
    time.sleep(0.1)

 

Link to comment
Share on other sites

  • 0

Hi @injection

Currently WF application can handle one protocol even when it connects to two devices. You would need two separate instances of the application to use two protocols and file io, named pipe, tcp for communication between the two scripts.... Later I could improve this to be able to use two protocols with two devices.
Currently with SDK functions only SPI master and spy is supported. Slave could be implemented using ROM logic, but this would be complicated.

Link to comment
Share on other sites

  • 0
7 minutes ago, attila said:

Hi @injection

Currently WF application can handle one protocol even when it connects to two devices. You would need two separate instances of the application to use two protocols and file io, named pipe, tcp for communication between the two scripts.... Later I could improve this to be able to use two protocols with two devices.
Currently with SDK functions only SPI master and spy is supported. Slave could be implemented using ROM logic, but this would be complicated.

Oh well, thanks for the info.

I will give a try with two devices, one as Spy and another one as Master, and find which is the fastest way to share data between both instances.

With Spy I can read the information I need:

 

image.png.a1b0a59b8c851627a8d83ebd83097a49.png

 

Thanks again, would be nice to see those features implemented to WS, specially 2 instances of protocol, as of now I could not find any tool to help me with this test.
 

Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...