Direct control of ports and pins

This eliminates calls to pinMode(), digitalWrite(), functions to
initialize hardware, etc.

New 2 parameter version of digitalWriteRGB() added, which sets an
individual RGB LED on or off digitally.

New function SPItransfer() added to replace Arduino SPI.transfer().
This commit is contained in:
Scott Allen 2017-03-15 14:10:19 -04:00
parent 4ff6973a4b
commit 1e7f251ce0
5 changed files with 319 additions and 141 deletions

View File

@ -75,6 +75,7 @@ setTextColor KEYWORD2
setTextBackground KEYWORD2 setTextBackground KEYWORD2
setTextSize KEYWORD2 setTextSize KEYWORD2
setTextWrap KEYWORD2 setTextWrap KEYWORD2
SPItransfer KEYWORD2
systemButtons KEYWORD2 systemButtons KEYWORD2
toggle KEYWORD2 toggle KEYWORD2
width KEYWORD2 width KEYWORD2

View File

@ -71,23 +71,23 @@ void Arduboy2Base::flashlight()
void Arduboy2Base::systemButtons() { void Arduboy2Base::systemButtons() {
while (pressed(B_BUTTON)) { while (pressed(B_BUTTON)) {
digitalWrite(BLUE_LED, RGB_ON); // turn on blue LED digitalWriteRGB(BLUE_LED, RGB_ON); // turn on blue LED
sysCtrlSound(UP_BUTTON + B_BUTTON, GREEN_LED, 0xff); sysCtrlSound(UP_BUTTON + B_BUTTON, GREEN_LED, 0xff);
sysCtrlSound(DOWN_BUTTON + B_BUTTON, RED_LED, 0); sysCtrlSound(DOWN_BUTTON + B_BUTTON, RED_LED, 0);
delay(200); delay(200);
} }
digitalWrite(BLUE_LED, RGB_OFF); // turn off blue LED digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
} }
void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal) { void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal) {
if (pressed(buttons)) { if (pressed(buttons)) {
digitalWrite(BLUE_LED, RGB_OFF); // turn off blue LED digitalWriteRGB(BLUE_LED, RGB_OFF); // turn off blue LED
delay(200); delay(200);
digitalWrite(led, RGB_ON); // turn on "acknowledge" LED digitalWriteRGB(led, RGB_ON); // turn on "acknowledge" LED
EEPROM.update(EEPROM_AUDIO_ON_OFF, eeVal); EEPROM.update(EEPROM_AUDIO_ON_OFF, eeVal);
delay(500); delay(500);
digitalWrite(led, RGB_OFF); // turn off "acknowledge" LED digitalWriteRGB(led, RGB_OFF); // turn off "acknowledge" LED
while (pressed(buttons)) {} // Wait for button release while (pressed(buttons)) {} // Wait for button release
} }
@ -95,7 +95,7 @@ void Arduboy2Base::sysCtrlSound(uint8_t buttons, uint8_t led, uint8_t eeVal) {
void Arduboy2Base::bootLogo() void Arduboy2Base::bootLogo()
{ {
digitalWrite(RED_LED, RGB_ON); digitalWriteRGB(RED_LED, RGB_ON);
for (int8_t y = -18; y <= 24; y++) { for (int8_t y = -18; y <= 24; y++) {
if (pressed(RIGHT_BUTTON)) { if (pressed(RIGHT_BUTTON)) {
@ -104,10 +104,12 @@ void Arduboy2Base::bootLogo()
} }
if (y == -4) { if (y == -4) {
digitalWriteRGB(RGB_OFF, RGB_ON, RGB_OFF); // green LED on digitalWriteRGB(RED_LED, RGB_OFF); // red LED off
digitalWriteRGB(GREEN_LED, RGB_ON); // green LED on
} }
else if (y == 24) { else if (y == 24) {
digitalWriteRGB(RGB_OFF, RGB_OFF, RGB_ON); // blue LED on digitalWriteRGB(GREEN_LED, RGB_OFF); // green LED off
digitalWriteRGB(BLUE_LED, RGB_ON); // blue LED on
} }
clear(); clear();
@ -122,7 +124,7 @@ void Arduboy2Base::bootLogo()
} }
delay(750); delay(750);
digitalWrite(BLUE_LED, RGB_OFF); digitalWriteRGB(BLUE_LED, RGB_OFF);
bootLogoExtra(); bootLogoExtra();
} }

View File

@ -11,12 +11,12 @@ bool Arduboy2Audio::audio_enabled = false;
void Arduboy2Audio::on() void Arduboy2Audio::on()
{ {
// fire up audio pins // fire up audio pins by seting them as outputs
#ifdef ARDUBOY_10 #ifdef ARDUBOY_10
pinMode(PIN_SPEAKER_1, OUTPUT); bitSet(SPEAKER_1_DDR, SPEAKER_1_BIT);
pinMode(PIN_SPEAKER_2, OUTPUT); bitSet(SPEAKER_2_DDR, SPEAKER_2_BIT);
#else #else
pinMode(PIN_SPEAKER_1, OUTPUT); bitSet(SPEAKER_1_DDR, SPEAKER_1_BIT);
#endif #endif
audio_enabled = true; audio_enabled = true;
} }
@ -24,12 +24,12 @@ void Arduboy2Audio::on()
void Arduboy2Audio::off() void Arduboy2Audio::off()
{ {
audio_enabled = false; audio_enabled = false;
// shut off audio pins // shut off audio pins by setting them as inputs
#ifdef ARDUBOY_10 #ifdef ARDUBOY_10
pinMode(PIN_SPEAKER_1, INPUT); bitClear(SPEAKER_1_DDR, SPEAKER_1_BIT);
pinMode(PIN_SPEAKER_2, INPUT); bitClear(SPEAKER_2_DDR, SPEAKER_2_BIT);
#else #else
pinMode(PIN_SPEAKER_1, INPUT); bitClear(SPEAKER_1_DDR, SPEAKER_1_BIT);
#endif #endif
} }
@ -50,6 +50,8 @@ void Arduboy2Audio::begin()
{ {
if (EEPROM.read(EEPROM_AUDIO_ON_OFF)) if (EEPROM.read(EEPROM_AUDIO_ON_OFF))
on(); on();
else
off();
} }
bool Arduboy2Audio::enabled() bool Arduboy2Audio::enabled()

View File

@ -6,40 +6,6 @@
#include "Arduboy2Core.h" #include "Arduboy2Core.h"
// need to redeclare these here since we declare them static in .h
volatile uint8_t *Arduboy2Core::csport, *Arduboy2Core::dcport;
uint8_t Arduboy2Core::cspinmask, Arduboy2Core::dcpinmask;
const uint8_t PROGMEM pinBootProgram[] = {
// buttons
PIN_LEFT_BUTTON, INPUT_PULLUP,
PIN_RIGHT_BUTTON, INPUT_PULLUP,
PIN_UP_BUTTON, INPUT_PULLUP,
PIN_DOWN_BUTTON, INPUT_PULLUP,
PIN_A_BUTTON, INPUT_PULLUP,
PIN_B_BUTTON, INPUT_PULLUP,
// RGB LED (or single blue LED on the DevKit)
#ifdef ARDUBOY_10
RED_LED, INPUT_PULLUP, // set INPUT_PULLUP to make the pin high when
RED_LED, OUTPUT, // set to OUTPUT
GREEN_LED, INPUT_PULLUP,
GREEN_LED, OUTPUT,
#endif
BLUE_LED, INPUT_PULLUP,
BLUE_LED, OUTPUT,
// audio is specifically not included here as those pins are handled
// separately by `audio.begin()`, `audio.on()` and `audio.off()` in order
// to respect the EEPROM audio settings
// OLED SPI
DC, OUTPUT,
CS, OUTPUT,
RST, OUTPUT,
0
};
const uint8_t PROGMEM lcdBootProgram[] = { const uint8_t PROGMEM lcdBootProgram[] = {
// boot defaults are commented out but left here in case they // boot defaults are commented out but left here in case they
// might prove useful for reference // might prove useful for reference
@ -114,7 +80,6 @@ void Arduboy2Core::boot()
setCPUSpeed8MHz(); setCPUSpeed8MHz();
#endif #endif
SPI.begin();
bootPins(); bootPins();
bootOLED(); bootOLED();
@ -143,58 +108,135 @@ void Arduboy2Core::setCPUSpeed8MHz()
} }
#endif #endif
// Pins are set to the proper modes and levels for the specific hardware.
// This routine must be modified if any pins are moved to a different port
void Arduboy2Core::bootPins() void Arduboy2Core::bootPins()
{ {
uint8_t pin, mode; #ifdef ARDUBOY_10
const uint8_t *i = pinBootProgram;
while(true) { // Port B INPUT_PULLUP or HIGH
pin = pgm_read_byte(i++); PORTB |= _BV(RED_LED_BIT) | _BV(GREEN_LED_BIT) | _BV(BLUE_LED_BIT) |
mode = pgm_read_byte(i++); _BV(B_BUTTON_BIT);
if (pin==0) break; // Port B INPUT or LOW (none)
pinMode(pin, mode); // Port B inputs
} DDRB &= ~(_BV(B_BUTTON_BIT));
// Port B outputs
DDRB |= _BV(RED_LED_BIT) | _BV(GREEN_LED_BIT) | _BV(BLUE_LED_BIT) |
_BV(SPI_MOSI_BIT) | _BV(SPI_SCK_BIT);
digitalWrite(RST, HIGH); // Port C
delay(1); // VDD (3.3V) goes high at start, lets just chill for a ms // Speaker: Not set here. Controlled by audio class
digitalWrite(RST, LOW); // bring reset low
delay(10); // wait 10ms // Port D INPUT_PULLUP or HIGH
digitalWrite(RST, HIGH); // bring out of reset PORTD |= _BV(CS_BIT);
// Port D INPUT or LOW
PORTD &= ~(_BV(RST_BIT));
// Port D inputs (none)
// Port D outputs
DDRD |= _BV(RST_BIT) | _BV(CS_BIT) | _BV(DC_BIT);
// Port E INPUT_PULLUP or HIGH
PORTE |= _BV(A_BUTTON_BIT);
// Port E INPUT or LOW (none)
// Port E inputs
DDRE &= ~(_BV(A_BUTTON_BIT));
// Port E outputs (none)
// Port F INPUT_PULLUP or HIGH
PORTF |= _BV(LEFT_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) |
_BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT);
// Port F INPUT or LOW (none)
// Port F inputs
DDRF &= ~(_BV(LEFT_BUTTON_BIT) | _BV(RIGHT_BUTTON_BIT) |
_BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT));
// Port F outputs (none)
#elif defined(AB_DEVKIT)
// Port B INPUT_PULLUP or HIGH
PORTB |= _BV(LEFT_BUTTON_BIT) | _BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT) |
_BV(BLUE_LED_BIT);
// Port B INPUT or LOW (none)
// Port B inputs
DDRB &= ~(_BV(LEFT_BUTTON_BIT) | _BV(UP_BUTTON_BIT) | _BV(DOWN_BUTTON_BIT));
// Port B outputs
DDRB |= _BV(BLUE_LED_BIT) | _BV(SPI_MOSI_BIT) | _BV(SPI_SCK_BIT);
// Port C INPUT_PULLUP or HIGH
PORTE |= _BV(RIGHT_BUTTON_BIT);
// Port C INPUT or LOW (none)
// Port C inputs
DDRE &= ~(_BV(RIGHT_BUTTON_BIT));
// Port C outputs (none)
// Port D INPUT_PULLUP or HIGH
PORTD |= _BV(CS_BIT);
// Port D INPUT or LOW
PORTD &= ~(_BV(RST_BIT));
// Port D inputs (none)
// Port D outputs
DDRD |= _BV(RST_BIT) | _BV(CS_BIT) | _BV(DC_BIT);
// Port E (none)
// Port F INPUT_PULLUP or HIGH
PORTF |= _BV(A_BUTTON_BIT) | _BV(B_BUTTON_BIT);
// Port F INPUT or LOW (none)
// Port F inputs
DDRF &= ~(_BV(A_BUTTON_BIT) | _BV(B_BUTTON_BIT));
// Port F outputs (none)
// Speaker: Not set here. Controlled by audio class
#endif
} }
void Arduboy2Core::bootOLED() void Arduboy2Core::bootOLED()
{ {
// setup the ports we need to talk to the OLED // init SPI
csport = portOutputRegister(digitalPinToPort(CS)); // master, mode 0, MSB first, CPU clock / 2 (8MHz)
cspinmask = digitalPinToBitMask(CS); SPCR = _BV(SPE) | _BV(MSTR);
dcport = portOutputRegister(digitalPinToPort(DC)); SPSR = _BV(SPI2X);
dcpinmask = digitalPinToBitMask(DC);
SPI.setClockDivider(SPI_CLOCK_DIV2); // reset the display
delay(2); // reset pin should be low here. let it stay low a while
bitSet(RST_PORT, RST_BIT); // set high to come out of reset
delay(10); // wait a while
// select the display (permanently, since nothing else is using SPI)
bitClear(CS_PORT, CS_BIT);
LCDCommandMode();
// run our customized boot-up command sequence against the // run our customized boot-up command sequence against the
// OLED to initialize it properly for Arduboy // OLED to initialize it properly for Arduboy
LCDCommandMode();
for (uint8_t i = 0; i < sizeof(lcdBootProgram); i++) { for (uint8_t i = 0; i < sizeof(lcdBootProgram); i++) {
SPI.transfer(pgm_read_byte(lcdBootProgram + i)); SPItransfer(pgm_read_byte(lcdBootProgram + i));
} }
LCDDataMode(); LCDDataMode();
} }
void Arduboy2Core::LCDDataMode() void Arduboy2Core::LCDDataMode()
{ {
*dcport |= dcpinmask; bitSet(DC_PORT, DC_BIT);
*csport &= ~cspinmask;
} }
void Arduboy2Core::LCDCommandMode() void Arduboy2Core::LCDCommandMode()
{ {
*csport |= cspinmask; bitClear(DC_PORT, DC_BIT);
*dcport &= ~dcpinmask;
*csport &= ~cspinmask;
} }
// Write to the SPI bus (MOSI pin)
void Arduboy2Core::SPItransfer(uint8_t data)
{
SPDR = data;
/*
* The following NOP introduces a small delay that can prevent the wait
* loop form iterating when running at the maximum speed. This gives
* about 10% more speed, even if it seems counter-intuitive. At lower
* speeds it is unnoticed.
*/
asm volatile("nop");
while (!(SPSR & _BV(SPIF))) { } // wait
}
void Arduboy2Core::safeMode() void Arduboy2Core::safeMode()
{ {
@ -215,15 +257,11 @@ void Arduboy2Core::idle()
void Arduboy2Core::bootPowerSaving() void Arduboy2Core::bootPowerSaving()
{ {
power_adc_disable(); // disable Two Wire Interface (I2C) and the ADC
power_usart0_disable(); PRR0 = _BV(PRTWI) | _BV(PRADC);
power_twi_disable(); // disable USART1
// timer 0 is for millis() PRR1 = _BV(PRUSART1);
// timers 1 and 3 are for music and sounds // All other bits will be written with 0 so will be enabled
power_timer2_disable();
power_usart1_disable();
// we need USB, for now (to allow triggered reboots to reprogram)
// power_usb_disable()
} }
uint8_t Arduboy2Core::width() { return WIDTH; } uint8_t Arduboy2Core::width() { return WIDTH; }
@ -235,14 +273,14 @@ uint8_t Arduboy2Core::height() { return HEIGHT; }
void Arduboy2Core::paint8Pixels(uint8_t pixels) void Arduboy2Core::paint8Pixels(uint8_t pixels)
{ {
SPI.transfer(pixels); SPItransfer(pixels);
} }
void Arduboy2Core::paintScreen(const uint8_t *image) void Arduboy2Core::paintScreen(const uint8_t *image)
{ {
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++) for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
{ {
SPI.transfer(pgm_read_byte(image + i)); SPItransfer(pgm_read_byte(image + i));
} }
} }
@ -288,13 +326,13 @@ void Arduboy2Core::paintScreen(uint8_t image[], bool clear)
void Arduboy2Core::blank() void Arduboy2Core::blank()
{ {
for (int i = 0; i < (HEIGHT*WIDTH)/8; i++) for (int i = 0; i < (HEIGHT*WIDTH)/8; i++)
SPI.transfer(0x00); SPItransfer(0x00);
} }
void Arduboy2Core::sendLCDCommand(uint8_t command) void Arduboy2Core::sendLCDCommand(uint8_t command)
{ {
LCDCommandMode(); LCDCommandMode();
SPI.transfer(command); SPItransfer(command);
LCDDataMode(); LCDDataMode();
} }
@ -334,19 +372,48 @@ void Arduboy2Core::setRGBled(uint8_t red, uint8_t green, uint8_t blue)
analogWrite(GREEN_LED, 255 - green); analogWrite(GREEN_LED, 255 - green);
analogWrite(BLUE_LED, 255 - blue); analogWrite(BLUE_LED, 255 - blue);
#elif defined(AB_DEVKIT) #elif defined(AB_DEVKIT)
// only blue on devkit // only blue on DevKit, which is not PWM capable
digitalWrite(BLUE_LED, ~blue); (void)red; // parameter unused
(void)green; // parameter unused
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue ? RGB_ON : RGB_OFF);
#endif #endif
} }
void Arduboy2Core::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue) void Arduboy2Core::digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue)
{ {
#ifdef ARDUBOY_10 #ifdef ARDUBOY_10
digitalWrite(RED_LED, red); bitWrite(RED_LED_PORT, RED_LED_BIT, red);
digitalWrite(GREEN_LED, green); bitWrite(GREEN_LED_PORT, GREEN_LED_BIT, green);
digitalWrite(BLUE_LED, blue); bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue);
#elif defined(AB_DEVKIT) #elif defined(AB_DEVKIT)
digitalWrite(BLUE_LED, blue); // only blue on DevKit
(void)red; // parameter unused
(void)green; // parameter unused
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, blue);
#endif
}
void Arduboy2Core::digitalWriteRGB(uint8_t color, uint8_t val)
{
#ifdef ARDUBOY_10
if (color == RED_LED)
{
bitWrite(RED_LED_PORT, RED_LED_BIT, val);
}
else if (color == GREEN_LED)
{
bitWrite(GREEN_LED_PORT, GREEN_LED_BIT, val);
}
else if (color == BLUE_LED)
{
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, val);
}
#elif defined(AB_DEVKIT)
// only blue on DevKit
if (color == BLUE_LED)
{
bitWrite(BLUE_LED_PORT, BLUE_LED_BIT, val);
}
#endif #endif
} }

