Carbide module reference#include <carbide.h>Makefile :
CARBIDE=true
This module defines helpers to make development on the Carbide board quicker.
You should start your main() function by calling Carbide::init(true) (instead of Core::init()). This will :
PA00, PA01, PA02 and PA04)Error module)true was passed as an argument, the USB port will be initialized with a handler allowing the board to automatically reset into bootloader mode when you type make uploadThe autoBootloaderReset parameter (enabled by passing true to init() as explained above) is a very handy feature allowing you to quickly upload and test each iteration of your program without the need to reset the board manually each time. However, if your program needs to use the USB port, avoid conflict by disabling this feature (remove true) and implementing the handler in your own code (look at the definition of usbControlHandler()).
Here is a simple example that uses the Carbide module to set up the board and flash the LEDs :
#include <carbide.h>
#include <core.h>
int main() {
// Initialize the board
Carbide::init();
// Blink the three LEDs alternatively
while (true) {
// Turn the blue LED off, and the red LED on
Carbide::setLedB(false);
Carbide::setLedR();
Core::sleep(200);
// Red off, green on
Carbide::setLedR(false);
Carbide::setLedG();
Core::sleep(200);
// Green off, blue on
Carbide::setLedG(false);
Carbide::setLedB();
Core::sleep(200);
}
}
true if the button is currently being pressed.true as the second argument).true if the button has been pressed since the last call to this function (you must call this function at regular interval to not miss an input, see the the Polling paragraph in the GPIO module reference for more information).true if the button has been released since the last call to this function (you must call this function at regular interval to not miss an input, see the the Polling paragraph in the GPIO module reference for more information).FREQ_4MHZFREQ_8MHZFREQ_12MHZFREQ_24MHZFREQ_36MHZFREQ_48MHZPA00 pin on which the red LED is connected. This is called in init().PA01 pin on which the green LED is connected. This is called in init().PA02 pin on which the blue LED is connected. This is called in init().PA04 pin on which the button is connected. This is called in init().
#ifndef _CARBIDE_H_
#define _CARBIDE_H_
#include <gpio.h>
#if PACKAGE != 64
#warning "You are compiling for the Carbide with an incorrect package, please set PACKAGE=64 in your Makefile"
#endif
namespace Carbide {
// Pins definition
const GPIO::Pin PIN_LED_R = GPIO::PA00;
const GPIO::Pin PIN_LED_G = GPIO::PA01;
const GPIO::Pin PIN_LED_B = GPIO::PA02;
const GPIO::Pin PIN_BUTTON = GPIO::PA04;
// Predefined CPU frequencies
enum class CPUFreq {
FREQ_4MHZ,
FREQ_8MHZ,
FREQ_12MHZ,
FREQ_24MHZ,
FREQ_36MHZ,
FREQ_48MHZ
};
// Helper functions
void init(bool autoBootloaderReset=false);
void setCPUFrequency(CPUFreq frequency);
void warningHandler(Error::Module module, int userModule, Error::Code code);
void criticalHandler(Error::Module module, int userModule, Error::Code code);
inline void initLedR() { GPIO::enableOutput(PIN_LED_R, GPIO::HIGH); }
inline void setLedR(bool on=true) { GPIO::set(PIN_LED_R, !on); } // Inverted : pin must be LOW to turn the LED on
inline void initLedG() { GPIO::enableOutput(PIN_LED_G, GPIO::HIGH); }
inline void setLedG(bool on=true) { GPIO::set(PIN_LED_G, !on); }
inline void initLedB() { GPIO::enableOutput(PIN_LED_B, GPIO::HIGH); }
inline void setLedB(bool on=true) { GPIO::set(PIN_LED_B, !on); }
inline void initLeds() { initLedR(); initLedG(); initLedB(); }
inline void initButton() { GPIO::enableInput(PIN_BUTTON, GPIO::Pulling::PULLUP); }
inline bool isButtonPressed() { return !GPIO::get(PIN_BUTTON); } // Inverted : the pin is LOW when the button is pressed (pullup)
void onButtonPressed(void (*handler)(), bool released=false);
inline bool buttonRisingEdge() { return GPIO::fallingEdge(PIN_BUTTON); } // Rising/falling are also inverted for the same reasons
inline bool buttonFallingEdge() { return GPIO::risingEdge(PIN_BUTTON); }
inline void waitButtonPressed() { while (!buttonRisingEdge()); }
}
#endif
#include "carbide.h"
#include <core.h>
#include <error.h>
#include <scif.h>
#include <pm.h>
#include <bpm.h>
#include <gpio.h>
#include <usb.h>
namespace Carbide {
// USB request codes
enum class Request {
START_BOOTLOADER,
CONNECT,
STATUS,
WRITE,
GET_ERROR,
};
// Handler called when a CONTROL packet is sent over USB
int usbControlHandler(USB::SetupPacket &lastSetupPacket, uint8_t* data, int size) {
Request request = static_cast<Request>(lastSetupPacket.bRequest);
if (request == Request::START_BOOTLOADER) {
lastSetupPacket.handled = true;
Core::resetToBootloader(10);
}
return 0;
}
// Handler called when an error of Warning level is triggered
void warningHandler(Error::Module module, int userModule, Error::Code code) {
// Blink the red LED three times and resume operation
setLedR(false);
Core::sleep(100);
setLedR();
Core::sleep(100);
setLedR(false);
Core::sleep(100);
setLedR();
Core::sleep(100);
setLedR(false);
Core::sleep(100);
}
// Handler called when an error of Critical level is triggered
void criticalHandler(Error::Module module, int userModule, Error::Code code) {
// Stop the execution and blink the red LED rapidly
while (1) {
setLedR();
Core::sleep(100);
setLedR(false);
Core::sleep(100);
}
}
void init(bool autoBootloaderReset) {
// Init the microcontroller on the default 12MHz clock
Core::init();
setCPUFrequency(CPUFreq::FREQ_12MHZ);
if (autoBootloaderReset) {
// Init the USB port start the bootloader when requested
USB::initDevice();
USB::setControlHandler(usbControlHandler);
}
// Init the leds and button
initLeds();
initButton();
// Set error handlers
Error::setHandler(Error::Severity::WARNING, warningHandler);
Error::setHandler(Error::Severity::CRITICAL, criticalHandler);
}
void setCPUFrequency(CPUFreq frequency) {
switch (frequency) {
case CPUFreq::FREQ_4MHZ:
SCIF::enableRCFAST(SCIF::RCFASTFrequency::RCFAST_4MHZ);
PM::setMainClockSource(PM::MainClockSource::RCFAST);
break;
case CPUFreq::FREQ_8MHZ:
SCIF::enableRCFAST(SCIF::RCFASTFrequency::RCFAST_8MHZ);
PM::setMainClockSource(PM::MainClockSource::RCFAST);
break;
case CPUFreq::FREQ_12MHZ:
SCIF::enableRCFAST(SCIF::RCFASTFrequency::RCFAST_12MHZ);
PM::setMainClockSource(PM::MainClockSource::RCFAST);
break;
case CPUFreq::FREQ_24MHZ:
SCIF::enableDFLL(24000000UL);
PM::setMainClockSource(PM::MainClockSource::DFLL);
break;
case CPUFreq::FREQ_36MHZ:
BPM::setPowerScaling(BPM::PowerScaling::PS2);
SCIF::enableDFLL(36000000UL);
PM::setMainClockSource(PM::MainClockSource::DFLL);
break;
case CPUFreq::FREQ_48MHZ:
BPM::setPowerScaling(BPM::PowerScaling::PS2);
SCIF::enableDFLL(48000000UL);
PM::setMainClockSource(PM::MainClockSource::DFLL);
break;
}
// Wait 100ms to make sure the clocks have stabilized
Core::sleep(100);
}
// Enable an handler to be called by interrupt when the button the button is
// either pressed or realeased
void onButtonPressed(void (*handler)(), bool released) {
GPIO::enableInterrupt(PIN_BUTTON, handler, (released ? GPIO::Trigger::RISING : GPIO::Trigger::FALLING));
}
}