Continuing the discussion from Intermittent Cloud Connectivity [Resolved]:
Sure.
The idea is that the 16 IO pins of the Core have been divided into 4 general 4-pin ports. On the other Core, I have tested these ports with a few modules (such as an NES controller, a PIC microcontroller, and a light sensor). On this Core, I have connected D0 to ground, and A4 to the output of a voltage divider consisting of a 1k resistor and a photoresistor, with the photoresistor going from 3.3V to A4, and the resistor going from A4 to ground. These pins correspond to port A in the code.
All other pins are high impedance.
The code follows:
// Port pins. There are 4 ports, each with 2 inputs and 2 outputs.
class Port {
int latchPin;
int strobePin;
int dataPin;
int notSerialPin;
int lastReading = 0;
public:
Port (int _latchPin, int _strobePin, int _dataPin, int _notSerialPin) {
// Set the pins...
latchPin = _latchPin;
strobePin = _strobePin;
dataPin = _dataPin;
notSerialPin = _notSerialPin;
// Initialize the pins...
pinMode (latchPin, OUTPUT);
pinMode (strobePin, OUTPUT);
pinMode (dataPin, INPUT_PULLUP);
pinMode (notSerialPin, INPUT_PULLUP);
// Initialize the outputs...
digitalWrite (latchPin, LOW);
digitalWrite (strobePin, LOW);
}
/**
* Reads the port as a serial input, and returns the read value.
*/
int serialRead () {
int reading = 0;
int i;
// Pulse LATCH for 12us to start.
digitalWrite (latchPin, HIGH);
delayMicroseconds (12);
digitalWrite (latchPin, LOW);
// Okay, now we can start reading the data.
for(i = 0; i < 8; i++) {
// Read the current bit.
reading |= (digitalRead(dataPin) << i);
// Prepare the next bit.
// This will run one more time than is strictly necessary.
delayMicroseconds (6);
digitalWrite (strobePin, HIGH);
delayMicroseconds (6);
digitalWrite (strobePin, LOW);
}
return reading;
}
/**
* Updates the lastReading variable, reading either as an analog or serial input.
* Analog inputs can be interpreted by the client software as digital.
*/
void read() {
lastReading = digitalRead (notSerialPin) ? analogRead (dataPin) : serialRead ();
}
/**
* Returns the most recent value read on this port.
*/
int getLastReading() {
return lastReading;
}
};
// Forward declations.
int readPort (String command);
// Initialize the ports.
// For forward compatibility, _notSerialPin should be capable of interrupts.
Port portA (A0, D4, A4, D0),
portB (A1, D5, A5, D1),
portC (A2, D6, A6, D2),
portD (A3, D7, A7, D3);
// Last time checked for timing.
unsigned long lastTime = 0L;
/**
* Register the readPort function, which can be called externally.
*/
void setup() {
Spark.function("readPort", readPort);
}
/**
* Update all readings periodically.
*/
void loop () {
if (millis() - lastTime >= 60) {
portA.read();
portB.read();
portC.read();
portD.read();
lastTime = millis();
}
}
/**
* Return the requested port reading.
* The port will decide whether to return a real-time reading or just the most recent value.
*
* Accepted arguments: "port_a", "port_b", "port_c", "port_d".
*
* Invalid arguments will yield a return value of -1.
*/
int readPort (String command) {
int ret = -1;
if (command == "port_a") {
ret = portA.getLastReading();
} else if (command == "port_b") {
ret = portB.getLastReading();
} else if (command == "port_c") {
ret = portC.getLastReading();
} else if (command == "port_d") {
ret = portD.getLastReading();
}
return ret;
}