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 upload
The 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_4MHZ
FREQ_8MHZ
FREQ_12MHZ
FREQ_24MHZ
FREQ_36MHZ
FREQ_48MHZ
PA00
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)); } }