It’s not pretty yet, but it’s working! Just a proof of concept that it can be done, pretty easily too:
(EDIT: see my next post for the port I made of adafruit’s library for the spark core on github)
Code:
uint32_t rgb;
uint16_t neoPin = D0;
void setPixel(uint32_t grb) {
uint8_t i;
uint8_t grb_bit = 23;
uint32_t grb_mask = 0x00800000;
for (i = 0; i < 24; i++) {
if (grb & (1 << grb_bit)) {
// 700ns HIGH (meas. 680ns)
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
// 600ns LOW (meas. 612ns)
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
} else {
// 350ns HIGH (meas. 348ns)
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
PIN_MAP[neoPin].gpio_peripheral->BSRR = PIN_MAP[neoPin].gpio_pin; // HIGH
// 800ns LOW (meas. 808ns)
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
PIN_MAP[neoPin].gpio_peripheral->BRR = PIN_MAP[neoPin].gpio_pin; // LOW
}
grb_bit--;
grb_mask = grb_mask >> 1;
}
}
// Packs and sets a 32-bit color from individual colors
void setRGB(uint8_t red, uint8_t green, uint8_t blue) {
uint32_t grb = ((uint32_t) red << 16) + ((uint32_t) green << 16) + blue;
setPixel(grb);
}
// Reorders and sets a 32-bit packed color
void setColor(uint32_t color) {
uint32_t grb = ((uint32_t)(color >> 8) & 0x0000FF00) + (uint32_t)((color << 8) & 0x00FF0000) + (uint32_t)(color & 0x000000FF);
setPixel(grb);
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t j;
for (j = 0; j < 256; j++) { // 1 cycle of all colors on wheel
setColor(Wheel(j));
delayMicroseconds(wait * 1000);
}
}
// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(uint8_t WheelPos) {
if (WheelPos < 85) {
return packColor(WheelPos * 3, 255 - WheelPos * 3, 0);
} else if (WheelPos < 170) {
WheelPos -= 85;
return packColor(255 - WheelPos * 3, 0, WheelPos * 3);
} else {
WheelPos -= 170;
return packColor(0, WheelPos * 3, 255 - WheelPos * 3);
}
}
// Convert separate R,G,B into packed 32-bit RGB color.
// Packed format is always RGB, regardless of LED strand color order.
uint32_t packColor(uint8_t r, uint8_t g, uint8_t b) {
uint32_t rgb = (((uint32_t) r << 16) + ((uint32_t) g << 8) + b);
return rgb;
}
void setup() {
pinMode(neoPin, OUTPUT);
}
void loop() {
rgb = 0x00000FF;
//setColor(rgb);
rainbowCycle(20);
}
As you can see, I didn’t spend a lot of time on the “timing” part… running the bit-banging part over and over again was a dirty way to do it. However it works well as you can see from the measured timing and demo. I think there are little glitches every no and then because of interrupts that should probably be turned off during the critical timing… or, driving at 3.3V. I seem to recall this 3.3V issue before was the reason it was a tad glitchy.
If anyone can point me a better way to burn 1 cycle, please let me know. I tried Nop(); and nop(); to no avail.
Anyhoo, I said I’d keep you up to date on anything that’s happening… so you got it! Down and dirty.