Is there a generic way to access a per macrodefinition defined port P, on Photon?

Is there a generic way to access a per macrodefinition defined port P, on Photon?

i.e. :

#define SS_DDR  <PORT D>
#define PIN SS_DDR <insert magic here to map to pin 2, for example>
pinMode(PIN, OUTPUT);

I’m working on adapting some code to interface RFM12b with the Photon, and I seek to adapt the code for the data direction and port register mapping from AVR to Photon:

#define SS_DDR      DDRB
#define SS_PORT     PORTB

The port layout on STM32 controllers is completely different to AVR controllers.

e.g. AFAIK the equivalent of the data direction register uses two bits per pin on STM32 rather than only one on AVRs.
To port a lib from AVR to STM you’d need to dive in a bit deeper :wink:

On the other hand setting up the SPI interface, why not just use the dedicated SPI object?

… because the pins from my breakout don’t line up 1:1 with the Photon’s and I need to implement the SPI manually or make a hw-mapping. :slight_smile:

Which pins do you need to use? Why exactly these?
And what do you mean with line up 1:1?

There are also some SoftSPI implementations around, maybe @peekay123 can chime in on that.

The order of the SPI pins on the breakout board in the link is not the same as the order of the SPI on the Photon. It’s no big deal, but I need to either build my own board or come up with a solution with airwires. Or use sw-spi.

I’m using pins A0-DAC to interface with RFM12.

@mihaigalos, first things first. The STM32 doesn’t use the same port control ports as Arduino. As such, there are low-level (high speed) port functions available to toggle pins directly.

Unless you get into the open-source system firmware and make substantial changes, you will not be able to remap the hardware SPI pins. I’m not sure why you need 1:1 mapping since you can wire the two together the way it needs to be wired. Can you explain?

I have some simple code that implements “true” software SPI. What I mean by true is that it will write to and read from the specified software SPI pins like the standard SPI.transfer() function does. I can post it if that interests you.


Hello @peekay123,
That would be awesome if you can post your sw-spi implementation. Thank you.

@mihaigalos, here you go:

// Set software SPI pin values - I used the same as the hardware SPI pins
// but you can change to any pins
const int _csPin = A2;
const int _clockPin = A3;
const int _misoPin = A4;
const int _mosiPin = A5;

	// Set the soft SPI pin modes
	pinMode(_csPin, OUTPUT);
	digitalWrite(_csPin, HIGH);
	pinMode(_mosiPin, OUTPUT);
	digitalWrite(_mosiPin, LOW);
	pinMode(_misoPin, INPUT);
	pinMode(_clockPin, OUTPUT);
	digitalWrite(_clockPin, LOW);


	SPIxfer(data);			// call that only writes data with no return value expected
	byte val = SPIxfer(0xFF);	// call that writes dummy value and expects return data

//inline __attribute__((always_inline))
byte SPIxfer(byte data) {
	byte b=0, bit;

	for (bit = 0; bit < 8; bit++)  { 	// walks down mask from bit 7 to bit 0
		digitalWriteFast(_mosiPin, !!(data & (1 << (7 - bit))));
		b |= pinReadFast(_misoPin) << (7 - bit);

	return b;

The only pins you’d need to cross for HW SPI are the MOSI/MISO pins, since SCK can be taken fix, SS is software adjustable and 3.3/0V can be provided via any GPIO and IRQ could be almost amy other pin too.

You even have the option to use SPI1 (D2~D4 / SS free to choose) if that would suite you better.

If I can, I’d always go for HW SPI.


I’m afraid I don’t understand. The info on MOSI / MISO is interpreted on the rising or falling edge of the SCK?

If the physical location of your desired HW SCK pin (A3 or D4) provides your “anchor point” for the setup, you’d only need to “twist” MOSI and MISO - the rest of the pins can be 1:1 wired and controlled via SW.
You can even play with the orientation of your board (flip side, beside or under the Photon).