Dec 14

The RoboCAN interface was developed to provide a fast serial link between the Primary motor cortexand the various sensors and actuators acting like a spinal cord. The second interface needed is between the primary motor cortex and the brains: the FOXBoard.

The initial plan was to have a memory mapped interface using available IO pins on the FB. Using an 8-bit address bus would provide 256 unique locations. Each location could indicate a specific command resulting in 256 commands, writing to a specific address could trigger that command using the 8-bit data as a parameter.  Although this looks to be enough I’m not sure it will be for two reasons:

  • Command most likely require more than one data byte
  • The 256 address locations will need to be divided over more than one add-on board

Without a good solution for above two problems, it would be better to use some sort of serial protocol were more bytes are written to a specific location.

While writing above statement, this can actually be a solution for the first problem. If indeed each memory location is a command but it requires more than one data bytes, why not write more than ones to this location and only execute the command when all bytes are received? If the amount of bytes is know for each command than there would not even be a need to include a NumberOfBytes parameter. Simply start counting bytes and when the amount required has been received than execute the command. If on the same address additional write cycles are detected, assume these are for a new command. The same principle can be used for a command that reads data from the add-on board. If two data bytes must be read, two read cycles from that location are required.

Using this solution already reduces the severity of the second reason. Now there are actually 256 individual commands to be divided over several add-on boards. Since most micro controllers that will be on an add-on board are of the AT90CAN series it would be an option to increase the number of address bits since there is plenty of IO pins on such devices.

On Port G on the FB IOG8..IOG15 provide eight consecutive bi-directional pins for the data bus. The next eight IO pins IOG16..IOG23 can be used for the address bus, these are input/output pins but than only used as output. Since from a software point of view you do not want to split the address over various bits on port G additional address pins than should use IOG24, IOG25 and so on. IOG24 is free so this increases the amount of command to 512. Pin 25 is split into I25 and O25. I25 is used for an USB interface, so it would not be wise to use this one. On the other hand we need an output and O25 is free increasing the amount of commands to 1024 which would take away my worry.

I’m not sure how this split between input and output is made, they are on different pins on the connectors (pin J7.14 and J7.13) so it seems that these are two pins on the processor were the read or write access determines which pin is used. But this worries me since it states that software defines which pin is used, so if some software block is added that uses the USB interface you can get conflicts between my software and the USB software each configuring this signal. Checking the schematic of the FB shows that the USB connectors that are soldered on the board use USB1 and USB2 so these pins are in use.

When searching for the schematic, I also found how to make use of the IO pins in software. It seems you can not directly write a value to the IO pins, there is a function to set a pin and a function to clear a pin. I guess this makes sense since there are multiple processes working on the port in parallel. A normal read-modify-write action would not work since during the modify part another process might have changed an output which is than modified back during the write part. 

// Set the lines specified by the bit mask “iomask” to 1

// Set the lines specified by the bit mask “iomask” to 0

The IO mask defines which bits are set or cleared, a 1 execute the task, a 0 is ignored. To set “a” specific address on the port would therefor require two calls, one for setting the 0’s and one for settings the 1’s. Assume a 18 bit wide port were the lower 8 are the data bus, the next 8 are the address bus, than the /WR signal and finally the /RD signal. Writing the value 0b00001111 to address 0b00110011 would than result in:

ioctl (some command to set databus to output);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_SETBITS), 0b01 00110011 00001111);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_CLRBITS), 0b01 11001100 11110000);

Since in both cases the /WR bit is set and first the SETBITS is used this will result in a faling flank on /WR when the second IO call is executed. The receiver can use this flank by connecting it to an interrupt pin and in the ISR copy the date from the address and data part (after a slight delay) and execute the command.

A read from address 0b00110011 would result in:

ioctl (some command to set databus to input);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_SETBITS), 0b10 00110011 11111111);

ioctl(fd,_IO(ETRAXGPIO_IOCTYPE,IO_CLRBITS), 0b10 11001100 00000000);

and after waiting a bit:


Also here the falling flank on /RD can be used for triggering an ISR to place the data on the bus and remove it after some delay or when the /RD pin become 1 again. For this it might be smart to also set the /RD in the first call for writing a command. Also setting the direction of the databus only needs to be done when the previous command was different (read versus write).

All this brings two conclusions:

  • There is no need to map the address part in an consecutive set of pins
  • It requires two to four IO calls per command

The first conclusion is perhaps not clear, reason for this is that the command will be defined as a constant value in the application (most likely). It is not needed to take an address, split it in multiple parts and using shift functions to place the bits in the right location.

So, using OG3..OG5, IOG8..IOG15 as address lines, IOG16..IOG23 as data lines, IOG0 as /RD and OG1 as /WR would provide a 2048 possible commands using 8 bit data. That should be more than enough!

That leaves the interrupt signal, since there is no true interrupt support in the normal IO driver this might require a custom device driver. All input pins can be used as a interrupt pin, so IG3 will do the trick.

OG4 and OG5 can be used for driving 2 LED’s, these always prove to be handy during development and can indicate data transfer in the final application.

Finally, it would be nice to add an SD-card slot as well. This has nothing to do with the primary motor cortex but if the application becomes big or requires lots of storage for storing collected data it is good to put this on a replaceable SD-card instead of writing the internal FLASH of the FB all the time. There is a schematic of the ZigBee add-on board that also provides an SD-card. Damn! This uses port G as well: IG1, OG1, OG3 and OG4. Exactly the same pins as for my extended address lines, /WR and /INT.

But is does seem input pins are not linked to output pins when they are separately available on the FB. The data from the SD-card is read using IG1 while the clock for the card is generated using OG1. I will do a small test later to easy my mind, but for now that leaves below listed unused pins:

  • IOG0, IG2..IG5, OG5, IOG24, OG25, OG28 and OG29

After a reset the FB will set a specific direction and state to all IO pins. To prevent direction conflicts the AT90CAN will set all IO pins to input except for the /INT output. For this reason it is best to use a dedicated input pin on the FOXBoard, for example IG2. Than the connection could be:

  • /INT on IG2
  • Data 0..7 on IOG8..IOG15
  • Address 0..9 on IOG16..IOG24, OG25
  • /RD on OG28
  • /WR on OG29
  • LED on OG5

As a result: 1024 possible commands that can use 8 bits of data, read and write, interrupt and a debug LED.

Leave a Comment

Please note: Comment moderation is enabled and may delay your comment. There is no need to resubmit your comment.