View File

@ -9,7 +9,6 @@
#include <Arduino.h> #include <Arduino.h>
#include <avr/power.h> #include <avr/power.h>
#include <SPI.h>
#include <avr/sleep.h> #include <avr/sleep.h>
#include <limits.h> #include <limits.h>
@ -41,27 +40,42 @@
#define RGB_ON LOW /**< For digitially setting an RGB LED on using digitalWriteRGB() */ #define RGB_ON LOW /**< For digitially setting an RGB LED on using digitalWriteRGB() */
#define RGB_OFF HIGH /**< For digitially setting an RGB LED off using digitalWriteRGB() */ #define RGB_OFF HIGH /**< For digitially setting an RGB LED off using digitalWriteRGB() */
// ----- Arduboy pins -----
#ifdef ARDUBOY_10 #ifdef ARDUBOY_10
#define CS 12 #define PIN_CS 12 // Display CS Arduino pin number
#define DC 4 #define CS_PORT PORTD // Display CS port
#define RST 6 #define CS_BIT PORTD6 // Display CS physical bit number
#define PIN_DC 4 // Display D/C Arduino pin number
#define DC_PORT PORTD // Display D/C port
#define DC_BIT PORTD4 // Display D/C physical bit number
#define PIN_RST 6 // Display reset Arduino pin number
#define RST_PORT PORTD // Display reset port
#define RST_BIT PORTD7 // Display reset physical bit number
#define SPI_MOSI_PORT PORTB
#define SPI_MOSI_BIT PORTB2
#define SPI_SCK_PORT PORTB
#define SPI_SCK_BIT PORTB1
#define RED_LED 10 /**< The pin number for the red color in the RGB LED. */ #define RED_LED 10 /**< The pin number for the red color in the RGB LED. */
#define GREEN_LED 11 /**< The pin number for the greem color in the RGB LED. */ #define GREEN_LED 11 /**< The pin number for the greem color in the RGB LED. */
#define BLUE_LED 9 /**< The pin number for the blue color in the RGB LED. */ #define BLUE_LED 9 /**< The pin number for the blue color in the RGB LED. */
#define TX_LED 30 /**< The pin number for the transmit indicator LED. */
#define RX_LED 17 /**< The pin number for the receive indicator LED. */
// pin values for buttons, probably shouldn't use these #define RED_LED_PORT PORTB
#define PIN_LEFT_BUTTON A2 #define RED_LED_BIT PORTB6
#define PIN_RIGHT_BUTTON A1
#define PIN_UP_BUTTON A0 #define GREEN_LED_PORT PORTB
#define PIN_DOWN_BUTTON A3 #define GREEN_LED_BIT PORTB7
#define PIN_A_BUTTON 7
#define PIN_B_BUTTON 8 #define BLUE_LED_PORT PORTB
#define BLUE_LED_BIT PORTB5
// bit values for button states // bit values for button states
// these are determined by the buttonsState() function
#define LEFT_BUTTON _BV(5) /**< The Left button value for functions requiring a bitmask */ #define LEFT_BUTTON _BV(5) /**< The Left button value for functions requiring a bitmask */
#define RIGHT_BUTTON _BV(6) /**< The Right button value for functions requiring a bitmask */ #define RIGHT_BUTTON _BV(6) /**< The Right button value for functions requiring a bitmask */
#define UP_BUTTON _BV(7) /**< The Up button value for functions requiring a bitmask */ #define UP_BUTTON _BV(7) /**< The Up button value for functions requiring a bitmask */
@ -69,37 +83,73 @@
#define A_BUTTON _BV(3) /**< The A button value for functions requiring a bitmask */ #define A_BUTTON _BV(3) /**< The A button value for functions requiring a bitmask */
#define B_BUTTON _BV(2) /**< The B button value for functions requiring a bitmask */ #define B_BUTTON _BV(2) /**< The B button value for functions requiring a bitmask */
#define PIN_LEFT_BUTTON A2
#define LEFT_BUTTON_PORT PORTF
#define LEFT_BUTTON_BIT PORTF5
#define PIN_RIGHT_BUTTON A1
#define RIGHT_BUTTON_PORT PORTF
#define RIGHT_BUTTON_BIT PORTF6
#define PIN_UP_BUTTON A0
#define UP_BUTTON_PORT PORTF
#define UP_BUTTON_BIT PORTF7
#define PIN_DOWN_BUTTON A3
#define DOWN_BUTTON_PORT PORTF
#define DOWN_BUTTON_BIT PORTF4
#define PIN_A_BUTTON 7
#define A_BUTTON_PORT PORTE
#define A_BUTTON_BIT PORTE6
#define PIN_B_BUTTON 8
#define B_BUTTON_PORT PORTB
#define B_BUTTON_BIT PORTB4
#define PIN_SPEAKER_1 5 /**< The pin number of the first lead of the speaker */ #define PIN_SPEAKER_1 5 /**< The pin number of the first lead of the speaker */
#define PIN_SPEAKER_2 13 /**< The pin number of the second lead of the speaker */ #define PIN_SPEAKER_2 13 /**< The pin number of the second lead of the speaker */
#define PIN_SPEAKER_1_PORT &PORTC #define SPEAKER_1_PORT PORTC
#define PIN_SPEAKER_2_PORT &PORTC #define SPEAKER_1_DDR DDRC
#define SPEAKER_1_BIT PORTC6
#define PIN_SPEAKER_1_BITMASK _BV(6) #define SPEAKER_2_PORT PORTC
#define PIN_SPEAKER_2_BITMASK _BV(7) #define SPEAKER_2_DDR DDRC
#define SPEAKER_2_BIT PORTC7
// -----------------------
// ----- DevKit pins -----
#elif defined(AB_DEVKIT) #elif defined(AB_DEVKIT)
#define CS 6 #define PIN_CS 6 // Display CS Arduino pin number
#define DC 4 #define CS_PORT PORTD // Display CS port
#define RST 12 #define CS_BIT PORTD7 // Display CS physical bit number
#define PIN_DC 4 // Display D/C Arduino pin number
#define DC_PORT PORTD // Display D/C port
#define DC_BIT PORTD4 // Display D/C physical bit number
#define PIN_RST 12 // Display reset Arduino pin number
#define RST_PORT PORTD // Display reset port
#define RST_BIT PORTD6 // Display reset physical bit number
#define SPI_MOSI_PORT PORTB
#define SPI_MOSI_BIT PORTB2
#define SPI_SCK_PORT PORTB
#define SPI_SCK_BIT PORTB1
// map all LEDs to the single TX LED on DEVKIT // map all LEDs to the single TX LED on DEVKIT
#define RED_LED 17 #define RED_LED 17
#define GREEN_LED 17 #define GREEN_LED 17
#define BLUE_LED 17 #define BLUE_LED 17
#define TX_LED 17
#define RX_LED 17
// pin values for buttons, probably shouldn't use these #define BLUE_LED_PORT PORTB
#define PIN_LEFT_BUTTON 9 #define BLUE_LED_BIT PORTB0
#define PIN_RIGHT_BUTTON 5
#define PIN_UP_BUTTON 8
#define PIN_DOWN_BUTTON 10
#define PIN_A_BUTTON A0
#define PIN_B_BUTTON A1
// bit values for button states // bit values for button states
// these are determined by the buttonsState() function
#define LEFT_BUTTON _BV(5) #define LEFT_BUTTON _BV(5)
#define RIGHT_BUTTON _BV(2) #define RIGHT_BUTTON _BV(2)
#define UP_BUTTON _BV(4) #define UP_BUTTON _BV(4)
@ -107,15 +157,42 @@
#define A_BUTTON _BV(1) #define A_BUTTON _BV(1)
#define B_BUTTON _BV(0) #define B_BUTTON _BV(0)
// pin values for buttons, probably shouldn't use these
#define PIN_LEFT_BUTTON 9
#define LEFT_BUTTON_PORT PORTB
#define LEFT_BUTTON_BIT PORTB5
#define PIN_RIGHT_BUTTON 5
#define RIGHT_BUTTON_PORT PORTC
#define RIGHT_BUTTON_BIT PORTC6
#define PIN_UP_BUTTON 8
#define UP_BUTTON_PORT PORTB
#define UP_BUTTON_BIT PORTB4
#define PIN_DOWN_BUTTON 10
#define DOWN_BUTTON_PORT PORTB
#define DOWN_BUTTON_BIT PORTB6
#define PIN_A_BUTTON A0
#define A_BUTTON_PORT PORTF
#define A_BUTTON_BIT PORTF7
#define PIN_B_BUTTON A1
#define B_BUTTON_PORT PORTF
#define B_BUTTON_BIT PORTF6
#define PIN_SPEAKER_1 A2 #define PIN_SPEAKER_1 A2
#define PIN_SPEAKER_1_PORT &PORTF #define SPEAKER_1_PORT PORTF
#define PIN_SPEAKER_1_BITMASK _BV(5) #define SPEAKER_1_DDR DDRF
#define SPEAKER_1_BIT PORTF5
// SPEAKER_2 is purposely not defined for DEVKIT as it could potentially // SPEAKER_2 is purposely not defined for DEVKIT as it could potentially
// be dangerous and fry your hardware (because of the devkit wiring). // be dangerous and fry your hardware (because of the devkit wiring).
// //
// Reference: https://github.com/Arduboy/Arduboy/issues/108 // Reference: https://github.com/Arduboy/Arduboy/issues/108
#endif #endif
// --------------------
// OLED hardware (SSD1306) // OLED hardware (SSD1306)
@ -183,6 +260,8 @@ class Arduboy2Core
* This is a low level function that is not intended for general use in a * This is a low level function that is not intended for general use in a
* sketch. It has been made public and documented for use by derived * sketch. It has been made public and documented for use by derived
* classes. * classes.
*
* \see LCDCommandMode() SPItransfer()
*/ */
void static LCDDataMode(); void static LCDDataMode();
@ -206,10 +285,25 @@ class Arduboy2Core
* sketch. It has been made public and documented for use by derived * sketch. It has been made public and documented for use by derived
* classes. * classes.
* *
* \see sendLCDCommand() * \see LCDDataMode() sendLCDCommand() SPItransfer()
*/ */
void static LCDCommandMode(); void static LCDCommandMode();
/** \brief
* Transfer a byte to the display.
*
* \param data The byte to be sent to the display.
*
* \details
* Transfer one byte to the display over the SPI port and wait for the
* transfer to complete. The byte will either be interpreted as a command
* or as data to be placed on the screen, depending on the command/data
* mode.
*
* \see LCDDataMode() LCDCommandMode() sendLCDCommand()
*/
void static inline SPItransfer(uint8_t data);
/** \brief /** \brief
* Get the width of the display in pixels. * Get the width of the display in pixels.
* *
@ -233,7 +327,7 @@ class Arduboy2Core
uint8_t static height(); uint8_t static height();
/** \brief /** \brief
* get current state of all buttons as a bitmask. * Get the current state of all buttons as a bitmask.
* *
* \return A bitmask of the state of all the buttons. * \return A bitmask of the state of all the buttons.
* *
@ -461,9 +555,9 @@ class Arduboy2Core
* *
* \details * \details
* The RGB LED is actually individual red, green and blue LEDs placed * The RGB LED is actually individual red, green and blue LEDs placed
* very close together in a single package. This function will set each * very close together in a single package. This 3 parameter version of the
* LED either on or off, to set the RGB LED to 7 different colors at their * function will set each LED either on or off, to set the RGB LED to
* highest brightness or turn it off. * 7 different colors at their highest brightness or turn it off.
* *
* The colors are as follows: * The colors are as follows:
* *
@ -486,10 +580,28 @@ class Arduboy2Core
* light the red LED. If the green LED is turned on, none of the LEDs * light the red LED. If the green LED is turned on, none of the LEDs
* will light. * will light.
* *
* \see setRGBled() * \see digitalWriteRGB(uint8_t, uint8_t) setRGBled()
*/ */
void static digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue); void static digitalWriteRGB(uint8_t red, uint8_t green, uint8_t blue);
/** \brief
* Set one of the RGB LEDs digitally, to either fully on or fully off.
*
* \param color The name of the LED to set. The value given should be one
* of RED_LED, GREEN_LED or BLUE_LED.
*
* \param val Indicates whether to turn the specified LED on or off.
* The value given should be RGB_ON or RGB_OFF.
*
* \details
* This 2 parameter version of the function will set a single LED within
* the RGB LED either fully on or fully off. See the description of the
* 3 parameter version of this function for more details on the RGB LED.
*
* \see digitalWriteRGB(uint8_t, uint8_t, uint8_t) setRGBled()
*/
void static digitalWriteRGB(uint8_t color, uint8_t val);
/** \brief /** \brief
* Initialize the Arduboy's hardware. * Initialize the Arduboy's hardware.
* *
@ -525,12 +637,6 @@ class Arduboy2Core
void static inline bootOLED() __attribute__((always_inline)); void static inline bootOLED() __attribute__((always_inline));
void static inline bootPins() __attribute__((always_inline)); void static inline bootPins() __attribute__((always_inline));
void static inline bootPowerSaving() __attribute__((always_inline)); void static inline bootPowerSaving() __attribute__((always_inline));
private:
volatile static uint8_t *csport, *dcport;
uint8_t static cspinmask, dcpinmask;
}; };
#endif #endif