Can I use raw pin reading methods with the Spark Core?

Hi there, I’m trying to make my first Arduino project with the Spark Core. I picked making a universal IR remote that Instructables has on their website. I’m trying to compile their IR_RECEIVE.ino which includes using raw pin reading methods. When

I’ve changed line 19 to

#define IRpin_PIN      PINB

and it’s not compiling. Neither was the original definition as PIND. I just get

'PINB' was not declared in this scope.

Is there something I’m missing that I have to include or is this not a capability of the Spark Core?

PINB is the arduino’s input pins register using direct port manipulation.

you need to rejigger the code for Spark Core… I’m not familiar with accessing Spark Core’s port registers, but I’ll keep an eye on this thread.

It’s not anything obvious that would be in the pinout diagram, right?

digitalRead() is a macro, so it runs slower than using Direct Port Manipulation, you can see the notes in his code:

//  while (digitalRead(IRpin)) { // this is too slow!
    while (IRpin_PIN & (1 << IRpin)) {

Since the Spark is a faster processor, try using digitalRead() by just changing his code to the notated version like this:

meanwhile, we can look to see how to get readings from the pins without the digitalRead() macro…

/* Raw IR decoder sketch!
 
 This sketch/program uses the Arduno and a PNA4602 to 
 decode IR received. This can be used to make a IR receiver
 (by looking for a particular code)
 or transmitter (by pulsing an IR LED at ~38KHz for the
 durations detected 
 
 Code is public domain, check out www.ladyada.net and adafruit.com
 for more tutorials! 
 */
 
// We need to use the 'raw' pin reading methods
// because timing is very important here and the digitalRead()
// procedure is slower!
//uint8_t IRpin = 2;
// Digital pin #2 is the same as Pin D2 see
// http://arduino.cc/en/Hacking/PinMapping168 for the 'raw' pin mapping
//#define IRpin_PIN      PIND
#define IRpin          2
 
// the maximum pulse we'll listen for - 65 milliseconds is a long time
#define MAXPULSE 65000
 
// what our timing resolution should be, larger is better
// as its more 'precise' - but too large and you wont get
// accurate timing
#define RESOLUTION 20 
 
// we will store up to 100 pulse pairs (this is -a lot-)
uint16_t pulses[100][2];  // pair is high and low pulse 
uint8_t currentpulse = 0; // index for pulses we're storing
 
void setup(void) 
{
  pinMode(IRpin,OUTPUT);
  Serial.begin(9600);
  Serial.println("Ready to decode IR!");
}
 
void loop(void) {
  uint16_t highpulse, lowpulse;  // temporary storage timing
  highpulse = lowpulse = 0; // start out with no pulse length
 
 
    while (digitalRead(IRpin)) { // this is too slow!
    //while (IRpin_PIN & (1 << IRpin)) {
     // pin is still HIGH
 
     // count off another few microseconds
     highpulse++;
     delayMicroseconds(RESOLUTION);
 
     // If the pulse is too long, we 'timed out' - either nothing
     // was received or the code is finished, so print what
     // we've grabbed so far, and then reset
     if ((highpulse >= MAXPULSE) && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  // we didn't time out so lets stash the reading
  pulses[currentpulse][0] = highpulse;
 
  // same as above
  while (!digitalRead(IRpin)) {
  //while (! (IRpin_PIN & _BV(IRpin))) {
     // pin is still LOW
     lowpulse++;
     delayMicroseconds(RESOLUTION);
     if ((lowpulse >= MAXPULSE)  && (currentpulse != 0)) {
       printpulses();
       currentpulse=0;
       return;
     }
  }
  pulses[currentpulse][1] = lowpulse;
 
  // we read one high-low pulse successfully, continue!
  currentpulse++;
}
 
void printpulses(void) {
  Serial.println("\n\r\n\rReceived: \n\rOFF \tON");
  for (uint8_t i = 0; i < currentpulse; i++) {
    Serial.print(pulses[i][0] * RESOLUTION, DEC);
    Serial.print(" usec, ");
    Serial.print(pulses[i][1] * RESOLUTION, DEC);
    Serial.println(" usec");
  }
}

There is more here regarding the topic… ways that may work for you.

While the speed thing is true and digitalRead is plenty fast, there is a port read too.

e.g.
In the pinout diagram you see D0 equals PB7 so it’s located on GPIOB port bit 7.

So when your pins are setup for digital read you could do int portb = GPIOB->IDR; to obtain all 16 bits of port B an pick out the pins you want.

Here are some other useful makros for speedier access

#if defined(SPARK)
  // fast pin access
  #define pinLO(_pin)	(PIN_MAP[_pin].gpio_peripheral->BRR = PIN_MAP[_pin].gpio_pin)
  #define pinHI(_pin)	(PIN_MAP[_pin].gpio_peripheral->BSRR = PIN_MAP[_pin].gpio_pin)
  #define pinSet(_pin, _hilo) (_hilo ? pinHI(_pin) : pinLO(_pin))
  
  // even faster port based multi pin access
  #define portSet(_port, _word) (_port->ODR = _word)
  #define portSetMasked(_port, _word, _mask) (_port->BSRR = (_mask << 16) | (_word & _mask))
#endif
2 Likes

Thanks guys, super helpful stuff. I’ll try this and report back.

BTW in Spark world digitalRead() is not a macro but a function.
If you want to know why it is so much slower than direct port access you can have a look in the Open Source files

Yes, I understood that, thanks.

It seems it is not as friendly on Spark, coming from Arduino. Also not a lot of examples here, yet.

Sorry, if I came across wrong - I didn’t mean to be clever :wink:
This comment was mainly meant for @KlooShanko to show where to find some morw background info.