Start work on dedicated sd card formatter program
This commit is contained in:
parent
4639aa70ab
commit
3fefcf7e34
5
hardware/sd_card_formatter/.gitignore
vendored
Normal file
5
hardware/sd_card_formatter/.gitignore
vendored
Normal file
|
@ -0,0 +1,5 @@
|
|||
build/
|
||||
sd_card_formatter*.bak
|
||||
gui_backup/
|
||||
sd_card_formatter.ino.beta
|
||||
sd_card_formatter.ino.orig
|
7
hardware/sd_card_formatter/README.md
Normal file
7
hardware/sd_card_formatter/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
# SD Card Formatter
|
||||
|
||||
A simple utility that will **FORMAT** the inserted SD Card.
|
||||
|
||||
**YOU MUST USE THIS TOOL TO INITIALIZE AN SD CARD 100% SAFELY**
|
||||
|
||||
*This utility is designed to be run from the ```_controller``` build!*
|
1
hardware/sd_card_formatter/build.ps1
Normal file
1
hardware/sd_card_formatter/build.ps1
Normal file
|
@ -0,0 +1 @@
|
|||
arduino-cli compile --log-level=warn --fqbn adafruit:nrf52:feather52840 sd_card_formatter.ino
|
8
hardware/sd_card_formatter/make.ps1
Normal file
8
hardware/sd_card_formatter/make.ps1
Normal file
|
@ -0,0 +1,8 @@
|
|||
# Ensure this script fails if either build or upload fails
|
||||
$ErrorActionPreference = "Stop"
|
||||
|
||||
# Ensure we actually build before upload (common mistake)
|
||||
& .\build.ps1
|
||||
|
||||
# Upload to board
|
||||
& .\upload.ps1
|
804
hardware/sd_card_formatter/sd_card_formatter.ino
Normal file
804
hardware/sd_card_formatter/sd_card_formatter.ino
Normal file
|
@ -0,0 +1,804 @@
|
|||
//<App !Start!>
|
||||
// FILE: [sd_card_formatter.ino]
|
||||
// Created by GUIslice Builder version: [0.15.b004]
|
||||
//
|
||||
// GUIslice Builder Generated File
|
||||
//
|
||||
// For the latest guides, updates and support view:
|
||||
// https://github.com/ImpulseAdventure/GUIslice
|
||||
//
|
||||
//<App !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Headers to include
|
||||
// ------------------------------------------------
|
||||
//<Includes !Start!>
|
||||
// Varous system includes
|
||||
#include <Arduino.h>
|
||||
|
||||
// Various library includes
|
||||
#include <Adafruit_NeoPixel.h>
|
||||
#include <Adafruit_GFX.h>
|
||||
#include <Adafruit_ILI9341.h>
|
||||
#include <BBQ10Keyboard.h>
|
||||
#include <CircularBuffer.h>
|
||||
|
||||
// Various local includes
|
||||
#include "sd_card_formatter_GSLC.h"
|
||||
|
||||
//<Includes !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Program Globals
|
||||
// ------------------------------------------------
|
||||
|
||||
// Battery level measurement
|
||||
#define VBATPIN A6
|
||||
float measuredVBat;
|
||||
int batteryPercent;
|
||||
|
||||
// TFT Setup
|
||||
#define TFT_CS 9
|
||||
#define TFT_DC 10
|
||||
Adafruit_ILI9341 tft(TFT_CS, TFT_DC);
|
||||
|
||||
// Keyboard
|
||||
BBQ10Keyboard keyboard;
|
||||
#define KBD_BTN_1 0x06
|
||||
#define KBD_BTN_2 0x11
|
||||
#define KBD_BTN_3 0x07
|
||||
#define KBD_BTN_4 0x12
|
||||
#define KBD_SW_UP 0x01
|
||||
#define KBD_SW_DN 0x02
|
||||
#define KBD_SW_LF 0x03
|
||||
#define KBD_SW_RT 0x04
|
||||
#define KBD_SW_OK 0x05
|
||||
CircularBuffer<int16_t,8> uiKeyBuffer;
|
||||
|
||||
// NeoPixels
|
||||
#define PIXELS_NUM_BOARD 1
|
||||
#define PIXELS_NUM_WING 1
|
||||
#define PIXELS_WING_PIN 11
|
||||
Adafruit_NeoPixel pixels_board(PIXELS_NUM_BOARD, PIN_NEOPIXEL, NEO_GRB + NEO_KHZ800);
|
||||
Adafruit_NeoPixel pixels_wing(PIXELS_NUM_WING, PIXELS_WING_PIN, NEO_GRB + NEO_KHZ800);
|
||||
|
||||
// GUI state globals
|
||||
bool popupOnScreen = false;
|
||||
|
||||
// Various loop handlers
|
||||
void handlerKeyboard();
|
||||
void handlerBatteryLevel();
|
||||
void eraseAndFormatCard();
|
||||
|
||||
// Save some element references for direct access
|
||||
//<Save_References !Start!>
|
||||
gslc_tsElemRef* m_pElemBatteryLevel= NULL;
|
||||
gslc_tsElemRef* m_pElemBtSDNo = NULL;
|
||||
gslc_tsElemRef* m_pElemBtSDYes = NULL;
|
||||
gslc_tsElemRef* m_pElemSDInfo = NULL;
|
||||
gslc_tsElemRef* m_pElemStatusText = NULL;
|
||||
//<Save_References !End!>
|
||||
|
||||
// Keyboard map related
|
||||
#define MAX_INPUT_MAP 5
|
||||
gslc_tsInputMap m_asInputMap[MAX_INPUT_MAP];
|
||||
|
||||
// Define debug message function
|
||||
static int16_t DebugOut(char ch) { if (ch == (char)'\n') Serial.println(""); else Serial.write(ch); return 0; }
|
||||
|
||||
// ------------------------------------------------
|
||||
// Callback Methods
|
||||
// ------------------------------------------------
|
||||
// Common Button callback
|
||||
bool CbBtnCommon(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY)
|
||||
{
|
||||
// Typecast the parameters to match the GUI and element types
|
||||
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||||
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
|
||||
if ( eTouch == GSLC_TOUCH_UP_IN ) {
|
||||
// From the element's ID we can determine which button was pressed.
|
||||
switch (pElem->nId) {
|
||||
//<Button Enums !Start!>
|
||||
case E_ELEM_BTN_SD_FMT:
|
||||
gslc_PopupShow(&m_gui, E_PG_SD_CONFIRM, false);
|
||||
popupOnScreen = true;
|
||||
break;
|
||||
case E_ELEM_SD_NO:
|
||||
gslc_PopupHide(&m_gui);
|
||||
popupOnScreen = false;
|
||||
break;
|
||||
case E_ELEM_SD_YES:
|
||||
gslc_PopupHide(&m_gui);
|
||||
popupOnScreen = false;
|
||||
gslc_ElemXTextboxReset(&m_gui, m_pElemSDInfo);
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Formatting SD Card\n");
|
||||
gslc_Update(&m_gui);
|
||||
eraseAndFormatCard();
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Formatting Complete\n");
|
||||
gslc_Update(&m_gui);
|
||||
break;
|
||||
//<Button Enums !End!>
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//<Checkbox Callback !Start!>
|
||||
//<Checkbox Callback !End!>
|
||||
//<Keypad Callback !Start!>
|
||||
//<Keypad Callback !End!>
|
||||
//<Spinner Callback !Start!>
|
||||
//<Spinner Callback !End!>
|
||||
//<Listbox Callback !Start!>
|
||||
//<Listbox Callback !End!>
|
||||
//<Draw Callback !Start!>
|
||||
//<Draw Callback !End!>
|
||||
//<Slider Enums !Start!>
|
||||
//<Slider Enums !End!>
|
||||
//<Tick Callback !Start!>
|
||||
//<Tick Callback !End!>
|
||||
|
||||
// Keyboard Input polling callback function
|
||||
bool CbKbdPoll(void* pvGui, int16_t* pnPinInd, int16_t* pnPinVal) {
|
||||
// Check for new keyboard events just in case
|
||||
handlerKeyboard();
|
||||
|
||||
// If the key buffer is empty no events to process
|
||||
if (uiKeyBuffer.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Process a key that's on the key buffer for the UI event(s)
|
||||
*pnPinInd = uiKeyBuffer.pop();
|
||||
*pnPinVal = 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Setup
|
||||
// ------------------------------------------------
|
||||
void setup() {
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
// If GUI Slice debug of drivers is turned on, wait for serial so we get proper debug output
|
||||
#if defined(DBG_LOG) || defined(DBG_TOUCH) || defined(DBG_FRAME_RATE) || defined(DBG_DRAW_IMM) || defined(DBG_DRIVER)
|
||||
while (!Serial) {
|
||||
;
|
||||
}
|
||||
#endif
|
||||
|
||||
// GUI Slice debugging
|
||||
gslc_InitDebug(&DebugOut);
|
||||
|
||||
// Setup red LED to indicate device is on (in case we disable NeoPixel battery level later)
|
||||
pinMode(3, OUTPUT);
|
||||
digitalWrite(3, HIGH);
|
||||
|
||||
// Setup NeoPixels
|
||||
pixels_board.begin();
|
||||
pixels_wing.begin();
|
||||
pixels_board.clear();
|
||||
pixels_wing.clear();
|
||||
pixels_board.setBrightness(10);
|
||||
pixels_wing.setBrightness(5);
|
||||
|
||||
// Setup neopixels to indicate we are initializing gui slice
|
||||
// This can serve as an indication something has gone wrong like the sd card is missing
|
||||
pixels_wing.setPixelColor(0, pixels_board.Color(255, 0, 0));
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(255, 0, 0));
|
||||
pixels_wing.show();
|
||||
pixels_board.show();
|
||||
|
||||
// Setup BBQ10Keyboard
|
||||
Wire.begin();
|
||||
keyboard.begin();
|
||||
keyboard.setBacklight(0.5f);
|
||||
|
||||
// Init GUI Slicle
|
||||
InitGUIslice_gen();
|
||||
|
||||
// Set the pin poll callback function
|
||||
gslc_SetPinPollFunc(&m_gui, CbKbdPoll);
|
||||
|
||||
// Create the GUI input mapping (pin event to GUI action)
|
||||
gslc_InitInputMap(&m_gui, m_asInputMap, MAX_INPUT_MAP);
|
||||
gslc_InputMapAdd(&m_gui, GSLC_INPUT_PIN_ASSERT, KBD_SW_UP, GSLC_ACTION_FOCUS_NEXT, 0);
|
||||
gslc_InputMapAdd(&m_gui, GSLC_INPUT_PIN_ASSERT, KBD_SW_DN, GSLC_ACTION_FOCUS_PREV, 0);
|
||||
gslc_InputMapAdd(&m_gui, GSLC_INPUT_PIN_ASSERT, KBD_SW_LF, GSLC_ACTION_FOCUS_NEXT, 0);
|
||||
gslc_InputMapAdd(&m_gui, GSLC_INPUT_PIN_ASSERT, KBD_SW_RT, GSLC_ACTION_FOCUS_PREV, 0);
|
||||
gslc_InputMapAdd(&m_gui, GSLC_INPUT_PIN_ASSERT, KBD_SW_OK, GSLC_ACTION_SELECT, 0);
|
||||
|
||||
// Flip to main screen
|
||||
// This wouldn't be necessary if we hadn't chopped off the formatter from the main _controller project and actually updated the main screen ;)
|
||||
gslc_SetPageCur(&m_gui, E_SD_CARD);
|
||||
|
||||
// Set neopixels to standard start state
|
||||
pixels_wing.clear();
|
||||
pixels_wing.show();
|
||||
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(0, 0, 255));
|
||||
pixels_board.show();
|
||||
}
|
||||
|
||||
// -----------------------------------
|
||||
// Main event loop
|
||||
// -----------------------------------
|
||||
void loop() {
|
||||
// Handle keyboard events
|
||||
handlerKeyboard();
|
||||
|
||||
// Update battery level as appropriate
|
||||
handlerBatteryLevel();
|
||||
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Keyboard Handler
|
||||
// ------------------------------------------------
|
||||
void handlerKeyboard() {
|
||||
// Don't do anything if there are no key presses to process
|
||||
if (keyboard.keyCount() == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if keys were pressed and drain queue of pressed keys
|
||||
while (keyboard.keyCount() > 0) {
|
||||
// Get keyboard event
|
||||
const BBQ10Keyboard::KeyEvent key = keyboard.keyEvent();
|
||||
|
||||
// Process key press events
|
||||
if (key.state == BBQ10Keyboard::StatePress) {
|
||||
// Add keys to the key buffer that are mapped to UI functions (only for config screens)
|
||||
if (key.key == KBD_SW_UP
|
||||
|| key.key == KBD_SW_DN
|
||||
|| key.key == KBD_SW_LF
|
||||
|| key.key == KBD_SW_RT
|
||||
|| key.key == KBD_SW_OK) {
|
||||
uiKeyBuffer.push(key.key);
|
||||
}
|
||||
}
|
||||
|
||||
// Pick color for signaling a key was pressed (short or long press)
|
||||
uint32_t keyboard_pixel_color = pixels_wing.Color(0, 0, 255);
|
||||
if (key.state == BBQ10Keyboard::StateLongPress) {
|
||||
keyboard_pixel_color = pixels_wing.Color(0, 255, 255);
|
||||
}
|
||||
|
||||
// Display indicator accordingly
|
||||
if (key.state == BBQ10Keyboard::StatePress || key.state == BBQ10Keyboard::StateLongPress) {
|
||||
pixels_wing.setPixelColor(0, keyboard_pixel_color);
|
||||
pixels_wing.show();
|
||||
}
|
||||
else {
|
||||
pixels_wing.clear();
|
||||
pixels_wing.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Battery level handler
|
||||
// ------------------------------------------------
|
||||
void handlerBatteryLevel() {
|
||||
measuredVBat = analogRead(VBATPIN);
|
||||
measuredVBat *= 2; // we divided by 2, so multiply back
|
||||
measuredVBat *= 3.3; // Multiply by 3.3V, our reference voltage
|
||||
measuredVBat /= 1024; // convert to voltage
|
||||
batteryPercent = (measuredVBat / 3.3) * 100;
|
||||
|
||||
gslc_tsColor colorForHeaderElements;
|
||||
if (batteryPercent >= 75) {
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(0, 255, 0));
|
||||
colorForHeaderElements = GSLC_COL_GREEN;
|
||||
}
|
||||
else if (batteryPercent >= 50) {
|
||||
colorForHeaderElements = GSLC_COL_YELLOW;
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(255, 255, 0));
|
||||
}
|
||||
else if (batteryPercent >= 25) {
|
||||
colorForHeaderElements = GSLC_COL_ORANGE;
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(255, 128, 0));
|
||||
}
|
||||
else {
|
||||
colorForHeaderElements = GSLC_COL_RED;
|
||||
pixels_board.setPixelColor(0, pixels_board.Color(255, 0, 0));
|
||||
}
|
||||
|
||||
gslc_ElemXProgressSetVal(&m_gui, m_pElemBatteryLevel, batteryPercent);
|
||||
gslc_tsXProgress* pGauge = (gslc_tsXProgress*)gslc_GetXDataFromRef(&m_gui,m_pElemBatteryLevel,GSLC_TYPEX_PROGRESS,__LINE__);
|
||||
pGauge->colGauge = colorForHeaderElements;
|
||||
gslc_ElemSetTxtCol(&m_gui, m_pElemStatusText, colorForHeaderElements);
|
||||
|
||||
// Update GUI and NeoPixel with battery status information
|
||||
pixels_board.show();
|
||||
}
|
||||
|
||||
// ------------------------------------------------
|
||||
// Format SD Card
|
||||
// ------------------------------------------------
|
||||
/*
|
||||
* This program will format an SD or SDHC card.
|
||||
* Warning all data will be deleted!
|
||||
*
|
||||
* For SD/SDHC cards larger than 64 MB this
|
||||
* program attempts to match the format
|
||||
* generated by SDFormatter available here:
|
||||
*
|
||||
* http://www.sdcard.org/consumers/formatter/
|
||||
*
|
||||
* For smaller cards this program uses FAT16
|
||||
* and SDFormatter uses FAT12.
|
||||
*/
|
||||
|
||||
// Set USE_SDIO to zero for SPI card access.
|
||||
#define USE_SDIO 0
|
||||
//
|
||||
// Change the value of chipSelect if your hardware does
|
||||
// not use the default value, SS. Common values are:
|
||||
// Arduino Ethernet shield: pin 4
|
||||
// Sparkfun SD shield: pin 8
|
||||
// Adafruit SD shields and modules: pin 10
|
||||
const uint8_t chipSelect = 5;
|
||||
|
||||
// Initialize at highest supported speed not over 50 MHz.
|
||||
// Reduce max speed if errors occur.
|
||||
#define SPI_SPEED SD_SCK_MHZ(50)
|
||||
|
||||
// Print extra info for debug if DEBUG_PRINT is nonzero
|
||||
#include <SPI.h>
|
||||
#include "src/SdFat/SdFat.h"
|
||||
#include "src/SdFat/sdios.h"
|
||||
|
||||
#if USE_SDIO
|
||||
// Use faster SdioCardEX
|
||||
SdioCardEX card;
|
||||
// SdioCard card;
|
||||
#else // USE_SDIO
|
||||
Sd2Card card;
|
||||
#endif // USE_SDIO
|
||||
|
||||
uint32_t cardSizeBlocks;
|
||||
uint32_t cardCapacityMB;
|
||||
|
||||
// cache for SD block
|
||||
cache_t cache;
|
||||
|
||||
// MBR information
|
||||
uint8_t partType;
|
||||
uint32_t relSector;
|
||||
uint32_t partSize;
|
||||
|
||||
// Fake disk geometry
|
||||
uint8_t numberOfHeads;
|
||||
uint8_t sectorsPerTrack;
|
||||
|
||||
// FAT parameters
|
||||
uint16_t reservedSectors;
|
||||
uint8_t sectorsPerCluster;
|
||||
uint32_t fatStart;
|
||||
uint32_t fatSize;
|
||||
uint32_t dataStart;
|
||||
|
||||
// constants for file system structure
|
||||
uint16_t const BU16 = 128;
|
||||
uint16_t const BU32 = 8192;
|
||||
|
||||
// strings needed in file system structures
|
||||
char noName[] = "NO NAME ";
|
||||
char fat16str[] = "FAT16 ";
|
||||
char fat32str[] = "FAT32 ";
|
||||
//------------------------------------------------------------------------------
|
||||
void sdError(char* msg) {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "error: ");
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, msg);
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "\n");
|
||||
gslc_Update(&m_gui);
|
||||
|
||||
sdErrorHalt();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void sdErrorHalt() {
|
||||
if (card.errorCode()) {
|
||||
char textForDisplay[32];
|
||||
snprintf(textForDisplay, 32, "SD error: %d\n", int(card.errorCode()));
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, textForDisplay);
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
SysCall::halt();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// write cached block to the card
|
||||
uint8_t writeCache(uint32_t lbn) {
|
||||
return card.writeBlock(lbn, cache.data);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// initialize appropriate sizes for SD capacity
|
||||
void initSizes() {
|
||||
if (cardCapacityMB <= 6) {
|
||||
sdError("Card is too small.");
|
||||
} else if (cardCapacityMB <= 16) {
|
||||
sectorsPerCluster = 2;
|
||||
} else if (cardCapacityMB <= 32) {
|
||||
sectorsPerCluster = 4;
|
||||
} else if (cardCapacityMB <= 64) {
|
||||
sectorsPerCluster = 8;
|
||||
} else if (cardCapacityMB <= 128) {
|
||||
sectorsPerCluster = 16;
|
||||
} else if (cardCapacityMB <= 1024) {
|
||||
sectorsPerCluster = 32;
|
||||
} else if (cardCapacityMB <= 32768) {
|
||||
sectorsPerCluster = 64;
|
||||
} else {
|
||||
// SDXC cards
|
||||
sectorsPerCluster = 128;
|
||||
}
|
||||
|
||||
char textForDisplay[64];
|
||||
snprintf(textForDisplay, 64, "Blocks/Cluster: %d\n", int(sectorsPerCluster));
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, textForDisplay);
|
||||
gslc_Update(&m_gui);
|
||||
|
||||
// set fake disk geometry
|
||||
sectorsPerTrack = cardCapacityMB <= 256 ? 32 : 63;
|
||||
|
||||
if (cardCapacityMB <= 16) {
|
||||
numberOfHeads = 2;
|
||||
} else if (cardCapacityMB <= 32) {
|
||||
numberOfHeads = 4;
|
||||
} else if (cardCapacityMB <= 128) {
|
||||
numberOfHeads = 8;
|
||||
} else if (cardCapacityMB <= 504) {
|
||||
numberOfHeads = 16;
|
||||
} else if (cardCapacityMB <= 1008) {
|
||||
numberOfHeads = 32;
|
||||
} else if (cardCapacityMB <= 2016) {
|
||||
numberOfHeads = 64;
|
||||
} else if (cardCapacityMB <= 4032) {
|
||||
numberOfHeads = 128;
|
||||
} else {
|
||||
numberOfHeads = 255;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// zero cache and optionally set the sector signature
|
||||
void clearCache(uint8_t addSig) {
|
||||
memset(&cache, 0, sizeof(cache));
|
||||
if (addSig) {
|
||||
cache.mbr.mbrSig0 = BOOTSIG0;
|
||||
cache.mbr.mbrSig1 = BOOTSIG1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// zero FAT and root dir area on SD
|
||||
void clearFatDir(uint32_t bgn, uint32_t count) {
|
||||
clearCache(false);
|
||||
#if USE_SDIO
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if (!card.writeBlock(bgn + i, cache.data)) {
|
||||
sdError("Clear FAT/DIR writeBlock failed");
|
||||
}
|
||||
if ((i & 0XFF) == 0) {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, ".");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
}
|
||||
#else // USE_SDIO
|
||||
if (!card.writeStart(bgn, count)) {
|
||||
sdError("Clear FAT/DIR writeStart failed");
|
||||
}
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if ((i & 0XFF) == 0) {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, ".");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
if (!card.writeData(cache.data)) {
|
||||
sdError("Clear FAT/DIR writeData failed");
|
||||
}
|
||||
}
|
||||
if (!card.writeStop()) {
|
||||
sdError("Clear FAT/DIR writeStop failed");
|
||||
}
|
||||
#endif // USE_SDIO
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "\n");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return cylinder number for a logical block number
|
||||
uint16_t lbnToCylinder(uint32_t lbn) {
|
||||
return lbn / (numberOfHeads * sectorsPerTrack);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return head number for a logical block number
|
||||
uint8_t lbnToHead(uint32_t lbn) {
|
||||
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return sector number for a logical block number
|
||||
uint8_t lbnToSector(uint32_t lbn) {
|
||||
return (lbn % sectorsPerTrack) + 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// format and write the Master Boot Record
|
||||
void writeMbr() {
|
||||
clearCache(true);
|
||||
part_t* p = cache.mbr.part;
|
||||
p->boot = 0;
|
||||
uint16_t c = lbnToCylinder(relSector);
|
||||
if (c > 1023) {
|
||||
sdError("MBR CHS");
|
||||
}
|
||||
p->beginCylinderHigh = c >> 8;
|
||||
p->beginCylinderLow = c & 0XFF;
|
||||
p->beginHead = lbnToHead(relSector);
|
||||
p->beginSector = lbnToSector(relSector);
|
||||
p->type = partType;
|
||||
uint32_t endLbn = relSector + partSize - 1;
|
||||
c = lbnToCylinder(endLbn);
|
||||
if (c <= 1023) {
|
||||
p->endCylinderHigh = c >> 8;
|
||||
p->endCylinderLow = c & 0XFF;
|
||||
p->endHead = lbnToHead(endLbn);
|
||||
p->endSector = lbnToSector(endLbn);
|
||||
} else {
|
||||
// Too big flag, c = 1023, h = 254, s = 63
|
||||
p->endCylinderHigh = 3;
|
||||
p->endCylinderLow = 255;
|
||||
p->endHead = 254;
|
||||
p->endSector = 63;
|
||||
}
|
||||
p->firstSector = relSector;
|
||||
p->totalSectors = partSize;
|
||||
if (!writeCache(0)) {
|
||||
sdError("write MBR");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// generate serial number from card size and micros since boot
|
||||
uint32_t volSerialNumber() {
|
||||
return (cardSizeBlocks << 8) + micros();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// format the SD as FAT16
|
||||
void makeFat16() {
|
||||
uint32_t nc;
|
||||
for (dataStart = 2 * BU16;; dataStart += BU16) {
|
||||
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||
fatSize = (nc + 2 + 255)/256;
|
||||
uint32_t r = BU16 + 1 + 2 * fatSize + 32;
|
||||
if (dataStart < r) {
|
||||
continue;
|
||||
}
|
||||
relSector = dataStart - r + BU16;
|
||||
break;
|
||||
}
|
||||
// check valid cluster count for FAT16 volume
|
||||
if (nc < 4085 || nc >= 65525) {
|
||||
sdError("Bad cluster count");
|
||||
}
|
||||
reservedSectors = 1;
|
||||
fatStart = relSector + reservedSectors;
|
||||
partSize = nc * sectorsPerCluster + 2 * fatSize + reservedSectors + 32;
|
||||
if (partSize < 32680) {
|
||||
partType = 0X01;
|
||||
} else if (partSize < 65536) {
|
||||
partType = 0X04;
|
||||
} else {
|
||||
partType = 0X06;
|
||||
}
|
||||
// write MBR
|
||||
writeMbr();
|
||||
clearCache(true);
|
||||
fat_boot_t* pb = &cache.fbs;
|
||||
pb->jump[0] = 0XEB;
|
||||
pb->jump[1] = 0X00;
|
||||
pb->jump[2] = 0X90;
|
||||
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||
pb->oemId[i] = ' ';
|
||||
}
|
||||
pb->bytesPerSector = 512;
|
||||
pb->sectorsPerCluster = sectorsPerCluster;
|
||||
pb->reservedSectorCount = reservedSectors;
|
||||
pb->fatCount = 2;
|
||||
pb->rootDirEntryCount = 512;
|
||||
pb->mediaType = 0XF8;
|
||||
pb->sectorsPerFat16 = fatSize;
|
||||
pb->sectorsPerTrack = sectorsPerTrack;
|
||||
pb->headCount = numberOfHeads;
|
||||
pb->hidddenSectors = relSector;
|
||||
pb->totalSectors32 = partSize;
|
||||
pb->driveNumber = 0X80;
|
||||
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||
pb->volumeSerialNumber = volSerialNumber();
|
||||
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||
memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
|
||||
// write partition boot sector
|
||||
if (!writeCache(relSector)) {
|
||||
sdError("FAT16 write PBS failed");
|
||||
}
|
||||
// clear FAT and root directory
|
||||
clearFatDir(fatStart, dataStart - fatStart);
|
||||
clearCache(false);
|
||||
cache.fat16[0] = 0XFFF8;
|
||||
cache.fat16[1] = 0XFFFF;
|
||||
// write first block of FAT and backup for reserved clusters
|
||||
if (!writeCache(fatStart)
|
||||
|| !writeCache(fatStart + fatSize)) {
|
||||
sdError("FAT16 reserve failed");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// format the SD as FAT32
|
||||
void makeFat32() {
|
||||
uint32_t nc;
|
||||
relSector = BU32;
|
||||
for (dataStart = 2 * BU32;; dataStart += BU32) {
|
||||
nc = (cardSizeBlocks - dataStart)/sectorsPerCluster;
|
||||
fatSize = (nc + 2 + 127)/128;
|
||||
uint32_t r = relSector + 9 + 2 * fatSize;
|
||||
if (dataStart >= r) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
// error if too few clusters in FAT32 volume
|
||||
if (nc < 65525) {
|
||||
sdError("Bad cluster count");
|
||||
}
|
||||
reservedSectors = dataStart - relSector - 2 * fatSize;
|
||||
fatStart = relSector + reservedSectors;
|
||||
partSize = nc * sectorsPerCluster + dataStart - relSector;
|
||||
// type depends on address of end sector
|
||||
// max CHS has lbn = 16450560 = 1024*255*63
|
||||
if ((relSector + partSize) <= 16450560) {
|
||||
// FAT32
|
||||
partType = 0X0B;
|
||||
} else {
|
||||
// FAT32 with INT 13
|
||||
partType = 0X0C;
|
||||
}
|
||||
writeMbr();
|
||||
clearCache(true);
|
||||
|
||||
fat32_boot_t* pb = &cache.fbs32;
|
||||
pb->jump[0] = 0XEB;
|
||||
pb->jump[1] = 0X00;
|
||||
pb->jump[2] = 0X90;
|
||||
for (uint8_t i = 0; i < sizeof(pb->oemId); i++) {
|
||||
pb->oemId[i] = ' ';
|
||||
}
|
||||
pb->bytesPerSector = 512;
|
||||
pb->sectorsPerCluster = sectorsPerCluster;
|
||||
pb->reservedSectorCount = reservedSectors;
|
||||
pb->fatCount = 2;
|
||||
pb->mediaType = 0XF8;
|
||||
pb->sectorsPerTrack = sectorsPerTrack;
|
||||
pb->headCount = numberOfHeads;
|
||||
pb->hidddenSectors = relSector;
|
||||
pb->totalSectors32 = partSize;
|
||||
pb->sectorsPerFat32 = fatSize;
|
||||
pb->fat32RootCluster = 2;
|
||||
pb->fat32FSInfo = 1;
|
||||
pb->fat32BackBootBlock = 6;
|
||||
pb->driveNumber = 0X80;
|
||||
pb->bootSignature = EXTENDED_BOOT_SIG;
|
||||
pb->volumeSerialNumber = volSerialNumber();
|
||||
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||
memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
|
||||
// write partition boot sector and backup
|
||||
if (!writeCache(relSector)
|
||||
|| !writeCache(relSector + 6)) {
|
||||
sdError("FAT32 write PBS failed");
|
||||
}
|
||||
clearCache(true);
|
||||
// write extra boot area and backup
|
||||
if (!writeCache(relSector + 2)
|
||||
|| !writeCache(relSector + 8)) {
|
||||
sdError("FAT32 PBS ext failed");
|
||||
}
|
||||
fat32_fsinfo_t* pf = &cache.fsinfo;
|
||||
pf->leadSignature = FSINFO_LEAD_SIG;
|
||||
pf->structSignature = FSINFO_STRUCT_SIG;
|
||||
pf->freeCount = 0XFFFFFFFF;
|
||||
pf->nextFree = 0XFFFFFFFF;
|
||||
// write FSINFO sector and backup
|
||||
if (!writeCache(relSector + 1)
|
||||
|| !writeCache(relSector + 7)) {
|
||||
sdError("FAT32 FSINFO failed");
|
||||
}
|
||||
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster);
|
||||
clearCache(false);
|
||||
cache.fat32[0] = 0x0FFFFFF8;
|
||||
cache.fat32[1] = 0x0FFFFFFF;
|
||||
cache.fat32[2] = 0x0FFFFFFF;
|
||||
// write first block of FAT and backup for reserved clusters
|
||||
if (!writeCache(fatStart)
|
||||
|| !writeCache(fatStart + fatSize)) {
|
||||
sdError("FAT32 reserve failed");
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// flash erase all data
|
||||
uint32_t const ERASE_SIZE = 262144L;
|
||||
void eraseCard() {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Erasing\n");
|
||||
gslc_Update(&m_gui);
|
||||
uint32_t firstBlock = 0;
|
||||
uint32_t lastBlock;
|
||||
uint16_t n = 0;
|
||||
|
||||
do {
|
||||
lastBlock = firstBlock + ERASE_SIZE - 1;
|
||||
if (lastBlock >= cardSizeBlocks) {
|
||||
lastBlock = cardSizeBlocks - 1;
|
||||
}
|
||||
if (!card.erase(firstBlock, lastBlock)) {
|
||||
sdError("erase failed");
|
||||
}
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, ".");
|
||||
gslc_Update(&m_gui);
|
||||
if ((n++)%32 == 31) {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "\n");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
firstBlock += ERASE_SIZE;
|
||||
} while (firstBlock < cardSizeBlocks);
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "\n");
|
||||
gslc_Update(&m_gui);
|
||||
|
||||
if (!card.readBlock(0, cache.data)) {
|
||||
sdError("readBlock");
|
||||
}
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Erase done\n");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void formatCard() {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Formatting\n");
|
||||
gslc_Update(&m_gui);
|
||||
initSizes();
|
||||
if (card.type() != SD_CARD_TYPE_SDHC) {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "FAT16\n");
|
||||
gslc_Update(&m_gui);
|
||||
makeFat16();
|
||||
} else {
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "FAT32\n");
|
||||
gslc_Update(&m_gui);
|
||||
makeFat32();
|
||||
}
|
||||
#if DEBUG_PRINT
|
||||
debugPrint();
|
||||
#endif // DEBUG_PRINT
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, "Format done\n");
|
||||
gslc_Update(&m_gui);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void eraseAndFormatCard() {
|
||||
#if USE_SDIO
|
||||
if (!card.begin()) {
|
||||
sdError("card.begin failed");
|
||||
}
|
||||
#else // USE_SDIO
|
||||
if (!card.begin(chipSelect, SPI_SPEED)) {
|
||||
sdError("card.begin failed");
|
||||
}
|
||||
#endif
|
||||
cardSizeBlocks = card.cardSize();
|
||||
if (cardSizeBlocks == 0) {
|
||||
sdError("cardSize");
|
||||
}
|
||||
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
|
||||
|
||||
char textForDisplay[128];
|
||||
snprintf(textForDisplay, 128, "Card Size: : %.0fMB, (MB = 1,000,000 bytes)\n", 1.048576*cardCapacityMB);
|
||||
gslc_ElemXTextboxAdd(&m_gui, m_pElemSDInfo, textForDisplay);
|
||||
gslc_Update(&m_gui);
|
||||
|
||||
eraseCard();
|
||||
formatCard();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
BIN
hardware/sd_card_formatter/sd_card_formatter.prj
Normal file
BIN
hardware/sd_card_formatter/sd_card_formatter.prj
Normal file
Binary file not shown.
255
hardware/sd_card_formatter/sd_card_formatter_GSLC.h
Normal file
255
hardware/sd_card_formatter/sd_card_formatter_GSLC.h
Normal file
|
@ -0,0 +1,255 @@
|
|||
//<File !Start!>
|
||||
// FILE: [sd_card_formatter_GSLC.h]
|
||||
// Created by GUIslice Builder version: [0.15.b004]
|
||||
//
|
||||
// GUIslice Builder Generated GUI Framework File
|
||||
//
|
||||
// For the latest guides, updates and support view:
|
||||
// https://github.com/ImpulseAdventure/GUIslice
|
||||
//
|
||||
//<File !End!>
|
||||
|
||||
#ifndef _GUISLICE_GEN_H
|
||||
#define _GUISLICE_GEN_H
|
||||
|
||||
// ------------------------------------------------
|
||||
// Headers to include
|
||||
// ------------------------------------------------
|
||||
#include "src/guislice/GUIslice.h"
|
||||
#include "src/guislice/GUIslice_drv.h"
|
||||
|
||||
// Include any extended elements
|
||||
//<Includes !Start!>
|
||||
// Include extended elements
|
||||
#include "src/guislice/XProgress.h"
|
||||
#include "src/guislice/XTextbox.h"
|
||||
//<Includes !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Headers and Defines for fonts
|
||||
// Note that font files are located within the Adafruit-GFX library folder:
|
||||
// ------------------------------------------------
|
||||
//<Fonts !Start!>
|
||||
#if defined(DRV_DISP_TFT_ESPI)
|
||||
#error Project tab->Target Platform should be tft_espi
|
||||
#endif
|
||||
#include <Adafruit_GFX.h>
|
||||
#include "src/guislice/NotoMono10pt7b.h"
|
||||
#include "src/guislice/NotoMono12pt7b.h"
|
||||
#include "src/guislice/NotoMono16pt7b.h"
|
||||
#include "src/guislice/NotoMono8pt7b.h"
|
||||
//<Fonts !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Defines for resources
|
||||
// ------------------------------------------------
|
||||
//<Resources !Start!>
|
||||
//<Resources !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Enumerations for pages, elements, fonts, images
|
||||
// ------------------------------------------------
|
||||
//<Enum !Start!>
|
||||
enum {E_PG_BASE,E_PG_MAIN,E_SD_CARD,E_PG_SD_CONFIRM};
|
||||
enum {E_ELEM_BATT_LEVEL,E_ELEM_BOX1,E_ELEM_BTN_SD_FMT,E_ELEM_SD_NO
|
||||
,E_ELEM_SD_YES,E_ELEM_STATUS,E_ELEM_TEXT14,E_ELEM_TEXT15
|
||||
,E_ELEM_TX_SD_INFO,E_STATUS_LINE};
|
||||
// Must use separate enum for fonts with MAX_FONT at end to use gslc_FontSet.
|
||||
enum {E_AO_NOTOMONO10PT7B,E_AO_NOTOMONO12PT7B,E_AO_NOTOMONO16PT7B
|
||||
,E_AO_NOTOMONO8PT7B,MAX_FONT};
|
||||
//<Enum !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Instantiate the GUI
|
||||
// ------------------------------------------------
|
||||
|
||||
// ------------------------------------------------
|
||||
// Define the maximum number of elements and pages
|
||||
// ------------------------------------------------
|
||||
//<ElementDefines !Start!>
|
||||
#define MAX_PAGE 4
|
||||
|
||||
#define MAX_ELEM_PG_BASE 3 // # Elems total on page
|
||||
#define MAX_ELEM_PG_BASE_RAM MAX_ELEM_PG_BASE // # Elems in RAM
|
||||
|
||||
#define MAX_ELEM_PG_MAIN 0 // # Elems total on page
|
||||
#define MAX_ELEM_PG_MAIN_RAM MAX_ELEM_PG_MAIN // # Elems in RAM
|
||||
|
||||
#define MAX_ELEM_SD_CARD 2 // # Elems total on page
|
||||
#define MAX_ELEM_SD_CARD_RAM MAX_ELEM_SD_CARD // # Elems in RAM
|
||||
|
||||
#define MAX_ELEM_PG_SD_CONFIRM 5 // # Elems total on page
|
||||
#define MAX_ELEM_PG_SD_CONFIRM_RAM MAX_ELEM_PG_SD_CONFIRM // # Elems in RAM
|
||||
//<ElementDefines !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Create element storage
|
||||
// ------------------------------------------------
|
||||
gslc_tsGui m_gui;
|
||||
gslc_tsDriver m_drv;
|
||||
gslc_tsFont m_asFont[MAX_FONT];
|
||||
gslc_tsPage m_asPage[MAX_PAGE];
|
||||
|
||||
//<GUI_Extra_Elements !Start!>
|
||||
gslc_tsElem m_asBasePage1Elem[MAX_ELEM_PG_BASE_RAM];
|
||||
gslc_tsElemRef m_asBasePage1ElemRef[MAX_ELEM_PG_BASE];
|
||||
gslc_tsElem m_asPage1Elem[MAX_ELEM_PG_MAIN_RAM];
|
||||
gslc_tsElemRef m_asPage1ElemRef[MAX_ELEM_PG_MAIN];
|
||||
gslc_tsElem m_asPage3Elem[MAX_ELEM_SD_CARD_RAM];
|
||||
gslc_tsElemRef m_asPage3ElemRef[MAX_ELEM_SD_CARD];
|
||||
gslc_tsElem m_asPopup1Elem[MAX_ELEM_PG_SD_CONFIRM_RAM];
|
||||
gslc_tsElemRef m_asPopup1ElemRef[MAX_ELEM_PG_SD_CONFIRM];
|
||||
gslc_tsXProgress m_sXBarGauge2;
|
||||
gslc_tsXTextbox m_sTextbox2;
|
||||
char m_acTextboxBuf2[224]; // NRows=8 NCols=28
|
||||
|
||||
#define MAX_STR 100
|
||||
|
||||
//<GUI_Extra_Elements !End!>
|
||||
|
||||
// ------------------------------------------------
|
||||
// Program Globals
|
||||
// ------------------------------------------------
|
||||
|
||||
// Element References for direct access
|
||||
//<Extern_References !Start!>
|
||||
extern gslc_tsElemRef* m_pElemBatteryLevel;
|
||||
extern gslc_tsElemRef* m_pElemBtSDNo;
|
||||
extern gslc_tsElemRef* m_pElemBtSDYes;
|
||||
extern gslc_tsElemRef* m_pElemSDInfo;
|
||||
extern gslc_tsElemRef* m_pElemStatusText;
|
||||
extern gslc_tsElemRef* m_pTextSliderSDInfo;
|
||||
//<Extern_References !End!>
|
||||
|
||||
// Define debug message function
|
||||
static int16_t DebugOut(char ch);
|
||||
|
||||
// ------------------------------------------------
|
||||
// Callback Methods
|
||||
// ------------------------------------------------
|
||||
bool CbBtnCommon(void* pvGui,void *pvElemRef,gslc_teTouch eTouch,int16_t nX,int16_t nY);
|
||||
bool CbCheckbox(void* pvGui, void* pvElemRef, int16_t nSelId, bool bState);
|
||||
bool CbDrawScanner(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw);
|
||||
bool CbKeypad(void* pvGui, void *pvElemRef, int16_t nState, void* pvData);
|
||||
bool CbListbox(void* pvGui, void* pvElemRef, int16_t nSelId);
|
||||
bool CbSlidePos(void* pvGui,void* pvElemRef,int16_t nPos);
|
||||
bool CbSpinner(void* pvGui, void *pvElemRef, int16_t nState, void* pvData);
|
||||
bool CbTickScanner(void* pvGui,void* pvScope);
|
||||
|
||||
// ------------------------------------------------
|
||||
// Create page elements
|
||||
// ------------------------------------------------
|
||||
void InitGUIslice_gen()
|
||||
{
|
||||
gslc_tsElemRef* pElemRef = NULL;
|
||||
|
||||
if (!gslc_Init(&m_gui,&m_drv,m_asPage,MAX_PAGE,m_asFont,MAX_FONT)) { return; }
|
||||
|
||||
// ------------------------------------------------
|
||||
// Load Fonts
|
||||
// ------------------------------------------------
|
||||
//<Load_Fonts !Start!>
|
||||
if (!gslc_FontSet(&m_gui,E_AO_NOTOMONO10PT7B,GSLC_FONTREF_PTR,&NotoMono10pt7b,1)) { return; }
|
||||
if (!gslc_FontSet(&m_gui,E_AO_NOTOMONO12PT7B,GSLC_FONTREF_PTR,&NotoMono12pt7b,1)) { return; }
|
||||
if (!gslc_FontSet(&m_gui,E_AO_NOTOMONO16PT7B,GSLC_FONTREF_PTR,&NotoMono16pt7b,1)) { return; }
|
||||
if (!gslc_FontSet(&m_gui,E_AO_NOTOMONO8PT7B,GSLC_FONTREF_PTR,&NotoMono8pt7b,1)) { return; }
|
||||
//<Load_Fonts !End!>
|
||||
|
||||
//<InitGUI !Start!>
|
||||
gslc_PageAdd(&m_gui,E_PG_BASE,m_asBasePage1Elem,MAX_ELEM_PG_BASE_RAM,m_asBasePage1ElemRef,MAX_ELEM_PG_BASE);
|
||||
gslc_PageAdd(&m_gui,E_PG_MAIN,m_asPage1Elem,MAX_ELEM_PG_MAIN_RAM,m_asPage1ElemRef,MAX_ELEM_PG_MAIN);
|
||||
gslc_PageAdd(&m_gui,E_SD_CARD,m_asPage3Elem,MAX_ELEM_SD_CARD_RAM,m_asPage3ElemRef,MAX_ELEM_SD_CARD);
|
||||
gslc_PageAdd(&m_gui,E_PG_SD_CONFIRM,m_asPopup1Elem,MAX_ELEM_PG_SD_CONFIRM_RAM,m_asPopup1ElemRef,MAX_ELEM_PG_SD_CONFIRM);
|
||||
|
||||
// Now mark E_PG_BASE as a "base" page which means that it's elements
|
||||
// are always visible. This is useful for common page elements.
|
||||
gslc_SetPageBase(&m_gui, E_PG_BASE);
|
||||
|
||||
|
||||
// NOTE: The current page defaults to the first page added. Here we explicitly
|
||||
// ensure that the main page is the correct page no matter the add order.
|
||||
gslc_SetPageCur(&m_gui,E_PG_MAIN);
|
||||
|
||||
// Set Background to a flat color
|
||||
gslc_SetBkgndColor(&m_gui,GSLC_COL_BLACK);
|
||||
|
||||
// -----------------------------------
|
||||
// PAGE: E_PG_BASE
|
||||
|
||||
|
||||
// Create progress bar E_ELEM_BATT_LEVEL
|
||||
pElemRef = gslc_ElemXProgressCreate(&m_gui,E_ELEM_BATT_LEVEL,E_PG_BASE,&m_sXBarGauge2,
|
||||
(gslc_tsRect){263,5,50,15},0,100,0,GSLC_COL_GREEN,false);
|
||||
m_pElemBatteryLevel = pElemRef;
|
||||
|
||||
// Create E_ELEM_STATUS text label
|
||||
pElemRef = gslc_ElemCreateTxt(&m_gui,E_ELEM_STATUS,E_PG_BASE,(gslc_tsRect){2,2,250,21},
|
||||
(char*)"SD Card Formatter",0,E_AO_NOTOMONO8PT7B);
|
||||
gslc_ElemSetTxtCol(&m_gui,pElemRef,GSLC_COL_GREEN);
|
||||
m_pElemStatusText = pElemRef;
|
||||
|
||||
// Create E_STATUS_LINE line
|
||||
pElemRef = gslc_ElemCreateLine(&m_gui,E_STATUS_LINE,E_PG_BASE,0,25,320,25);
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_BLACK,GSLC_COL_GRAY_DK1,GSLC_COL_GRAY_DK1);
|
||||
|
||||
// -----------------------------------
|
||||
// PAGE: E_PG_MAIN
|
||||
|
||||
|
||||
// -----------------------------------
|
||||
// PAGE: E_SD_CARD
|
||||
|
||||
|
||||
// Create textbox
|
||||
pElemRef = gslc_ElemXTextboxCreate(&m_gui,E_ELEM_TX_SD_INFO,E_SD_CARD,&m_sTextbox2,
|
||||
(gslc_tsRect){3,30,313,150},E_AO_NOTOMONO8PT7B,
|
||||
(char*)&m_acTextboxBuf2,8,28);
|
||||
gslc_ElemXTextboxWrapSet(&m_gui,pElemRef,true);
|
||||
gslc_ElemSetTxtCol(&m_gui,pElemRef,GSLC_COL_GRAY_LT3);
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_GRAY,GSLC_COL_BLACK,GSLC_COL_BLACK);
|
||||
m_pElemSDInfo = pElemRef;
|
||||
|
||||
// create E_ELEM_BTN_SD_FMT button with text label
|
||||
pElemRef = gslc_ElemCreateBtnTxt(&m_gui,E_ELEM_BTN_SD_FMT,E_SD_CARD,
|
||||
(gslc_tsRect){110,190,100,40},(char*)"FORMAT?",0,E_AO_NOTOMONO8PT7B,&CbBtnCommon);
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_RED_DK1,GSLC_COL_GRAY,GSLC_COL_RED_DK1);
|
||||
|
||||
// -----------------------------------
|
||||
// PAGE: E_PG_SD_CONFIRM
|
||||
|
||||
|
||||
// Create E_ELEM_BOX1 box
|
||||
pElemRef = gslc_ElemCreateBox(&m_gui,E_ELEM_BOX1,E_PG_SD_CONFIRM,(gslc_tsRect){0,0,320,240});
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_BLACK,GSLC_COL_BLACK,GSLC_COL_BLACK);
|
||||
|
||||
// Create E_ELEM_TEXT14 text label
|
||||
pElemRef = gslc_ElemCreateTxt(&m_gui,E_ELEM_TEXT14,E_PG_SD_CONFIRM,(gslc_tsRect){0,30,320,42},
|
||||
(char*)"Format SD Card?",0,E_AO_NOTOMONO16PT7B);
|
||||
gslc_ElemSetTxtAlign(&m_gui,pElemRef,GSLC_ALIGN_MID_MID);
|
||||
gslc_ElemSetTxtCol(&m_gui,pElemRef,GSLC_COL_RED_LT1);
|
||||
|
||||
// Create E_ELEM_TEXT15 text label
|
||||
pElemRef = gslc_ElemCreateTxt(&m_gui,E_ELEM_TEXT15,E_PG_SD_CONFIRM,(gslc_tsRect){0,90,320,32},
|
||||
(char*)"This will ERASE it!",0,E_AO_NOTOMONO12PT7B);
|
||||
gslc_ElemSetTxtAlign(&m_gui,pElemRef,GSLC_ALIGN_MID_MID);
|
||||
gslc_ElemSetTxtCol(&m_gui,pElemRef,GSLC_COL_RED_LT4);
|
||||
|
||||
// create E_ELEM_SD_NO button with text label
|
||||
pElemRef = gslc_ElemCreateBtnTxt(&m_gui,E_ELEM_SD_NO,E_PG_SD_CONFIRM,
|
||||
(gslc_tsRect){50,160,80,40},(char*)"No",0,E_AO_NOTOMONO10PT7B,&CbBtnCommon);
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_BLUE_LT2,GSLC_COL_GRAY,GSLC_COL_BLUE_LT2);
|
||||
m_pElemBtSDNo = pElemRef;
|
||||
|
||||
// create E_ELEM_SD_YES button with text label
|
||||
pElemRef = gslc_ElemCreateBtnTxt(&m_gui,E_ELEM_SD_YES,E_PG_SD_CONFIRM,
|
||||
(gslc_tsRect){170,160,80,40},(char*)"Yes",0,E_AO_NOTOMONO10PT7B,&CbBtnCommon);
|
||||
gslc_ElemSetCol(&m_gui,pElemRef,GSLC_COL_RED_LT1,GSLC_COL_GRAY,GSLC_COL_RED_LT1);
|
||||
m_pElemBtSDYes = pElemRef;
|
||||
//<InitGUI !End!>
|
||||
|
||||
//<Startup !Start!>
|
||||
//<Startup !End!>
|
||||
|
||||
}
|
||||
|
||||
#endif // end _GUISLICE_GEN_H
|
40
hardware/sd_card_formatter/src/SdFat/BlockDriver.h
Normal file
40
hardware/sd_card_formatter/src/SdFat/BlockDriver.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief Define block driver.
|
||||
*/
|
||||
#ifndef BlockDriver_h
|
||||
#define BlockDriver_h
|
||||
#include "FatLib/BaseBlockDriver.h"
|
||||
#include "SdCard/SdSpiCard.h"
|
||||
//-----------------------------------------------------------------------------
|
||||
/** typedef for BlockDriver */
|
||||
#if ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
typedef BaseBlockDriver BlockDriver;
|
||||
#else // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
typedef SdSpiCard BlockDriver;
|
||||
#endif // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
#endif // BlockDriver_h
|
249
hardware/sd_card_formatter/src/SdFat/FatLib/ArduinoFiles.h
Normal file
249
hardware/sd_card_formatter/src/SdFat/FatLib/ArduinoFiles.h
Normal file
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief PrintFile class
|
||||
*/
|
||||
#ifndef ArduinoFiles_h
|
||||
#define ArduinoFiles_h
|
||||
#include "FatLibConfig.h"
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
#include "FatFile.h"
|
||||
#include <limits.h>
|
||||
//------------------------------------------------------------------------------
|
||||
/** Arduino SD.h style flag for open for read. */
|
||||
#define FILE_READ O_RDONLY
|
||||
/** Arduino SD.h style flag for open at EOF for read/write with create. */
|
||||
#define FILE_WRITE (O_RDWR | O_CREAT | O_AT_END)
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class PrintFile
|
||||
* \brief FatFile with Print.
|
||||
*/
|
||||
class PrintFile : public FatFile, public Print {
|
||||
public:
|
||||
PrintFile() {}
|
||||
/** Create a file object and open it in the current working directory.
|
||||
*
|
||||
* \param[in] path A path for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a
|
||||
* bitwise-inclusive OR of open flags. see
|
||||
* FatFile::open(FatFile*, const char*, oflag_t).
|
||||
*/
|
||||
PrintFile(const char* path, oflag_t oflag) : FatFile(path, oflag) {}
|
||||
#if DESTRUCTOR_CLOSES_FILE
|
||||
~PrintFile() {}
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
using FatFile::clearWriteError;
|
||||
using FatFile::getWriteError;
|
||||
using FatFile::read;
|
||||
using FatFile::write;
|
||||
/** \return number of bytes available from the current position to EOF
|
||||
* or INT_MAX if more than INT_MAX bytes are available.
|
||||
*/
|
||||
int available() {
|
||||
uint32_t n = FatFile::available();
|
||||
return n > INT_MAX ? INT_MAX : n;
|
||||
}
|
||||
/** Ensure that any bytes written to the file are saved to the SD card. */
|
||||
void flush() {
|
||||
FatFile::sync();
|
||||
}
|
||||
/** Return the next available byte without consuming it.
|
||||
*
|
||||
* \return The byte if no error and not at eof else -1;
|
||||
*/
|
||||
int peek() {
|
||||
return FatFile::peek();
|
||||
}
|
||||
/** Read the next byte from a file.
|
||||
*
|
||||
* \return For success return the next byte in the file as an int.
|
||||
* If an error occurs or end of file is reached return -1.
|
||||
*/
|
||||
// int read() {
|
||||
// return FatFile::read();
|
||||
// }
|
||||
/** Write a byte to a file. Required by the Arduino Print class.
|
||||
* \param[in] b the byte to be written.
|
||||
* Use getWriteError to check for errors.
|
||||
* \return 1 for success and 0 for failure.
|
||||
*/
|
||||
size_t write(uint8_t b) {
|
||||
return FatFile::write(b);
|
||||
}
|
||||
/** Write data to an open file. Form required by Print.
|
||||
*
|
||||
* \note Data is moved to the cache but may not be written to the
|
||||
* storage device until sync() is called.
|
||||
*
|
||||
* \param[in] buf Pointer to the location of the data to be written.
|
||||
*
|
||||
* \param[in] size Number of bytes to write.
|
||||
*
|
||||
* \return For success write() returns the number of bytes written, always
|
||||
* \a nbyte. If an error occurs, write() returns -1. Possible errors
|
||||
* include write() is called before a file has been opened, write is called
|
||||
* for a read-only file, device is full, a corrupt file system or an
|
||||
* I/O error.
|
||||
*/
|
||||
size_t write(const uint8_t *buf, size_t size) {
|
||||
return FatFile::write(buf, size);
|
||||
}
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class File
|
||||
* \brief Arduino SD.h style File API
|
||||
*/
|
||||
class File : public FatFile, public Stream {
|
||||
public:
|
||||
File() {}
|
||||
/** Create a file object and open it in the current working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a
|
||||
* bitwise-inclusive OR of open flags. see
|
||||
* FatFile::open(FatFile*, const char*, oflag_t).
|
||||
*/
|
||||
File(const char* path, oflag_t oflag) {
|
||||
open(path, oflag);
|
||||
}
|
||||
using FatFile::clearWriteError;
|
||||
using FatFile::getWriteError;
|
||||
using FatFile::read;
|
||||
using FatFile::write;
|
||||
/** The parenthesis operator.
|
||||
*
|
||||
* \return true if a file is open.
|
||||
*/
|
||||
operator bool() {
|
||||
return isOpen();
|
||||
}
|
||||
/** \return number of bytes available from the current position to EOF
|
||||
* or INT_MAX if more than INT_MAX bytes are available.
|
||||
*/
|
||||
int available() {
|
||||
uint32_t n = FatFile::available();
|
||||
return n > INT_MAX ? INT_MAX : n;
|
||||
}
|
||||
/** Ensure that any bytes written to the file are saved to the SD card. */
|
||||
void flush() {
|
||||
FatFile::sync();
|
||||
}
|
||||
/** This function reports if the current file is a directory or not.
|
||||
* \return true if the file is a directory.
|
||||
*/
|
||||
bool isDirectory() {
|
||||
return isDir();
|
||||
}
|
||||
/** No longer implemented due to Long File Names.
|
||||
*
|
||||
* Use getName(char* name, size_t size).
|
||||
* \return a pointer to replacement suggestion.
|
||||
*/
|
||||
const char* name() const {
|
||||
return "use getName()";
|
||||
}
|
||||
/** Return the next available byte without consuming it.
|
||||
*
|
||||
* \return The byte if no error and not at eof else -1;
|
||||
*/
|
||||
int peek() {
|
||||
return FatFile::peek();
|
||||
}
|
||||
/** \return the current file position. */
|
||||
uint32_t position() {
|
||||
return curPosition();
|
||||
}
|
||||
/** Opens the next file or folder in a directory.
|
||||
*
|
||||
* \param[in] oflag open oflag flags.
|
||||
* \return a File object.
|
||||
*/
|
||||
File openNextFile(oflag_t oflag = O_RDONLY) {
|
||||
File tmpFile;
|
||||
tmpFile.openNext(this, oflag);
|
||||
return tmpFile;
|
||||
}
|
||||
/** Read the next byte from a file.
|
||||
*
|
||||
* \return For success return the next byte in the file as an int.
|
||||
* If an error occurs or end of file is reached return -1.
|
||||
*/
|
||||
int read() {
|
||||
return FatFile::read();
|
||||
}
|
||||
/** Rewind a file if it is a directory */
|
||||
void rewindDirectory() {
|
||||
if (isDir()) {
|
||||
rewind();
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Seek to a new position in the file, which must be between
|
||||
* 0 and the size of the file (inclusive).
|
||||
*
|
||||
* \param[in] pos the new file position.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool seek(uint32_t pos) {
|
||||
return seekSet(pos);
|
||||
}
|
||||
/** \return the file's size. */
|
||||
uint32_t size() {
|
||||
return fileSize();
|
||||
}
|
||||
/** Write a byte to a file. Required by the Arduino Print class.
|
||||
* \param[in] b the byte to be written.
|
||||
* Use getWriteError to check for errors.
|
||||
* \return 1 for success and 0 for failure.
|
||||
*/
|
||||
size_t write(uint8_t b) {
|
||||
return FatFile::write(b);
|
||||
}
|
||||
/** Write data to an open file. Form required by Print.
|
||||
*
|
||||
* \note Data is moved to the cache but may not be written to the
|
||||
* storage device until sync() is called.
|
||||
*
|
||||
* \param[in] buf Pointer to the location of the data to be written.
|
||||
*
|
||||
* \param[in] size Number of bytes to write.
|
||||
*
|
||||
* \return For success write() returns the number of bytes written, always
|
||||
* \a nbyte. If an error occurs, write() returns -1. Possible errors
|
||||
* include write() is called before a file has been opened, write is called
|
||||
* for a read-only file, device is full, a corrupt file system or an
|
||||
* I/O error.
|
||||
*/
|
||||
size_t write(const uint8_t *buf, size_t size) {
|
||||
return FatFile::write(buf, size);
|
||||
}
|
||||
};
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
#endif // ArduinoFiles_h
|
153
hardware/sd_card_formatter/src/SdFat/FatLib/ArduinoStream.h
Normal file
153
hardware/sd_card_formatter/src/SdFat/FatLib/ArduinoStream.h
Normal file
|
@ -0,0 +1,153 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ArduinoStream_h
|
||||
#define ArduinoStream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief ArduinoInStream and ArduinoOutStream classes
|
||||
*/
|
||||
#include "FatLibConfig.h"
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
#include "bufstream.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ArduinoInStream
|
||||
* \brief Input stream for Arduino Stream objects
|
||||
*/
|
||||
class ArduinoInStream : public ibufstream {
|
||||
public:
|
||||
/**
|
||||
* Constructor
|
||||
* \param[in] hws hardware stream
|
||||
* \param[in] buf buffer for input line
|
||||
* \param[in] size size of input buffer
|
||||
*/
|
||||
ArduinoInStream(Stream &hws, char* buf, size_t size) {
|
||||
m_hw = &hws;
|
||||
m_line = buf;
|
||||
m_size = size;
|
||||
}
|
||||
/** read a line. */
|
||||
void readline() {
|
||||
size_t i = 0;
|
||||
uint32_t t;
|
||||
m_line[0] = '\0';
|
||||
while (!m_hw->available()) {
|
||||
yield();
|
||||
}
|
||||
|
||||
while (1) {
|
||||
t = millis();
|
||||
while (!m_hw->available()) {
|
||||
if ((millis() - t) > 10) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (i >= (m_size - 1)) {
|
||||
setstate(failbit);
|
||||
return;
|
||||
}
|
||||
m_line[i++] = m_hw->read();
|
||||
m_line[i] = '\0';
|
||||
}
|
||||
done:
|
||||
init(m_line);
|
||||
}
|
||||
|
||||
protected:
|
||||
/** Internal - do not use.
|
||||
* \param[in] off
|
||||
* \param[in] way
|
||||
* \return true/false.
|
||||
*/
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
(void)off;
|
||||
(void)way;
|
||||
return false;
|
||||
}
|
||||
/** Internal - do not use.
|
||||
* \param[in] pos
|
||||
* \return true/false.
|
||||
*/
|
||||
bool seekpos(pos_type pos) {
|
||||
(void)pos;
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
char *m_line;
|
||||
size_t m_size;
|
||||
Stream* m_hw;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ArduinoOutStream
|
||||
* \brief Output stream for Arduino Print objects
|
||||
*/
|
||||
class ArduinoOutStream : public ostream {
|
||||
public:
|
||||
/** constructor
|
||||
*
|
||||
* \param[in] pr Print object for this ArduinoOutStream.
|
||||
*/
|
||||
explicit ArduinoOutStream(Print& pr) : m_pr(&pr) {}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/**
|
||||
* Internal do not use
|
||||
* \param[in] c
|
||||
*/
|
||||
void putch(char c) {
|
||||
if (c == '\n') {
|
||||
m_pr->write('\r');
|
||||
}
|
||||
m_pr->write(c);
|
||||
}
|
||||
void putstr(const char* str) {
|
||||
m_pr->write(str);
|
||||
}
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
(void)off;
|
||||
(void)way;
|
||||
return false;
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
(void)pos;
|
||||
return false;
|
||||
}
|
||||
bool sync() {
|
||||
return true;
|
||||
}
|
||||
pos_type tellpos() {
|
||||
return 0;
|
||||
}
|
||||
/// @endcond
|
||||
private:
|
||||
ArduinoOutStream() {}
|
||||
Print* m_pr;
|
||||
};
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
#endif // ArduinoStream_h
|
|
@ -0,0 +1,80 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef BaseBlockDriver_h
|
||||
#define BaseBlockDriver_h
|
||||
#include "FatLibConfig.h"
|
||||
/**
|
||||
* \class BaseBlockDriver
|
||||
* \brief Base block driver.
|
||||
*/
|
||||
class BaseBlockDriver {
|
||||
public:
|
||||
/**
|
||||
* Read a 512 byte block from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
virtual bool readBlock(uint32_t block, uint8_t* dst) = 0;
|
||||
/** End multi-block transfer and go to idle state.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
virtual bool syncBlocks() = 0;
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
virtual bool writeBlock(uint32_t block, const uint8_t* src) = 0;
|
||||
#if USE_MULTI_BLOCK_IO
|
||||
/**
|
||||
* Read multiple 512 byte blocks from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[in] nb Number of blocks to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
virtual bool readBlocks(uint32_t block, uint8_t* dst, size_t nb) = 0;
|
||||
/**
|
||||
* Write multiple 512 byte blocks to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] nb Number of blocks to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
virtual bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb) = 0;
|
||||
#endif // USE_MULTI_BLOCK_IO
|
||||
};
|
||||
#endif // BaseBlockDriver_h
|
|
@ -0,0 +1,87 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatApiConstants_h
|
||||
#define FatApiConstants_h
|
||||
#include "../SdFatConfig.h"
|
||||
|
||||
#if USE_FCNTL_H
|
||||
#include <fcntl.h>
|
||||
/* values for GNU Arm Embedded Toolchain.
|
||||
* O_RDONLY: 0x0
|
||||
* O_WRONLY: 0x1
|
||||
* O_RDWR: 0x2
|
||||
* O_ACCMODE: 0x3
|
||||
* O_APPEND: 0x8
|
||||
* O_CREAT: 0x200
|
||||
* O_TRUNC: 0x400
|
||||
* O_EXCL: 0x800
|
||||
* O_SYNC: 0x2000
|
||||
* O_NONBLOCK: 0x4000
|
||||
*/
|
||||
/** Use O_NONBLOCK for open at EOF */
|
||||
#define O_AT_END O_NONBLOCK ///< Open at EOF.
|
||||
typedef int oflag_t;
|
||||
#else // USE_FCNTL_H
|
||||
#define O_RDONLY 0X00 ///< Open for reading only.
|
||||
#define O_WRONLY 0X01 ///< Open for writing only.
|
||||
#define O_RDWR 0X02 ///< Open for reading and writing.
|
||||
#define O_AT_END 0X04 ///< Open at EOF.
|
||||
#define O_APPEND 0X08 ///< Set append mode.
|
||||
#define O_CREAT 0x10 ///< Create file if it does not exist.
|
||||
#define O_TRUNC 0x20 ///< Truncate file to zero length.
|
||||
#define O_EXCL 0x40 ///< Fail if the file exists.
|
||||
#define O_SYNC 0x80 ///< Synchronized write I/O operations.
|
||||
|
||||
#define O_ACCMODE (O_RDONLY|O_WRONLY|O_RDWR) ///< Mask for access mode.
|
||||
typedef uint8_t oflag_t;
|
||||
#endif // USE_FCNTL_H
|
||||
|
||||
#define O_READ O_RDONLY
|
||||
#define O_WRITE O_WRONLY
|
||||
|
||||
inline bool isWriteMode(oflag_t oflag) {
|
||||
oflag &= O_ACCMODE;
|
||||
return oflag == O_WRONLY || oflag == O_RDWR;
|
||||
}
|
||||
|
||||
// FatFile class static and const definitions
|
||||
// flags for ls()
|
||||
/** ls() flag for list all files including hidden. */
|
||||
#define LS_A 1
|
||||
/** ls() flag to print modify. date */
|
||||
#define LS_DATE 2
|
||||
/** ls() flag to print file size. */
|
||||
#define LS_SIZE 4
|
||||
/** ls() flag for recursive list of subdirectories */
|
||||
#define LS_R 8
|
||||
|
||||
// flags for timestamp
|
||||
/** set the file's last access date */
|
||||
#define T_ACCESS 1
|
||||
/** set the file's creation date and time */
|
||||
#define T_CREATE 2
|
||||
/** Set the file's write date and time */
|
||||
#define T_WRITE 4
|
||||
#endif // FatApiConstants_h
|
1531
hardware/sd_card_formatter/src/SdFat/FatLib/FatFile.cpp
Normal file
1531
hardware/sd_card_formatter/src/SdFat/FatLib/FatFile.cpp
Normal file
File diff suppressed because it is too large
Load diff
1032
hardware/sd_card_formatter/src/SdFat/FatLib/FatFile.h
Normal file
1032
hardware/sd_card_formatter/src/SdFat/FatLib/FatFile.h
Normal file
File diff suppressed because it is too large
Load diff
685
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileLFN.cpp
Normal file
685
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileLFN.cpp
Normal file
|
@ -0,0 +1,685 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "FatFile.h"
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
uint8_t FatFile::lfnChecksum(uint8_t* name) {
|
||||
uint8_t sum = 0;
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
sum = (((sum & 1) << 7) | ((sum & 0xfe) >> 1)) + name[i];
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
#if USE_LONG_FILE_NAMES
|
||||
//------------------------------------------------------------------------------
|
||||
// Saves about 90 bytes of flash on 328 over tolower().
|
||||
inline char lfnToLower(char c) {
|
||||
return 'A' <= c && c <= 'Z' ? c + 'a' - 'A' : c;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Daniel Bernstein University of Illinois at Chicago.
|
||||
// Original had + instead of ^
|
||||
static uint16_t Bernstein(uint16_t hash, const char *str, size_t len) {
|
||||
for (size_t i = 0; i < len; i++) {
|
||||
// hash = hash * 33 ^ str[i];
|
||||
hash = ((hash << 5) + hash) ^ str[i];
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Fetch a 16-bit long file name character.
|
||||
*
|
||||
* \param[in] ldir Pointer to long file name directory entry.
|
||||
* \param[in] i Index of character.
|
||||
* \return The 16-bit character.
|
||||
*/
|
||||
static uint16_t lfnGetChar(ldir_t *ldir, uint8_t i) {
|
||||
if (i < LDIR_NAME1_DIM) {
|
||||
return ldir->name1[i];
|
||||
} else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM)) {
|
||||
return ldir->name2[i - LDIR_NAME1_DIM];
|
||||
} else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM + LDIR_NAME2_DIM)) {
|
||||
return ldir->name3[i - LDIR_NAME1_DIM - LDIR_NAME2_DIM];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static bool lfnGetName(ldir_t *ldir, char* name, size_t n) {
|
||||
uint8_t i;
|
||||
size_t k = 13*((ldir->ord & 0X1F) - 1);
|
||||
for (i = 0; i < 13; i++) {
|
||||
uint16_t c = lfnGetChar(ldir, i);
|
||||
if (c == 0 || k >= n) {
|
||||
break;
|
||||
}
|
||||
name[k++] = c >= 0X7F ? '?' : c;
|
||||
}
|
||||
// Terminate with zero byte if name fits.
|
||||
if (k < n && (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY)) {
|
||||
name[k] = 0;
|
||||
}
|
||||
// Truncate if name is too long.
|
||||
name[n - 1] = 0;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool lfnLegalChar(char c) {
|
||||
if (c == '/' || c == '\\' || c == '"' || c == '*' ||
|
||||
c == ':' || c == '<' || c == '>' || c == '?' || c == '|') {
|
||||
return false;
|
||||
}
|
||||
return 0X1F < c && c < 0X7F;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Store a 16-bit long file name character.
|
||||
*
|
||||
* \param[in] ldir Pointer to long file name directory entry.
|
||||
* \param[in] i Index of character.
|
||||
* \param[in] c The 16-bit character.
|
||||
*/
|
||||
static void lfnPutChar(ldir_t *ldir, uint8_t i, uint16_t c) {
|
||||
if (i < LDIR_NAME1_DIM) {
|
||||
ldir->name1[i] = c;
|
||||
} else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM)) {
|
||||
ldir->name2[i - LDIR_NAME1_DIM] = c;
|
||||
} else if (i < (LDIR_NAME1_DIM + LDIR_NAME2_DIM + LDIR_NAME2_DIM)) {
|
||||
ldir->name3[i - LDIR_NAME1_DIM - LDIR_NAME2_DIM] = c;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void lfnPutName(ldir_t *ldir, const char* name, size_t n) {
|
||||
size_t k = 13*((ldir->ord & 0X1F) - 1);
|
||||
for (uint8_t i = 0; i < 13; i++, k++) {
|
||||
uint16_t c = k < n ? name[k] : k == n ? 0 : 0XFFFF;
|
||||
lfnPutChar(ldir, i, c);
|
||||
}
|
||||
}
|
||||
//==============================================================================
|
||||
bool FatFile::getName(char* name, size_t size) {
|
||||
FatFile dirFile;
|
||||
ldir_t* ldir;
|
||||
if (!isOpen() || size < 13) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!isLFN()) {
|
||||
return getSFN(name);
|
||||
}
|
||||
if (!dirFile.openCluster(this)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
for (uint8_t ord = 1; ord <= m_lfnOrd; ord++) {
|
||||
if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache());
|
||||
if (!ldir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (ldir->attr != DIR_ATT_LONG_NAME) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (ord != (ldir->ord & 0X1F)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!lfnGetName(ldir, name, size)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Fall into fail.
|
||||
DBG_FAIL_MACRO;
|
||||
|
||||
fail:
|
||||
name[0] = 0;
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::openCluster(FatFile* file) {
|
||||
if (file->m_dirCluster == 0) {
|
||||
return openRoot(file->m_vol);
|
||||
}
|
||||
memset(this, 0, sizeof(FatFile));
|
||||
m_attr = FILE_ATTR_SUBDIR;
|
||||
m_flags = F_READ;
|
||||
m_vol = file->m_vol;
|
||||
m_firstCluster = file->m_dirCluster;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::parsePathName(const char* path,
|
||||
fname_t* fname, const char** ptr) {
|
||||
char c;
|
||||
bool is83;
|
||||
uint8_t bit = DIR_NT_LC_BASE;
|
||||
uint8_t lc = 0;
|
||||
uint8_t uc = 0;
|
||||
uint8_t i = 0;
|
||||
uint8_t in = 7;
|
||||
int end;
|
||||
int len = 0;
|
||||
int si;
|
||||
int dot;
|
||||
|
||||
// Skip leading spaces.
|
||||
while (*path == ' ') {
|
||||
path++;
|
||||
}
|
||||
fname->lfn = path;
|
||||
|
||||
for (len = 0; ; len++) {
|
||||
c = path[len];
|
||||
if (c == 0 || isDirSeparator(c)) {
|
||||
break;
|
||||
}
|
||||
if (!lfnLegalChar(c)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// Advance to next path component.
|
||||
for (end = len; path[end] == ' ' || isDirSeparator(path[end]); end++) {}
|
||||
*ptr = &path[end];
|
||||
|
||||
// Back over spaces and dots.
|
||||
while (len) {
|
||||
c = path[len - 1];
|
||||
if (c != '.' && c != ' ') {
|
||||
break;
|
||||
}
|
||||
len--;
|
||||
}
|
||||
// Max length of LFN is 255.
|
||||
if (len > 255) {
|
||||
return false;
|
||||
}
|
||||
fname->len = len;
|
||||
// Blank file short name.
|
||||
for (uint8_t k = 0; k < 11; k++) {
|
||||
fname->sfn[k] = ' ';
|
||||
}
|
||||
// skip leading spaces and dots.
|
||||
for (si = 0; path[si] == '.' || path[si] == ' '; si++) {}
|
||||
// Not 8.3 if leading dot or space.
|
||||
is83 = !si;
|
||||
|
||||
// find last dot.
|
||||
for (dot = len - 1; dot >= 0 && path[dot] != '.'; dot--) {}
|
||||
for (; si < len; si++) {
|
||||
c = path[si];
|
||||
if (c == ' ' || (c == '.' && dot != si)) {
|
||||
is83 = false;
|
||||
continue;
|
||||
}
|
||||
if (!legal83Char(c) && si != dot) {
|
||||
is83 = false;
|
||||
c = '_';
|
||||
}
|
||||
if (si == dot || i > in) {
|
||||
if (in == 10) {
|
||||
// Done - extension longer than three characters.
|
||||
is83 = false;
|
||||
break;
|
||||
}
|
||||
if (si != dot) {
|
||||
is83 = false;
|
||||
}
|
||||
// Break if no dot and base-name is longer than eight characters.
|
||||
if (si > dot) {
|
||||
break;
|
||||
}
|
||||
si = dot;
|
||||
in = 10; // Max index for full 8.3 name.
|
||||
i = 8; // Place for extension.
|
||||
bit = DIR_NT_LC_EXT; // bit for extension.
|
||||
} else {
|
||||
if ('a' <= c && c <= 'z') {
|
||||
c += 'A' - 'a';
|
||||
lc |= bit;
|
||||
} else if ('A' <= c && c <= 'Z') {
|
||||
uc |= bit;
|
||||
}
|
||||
fname->sfn[i++] = c;
|
||||
if (i < 7) {
|
||||
fname->seqPos = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (fname->sfn[0] == ' ') {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (is83) {
|
||||
fname->flags = lc & uc ? FNAME_FLAG_MIXED_CASE : lc;
|
||||
} else {
|
||||
fname->flags = FNAME_FLAG_LOST_CHARS;
|
||||
fname->sfn[fname->seqPos] = '~';
|
||||
fname->sfn[fname->seqPos + 1] = '1';
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) {
|
||||
bool fnameFound = false;
|
||||
uint8_t lfnOrd = 0;
|
||||
uint8_t freeNeed;
|
||||
uint8_t freeFound = 0;
|
||||
uint8_t ord = 0;
|
||||
uint8_t chksum = 0;
|
||||
uint16_t freeIndex = 0;
|
||||
uint16_t curIndex;
|
||||
dir_t* dir;
|
||||
ldir_t* ldir;
|
||||
size_t len = fname->len;
|
||||
|
||||
if (!dirFile || !dirFile->isDir() || isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Number of directory entries needed.
|
||||
freeNeed = fname->flags & FNAME_FLAG_NEED_LFN ? 1 + (len + 12)/13 : 1;
|
||||
|
||||
dirFile->rewind();
|
||||
while (1) {
|
||||
curIndex = dirFile->m_curPosition/32;
|
||||
dir = dirFile->readDirCache(true);
|
||||
if (!dir) {
|
||||
if (dirFile->getError()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// At EOF
|
||||
goto create;
|
||||
}
|
||||
if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == DIR_NAME_FREE) {
|
||||
if (freeFound == 0) {
|
||||
freeIndex = curIndex;
|
||||
}
|
||||
if (freeFound < freeNeed) {
|
||||
freeFound++;
|
||||
}
|
||||
if (dir->name[0] == DIR_NAME_FREE) {
|
||||
goto create;
|
||||
}
|
||||
} else {
|
||||
if (freeFound < freeNeed) {
|
||||
freeFound = 0;
|
||||
}
|
||||
}
|
||||
// skip empty slot or '.' or '..'
|
||||
if (dir->name[0] == DIR_NAME_DELETED || dir->name[0] == '.') {
|
||||
lfnOrd = 0;
|
||||
} else if (DIR_IS_LONG_NAME(dir)) {
|
||||
ldir_t *ldir = reinterpret_cast<ldir_t*>(dir);
|
||||
if (!lfnOrd) {
|
||||
if ((ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) == 0) {
|
||||
continue;
|
||||
}
|
||||
lfnOrd = ord = ldir->ord & 0X1F;
|
||||
chksum = ldir->chksum;
|
||||
} else if (ldir->ord != --ord || chksum != ldir->chksum) {
|
||||
lfnOrd = 0;
|
||||
continue;
|
||||
}
|
||||
size_t k = 13*(ord - 1);
|
||||
if (k >= len) {
|
||||
// Not found.
|
||||
lfnOrd = 0;
|
||||
continue;
|
||||
}
|
||||
for (uint8_t i = 0; i < 13; i++) {
|
||||
uint16_t u = lfnGetChar(ldir, i);
|
||||
if (k == len) {
|
||||
if (u != 0) {
|
||||
// Not found.
|
||||
lfnOrd = 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (u > 255 || lfnToLower(u) != lfnToLower(fname->lfn[k++])) {
|
||||
// Not found.
|
||||
lfnOrd = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (DIR_IS_FILE_OR_SUBDIR(dir)) {
|
||||
if (lfnOrd) {
|
||||
if (1 == ord && lfnChecksum(dir->name) == chksum) {
|
||||
goto found;
|
||||
}
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!memcmp(dir->name, fname->sfn, sizeof(fname->sfn))) {
|
||||
if (!(fname->flags & FNAME_FLAG_LOST_CHARS)) {
|
||||
goto found;
|
||||
}
|
||||
fnameFound = true;
|
||||
}
|
||||
} else {
|
||||
lfnOrd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
found:
|
||||
// Don't open if create only.
|
||||
if (oflag & O_EXCL) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
goto open;
|
||||
|
||||
create:
|
||||
// don't create unless O_CREAT and write mode.
|
||||
if (!(oflag & O_CREAT) || !isWriteMode(oflag)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// If at EOF start in next cluster.
|
||||
if (freeFound == 0) {
|
||||
freeIndex = curIndex;
|
||||
}
|
||||
|
||||
while (freeFound < freeNeed) {
|
||||
dir = dirFile->readDirCache();
|
||||
if (!dir) {
|
||||
if (dirFile->getError()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// EOF if no error.
|
||||
break;
|
||||
}
|
||||
freeFound++;
|
||||
}
|
||||
while (freeFound < freeNeed) {
|
||||
// Will fail if FAT16 root.
|
||||
if (!dirFile->addDirCluster()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Done if more than one block per cluster. Max freeNeed is 21.
|
||||
if (dirFile->m_vol->blocksPerCluster() > 1) {
|
||||
break;
|
||||
}
|
||||
freeFound += 16;
|
||||
}
|
||||
if (fnameFound) {
|
||||
if (!dirFile->lfnUniqueSfn(fname)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!dirFile->seekSet(32UL*freeIndex)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
lfnOrd = freeNeed - 1;
|
||||
for (uint8_t ord = lfnOrd ; ord ; ord--) {
|
||||
ldir = reinterpret_cast<ldir_t*>(dirFile->readDirCache());
|
||||
if (!ldir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
dirFile->m_vol->cacheDirty();
|
||||
ldir->ord = ord == lfnOrd ? LDIR_ORD_LAST_LONG_ENTRY | ord : ord;
|
||||
ldir->attr = DIR_ATT_LONG_NAME;
|
||||
ldir->type = 0;
|
||||
ldir->chksum = lfnChecksum(fname->sfn);
|
||||
ldir->mustBeZero = 0;
|
||||
lfnPutName(ldir, fname->lfn, len);
|
||||
}
|
||||
curIndex = dirFile->m_curPosition/32;
|
||||
dir = dirFile->readDirCache();
|
||||
if (!dir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// initialize as empty file
|
||||
memset(dir, 0, sizeof(dir_t));
|
||||
memcpy(dir->name, fname->sfn, 11);
|
||||
|
||||
// Set base-name and extension lower case bits.
|
||||
dir->reservedNT = (DIR_NT_LC_BASE | DIR_NT_LC_EXT) & fname->flags;
|
||||
|
||||
// set timestamps
|
||||
if (m_dateTime) {
|
||||
// call user date/time function
|
||||
m_dateTime(&dir->creationDate, &dir->creationTime);
|
||||
} else {
|
||||
// use default date/time
|
||||
dir->creationDate = FAT_DEFAULT_DATE;
|
||||
dir->creationTime = FAT_DEFAULT_TIME;
|
||||
}
|
||||
dir->lastAccessDate = dir->creationDate;
|
||||
dir->lastWriteDate = dir->creationDate;
|
||||
dir->lastWriteTime = dir->creationTime;
|
||||
|
||||
// Force write of entry to device.
|
||||
dirFile->m_vol->cacheDirty();
|
||||
|
||||
open:
|
||||
// open entry in cache.
|
||||
if (!openCachedEntry(dirFile, curIndex, oflag, lfnOrd)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printName(print_t* pr) {
|
||||
FatFile dirFile;
|
||||
ldir_t* ldir;
|
||||
size_t n = 0;
|
||||
uint16_t u;
|
||||
uint8_t buf[13];
|
||||
uint8_t i;
|
||||
|
||||
if (!isLFN()) {
|
||||
return printSFN(pr);
|
||||
}
|
||||
if (!dirFile.openCluster(this)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
for (uint8_t ord = 1; ord <= m_lfnOrd; ord++) {
|
||||
if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache());
|
||||
if (!ldir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (ldir->attr != DIR_ATT_LONG_NAME ||
|
||||
ord != (ldir->ord & 0X1F)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
for (i = 0; i < 13; i++) {
|
||||
u = lfnGetChar(ldir, i);
|
||||
if (u == 0) {
|
||||
// End of name.
|
||||
break;
|
||||
}
|
||||
buf[i] = u < 0X7F ? u : '?';
|
||||
n++;
|
||||
}
|
||||
pr->write(buf, i);
|
||||
}
|
||||
return n;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::remove() {
|
||||
bool last;
|
||||
uint8_t chksum;
|
||||
uint8_t ord;
|
||||
FatFile dirFile;
|
||||
dir_t* dir;
|
||||
ldir_t* ldir;
|
||||
|
||||
// Cant' remove not open for write.
|
||||
if (!isFile() || !(m_flags & F_WRITE)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Free any clusters.
|
||||
if (m_firstCluster && !m_vol->freeChain(m_firstCluster)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Cache directory entry.
|
||||
dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE);
|
||||
if (!dir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
chksum = lfnChecksum(dir->name);
|
||||
|
||||
// Mark entry deleted.
|
||||
dir->name[0] = DIR_NAME_DELETED;
|
||||
|
||||
// Set this file closed.
|
||||
m_attr = FILE_ATTR_CLOSED;
|
||||
|
||||
// Write entry to device.
|
||||
if (!m_vol->cacheSync()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!isLFN()) {
|
||||
// Done, no LFN entries.
|
||||
return true;
|
||||
}
|
||||
if (!dirFile.openCluster(this)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
for (ord = 1; ord <= m_lfnOrd; ord++) {
|
||||
if (!dirFile.seekSet(32UL*(m_dirIndex - ord))) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
ldir = reinterpret_cast<ldir_t*>(dirFile.readDirCache());
|
||||
if (!ldir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (ldir->attr != DIR_ATT_LONG_NAME ||
|
||||
ord != (ldir->ord & 0X1F) ||
|
||||
chksum != ldir->chksum) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
last = ldir->ord & LDIR_ORD_LAST_LONG_ENTRY;
|
||||
ldir->ord = DIR_NAME_DELETED;
|
||||
m_vol->cacheDirty();
|
||||
if (last) {
|
||||
if (!m_vol->cacheSync()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
// Fall into fail.
|
||||
DBG_FAIL_MACRO;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::lfnUniqueSfn(fname_t* fname) {
|
||||
const uint8_t FIRST_HASH_SEQ = 2; // min value is 2
|
||||
uint8_t pos = fname->seqPos;;
|
||||
dir_t *dir;
|
||||
uint16_t hex;
|
||||
|
||||
DBG_HALT_IF(!(fname->flags & FNAME_FLAG_LOST_CHARS));
|
||||
DBG_HALT_IF(fname->sfn[pos] != '~' && fname->sfn[pos + 1] != '1');
|
||||
|
||||
for (uint8_t seq = 2; seq < 100; seq++) {
|
||||
if (seq < FIRST_HASH_SEQ) {
|
||||
fname->sfn[pos + 1] = '0' + seq;
|
||||
} else {
|
||||
DBG_PRINT_IF(seq > FIRST_HASH_SEQ);
|
||||
hex = Bernstein(seq + fname->len, fname->lfn, fname->len);
|
||||
if (pos > 3) {
|
||||
// Make space in name for ~HHHH.
|
||||
pos = 3;
|
||||
}
|
||||
for (uint8_t i = pos + 4 ; i > pos; i--) {
|
||||
uint8_t h = hex & 0XF;
|
||||
fname->sfn[i] = h < 10 ? h + '0' : h + 'A' - 10;
|
||||
hex >>= 4;
|
||||
}
|
||||
}
|
||||
fname->sfn[pos] = '~';
|
||||
rewind();
|
||||
while (1) {
|
||||
dir = readDirCache(true);
|
||||
if (!dir) {
|
||||
if (!getError()) {
|
||||
// At EOF and name not found if no error.
|
||||
goto done;
|
||||
}
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (dir->name[0] == DIR_NAME_FREE) {
|
||||
goto done;
|
||||
}
|
||||
if (DIR_IS_FILE_OR_SUBDIR(dir) && !memcmp(fname->sfn, dir->name, 11)) {
|
||||
// Name found - try another.
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
// fall inti fail - too many tries.
|
||||
DBG_FAIL_MACRO;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
|
||||
done:
|
||||
return true;
|
||||
}
|
||||
#endif // #if USE_LONG_FILE_NAMES
|
267
hardware/sd_card_formatter/src/SdFat/FatLib/FatFilePrint.cpp
Normal file
267
hardware/sd_card_formatter/src/SdFat/FatLib/FatFilePrint.cpp
Normal file
|
@ -0,0 +1,267 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <math.h>
|
||||
#include "FatFile.h"
|
||||
#include "FmtNumber.h"
|
||||
//------------------------------------------------------------------------------
|
||||
// print uint8_t with width 2
|
||||
static void print2u(print_t* pr, uint8_t v) {
|
||||
char c0 = '?';
|
||||
char c1 = '?';
|
||||
if (v < 100) {
|
||||
c1 = v/10;
|
||||
c0 = v - 10*c1 + '0';
|
||||
c1 += '0';
|
||||
}
|
||||
pr->write(c1);
|
||||
pr->write(c0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void printU32(print_t* pr, uint32_t v) {
|
||||
char buf[11];
|
||||
char* ptr = buf + sizeof(buf);
|
||||
*--ptr = 0;
|
||||
pr->write(fmtDec(v, ptr));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void printHex(print_t* pr, uint8_t w, uint16_t h) {
|
||||
char buf[5];
|
||||
char* ptr = buf + sizeof(buf);
|
||||
*--ptr = 0;
|
||||
for (uint8_t i = 0; i < w; i++) {
|
||||
char c = h & 0XF;
|
||||
*--ptr = c < 10 ? c + '0' : c + 'A' - 10;
|
||||
h >>= 4;
|
||||
}
|
||||
pr->write(ptr);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatFile::dmpFile(print_t* pr, uint32_t pos, size_t n) {
|
||||
char text[17];
|
||||
text[16] = 0;
|
||||
if (n >= 0XFFF0) {
|
||||
n = 0XFFF0;
|
||||
}
|
||||
if (!seekSet(pos)) {
|
||||
return;
|
||||
}
|
||||
for (size_t i = 0; i <= n; i++) {
|
||||
if ((i & 15) == 0) {
|
||||
if (i) {
|
||||
pr->write(' ');
|
||||
pr->write(text);
|
||||
if (i == n) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
pr->write('\r');
|
||||
pr->write('\n');
|
||||
if (i >= n) {
|
||||
break;
|
||||
}
|
||||
printHex(pr, 4, i);
|
||||
pr->write(' ');
|
||||
}
|
||||
int16_t h = read();
|
||||
if (h < 0) {
|
||||
break;
|
||||
}
|
||||
pr->write(' ');
|
||||
printHex(pr, 2, h);
|
||||
text[i&15] = ' ' <= h && h < 0X7F ? h : '.';
|
||||
}
|
||||
pr->write('\r');
|
||||
pr->write('\n');
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::ls(print_t* pr, uint8_t flags, uint8_t indent) {
|
||||
FatFile file;
|
||||
if (!isDir() || getError()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
rewind();
|
||||
while (file.openNext(this, O_RDONLY)) {
|
||||
if (!file.isHidden() || (flags & LS_A)) {
|
||||
// indent for dir level
|
||||
for (uint8_t i = 0; i < indent; i++) {
|
||||
pr->write(' ');
|
||||
}
|
||||
if (flags & LS_DATE) {
|
||||
file.printModifyDateTime(pr);
|
||||
pr->write(' ');
|
||||
}
|
||||
if (flags & LS_SIZE) {
|
||||
file.printFileSize(pr);
|
||||
pr->write(' ');
|
||||
}
|
||||
file.printName(pr);
|
||||
if (file.isDir()) {
|
||||
pr->write('/');
|
||||
}
|
||||
pr->write('\r');
|
||||
pr->write('\n');
|
||||
if ((flags & LS_R) && file.isDir()) {
|
||||
if (!file.ls(pr, flags, indent + 2)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
file.close();
|
||||
}
|
||||
if (getError()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::printCreateDateTime(print_t* pr) {
|
||||
dir_t dir;
|
||||
if (!dirEntry(&dir)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
printFatDate(pr, dir.creationDate);
|
||||
pr->write(' ');
|
||||
printFatTime(pr, dir.creationTime);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatFile::printFatDate(print_t* pr, uint16_t fatDate) {
|
||||
printU32(pr, FAT_YEAR(fatDate));
|
||||
pr->write('-');
|
||||
print2u(pr, FAT_MONTH(fatDate));
|
||||
pr->write('-');
|
||||
print2u(pr, FAT_DAY(fatDate));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatFile::printFatTime(print_t* pr, uint16_t fatTime) {
|
||||
print2u(pr, FAT_HOUR(fatTime));
|
||||
pr->write(':');
|
||||
print2u(pr, FAT_MINUTE(fatTime));
|
||||
pr->write(':');
|
||||
print2u(pr, FAT_SECOND(fatTime));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Template for FatFile::printField() */
|
||||
template <typename Type>
|
||||
static int printFieldT(FatFile* file, char sign, Type value, char term) {
|
||||
char buf[3*sizeof(Type) + 3];
|
||||
char* str = &buf[sizeof(buf)];
|
||||
|
||||
if (term) {
|
||||
*--str = term;
|
||||
if (term == '\n') {
|
||||
*--str = '\r';
|
||||
}
|
||||
}
|
||||
#ifdef OLD_FMT
|
||||
do {
|
||||
Type m = value;
|
||||
value /= 10;
|
||||
*--str = '0' + m - 10*value;
|
||||
} while (value);
|
||||
#else // OLD_FMT
|
||||
str = fmtDec(value, str);
|
||||
#endif // OLD_FMT
|
||||
if (sign) {
|
||||
*--str = sign;
|
||||
}
|
||||
return file->write(str, &buf[sizeof(buf)] - str);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
int FatFile::printField(float value, char term, uint8_t prec) {
|
||||
char buf[24];
|
||||
char* str = &buf[sizeof(buf)];
|
||||
if (term) {
|
||||
*--str = term;
|
||||
if (term == '\n') {
|
||||
*--str = '\r';
|
||||
}
|
||||
}
|
||||
str = fmtFloat(value, str, prec);
|
||||
return write(str, buf + sizeof(buf) - str);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatFile::printField(uint16_t value, char term) {
|
||||
return printFieldT(this, 0, value, term);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatFile::printField(int16_t value, char term) {
|
||||
char sign = 0;
|
||||
if (value < 0) {
|
||||
sign = '-';
|
||||
value = -value;
|
||||
}
|
||||
return printFieldT(this, sign, (uint16_t)value, term);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatFile::printField(uint32_t value, char term) {
|
||||
return printFieldT(this, 0, value, term);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatFile::printField(int32_t value, char term) {
|
||||
char sign = 0;
|
||||
if (value < 0) {
|
||||
sign = '-';
|
||||
value = -value;
|
||||
}
|
||||
return printFieldT(this, sign, (uint32_t)value, term);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::printModifyDateTime(print_t* pr) {
|
||||
dir_t dir;
|
||||
if (!dirEntry(&dir)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
printFatDate(pr, dir.lastWriteDate);
|
||||
pr->write(' ');
|
||||
printFatTime(pr, dir.lastWriteTime);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printFileSize(print_t* pr) {
|
||||
char buf[11];
|
||||
char *ptr = buf + sizeof(buf);
|
||||
*--ptr = 0;
|
||||
ptr = fmtDec(fileSize(), ptr);
|
||||
while (ptr > buf) {
|
||||
*--ptr = ' ';
|
||||
}
|
||||
return pr->write(buf);
|
||||
}
|
278
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileSFN.cpp
Normal file
278
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileSFN.cpp
Normal file
|
@ -0,0 +1,278 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "FatFile.h"
|
||||
#include "FatFileSystem.h"
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::getSFN(char* name) {
|
||||
dir_t* dir;
|
||||
if (!isOpen()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (isRoot()) {
|
||||
name[0] = '/';
|
||||
name[1] = '\0';
|
||||
return true;
|
||||
}
|
||||
// cache entry
|
||||
dir = cacheDirEntry(FatCache::CACHE_FOR_READ);
|
||||
if (!dir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// format name
|
||||
dirName(dir, name);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printSFN(print_t* pr) {
|
||||
char name[13];
|
||||
if (!getSFN(name)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
return pr->write(name);
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
#if !USE_LONG_FILE_NAMES
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::getName(char* name, size_t size) {
|
||||
return size < 13 ? 0 : getSFN(name);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// format directory name field from a 8.3 name string
|
||||
bool FatFile::parsePathName(const char* path, fname_t* fname,
|
||||
const char** ptr) {
|
||||
uint8_t uc = 0;
|
||||
uint8_t lc = 0;
|
||||
uint8_t bit = FNAME_FLAG_LC_BASE;
|
||||
// blank fill name and extension
|
||||
for (uint8_t i = 0; i < 11; i++) {
|
||||
fname->sfn[i] = ' ';
|
||||
}
|
||||
|
||||
for (uint8_t i = 0, n = 7;; path++) {
|
||||
uint8_t c = *path;
|
||||
if (c == 0 || isDirSeparator(c)) {
|
||||
// Done.
|
||||
break;
|
||||
}
|
||||
if (c == '.' && n == 7) {
|
||||
n = 10; // max index for full 8.3 name
|
||||
i = 8; // place for extension
|
||||
|
||||
// bit for extension.
|
||||
bit = FNAME_FLAG_LC_EXT;
|
||||
} else {
|
||||
if (!legal83Char(c) || i > n) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if ('a' <= c && c <= 'z') {
|
||||
c += 'A' - 'a';
|
||||
lc |= bit;
|
||||
} else if ('A' <= c && c <= 'Z') {
|
||||
uc |= bit;
|
||||
}
|
||||
fname->sfn[i++] = c;
|
||||
}
|
||||
}
|
||||
// must have a file name, extension is optional
|
||||
if (fname->sfn[0] == ' ') {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Set base-name and extension bits.
|
||||
fname->flags = lc & uc ? 0 : lc;
|
||||
while (isDirSeparator(*path)) {
|
||||
path++;
|
||||
}
|
||||
*ptr = path;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// open with filename in fname
|
||||
#define SFN_OPEN_USES_CHKSUM 0
|
||||
bool FatFile::open(FatFile* dirFile, fname_t* fname, oflag_t oflag) {
|
||||
bool emptyFound = false;
|
||||
#if SFN_OPEN_USES_CHKSUM
|
||||
uint8_t chksum;
|
||||
#endif
|
||||
uint8_t lfnOrd = 0;
|
||||
uint16_t emptyIndex;
|
||||
uint16_t index = 0;
|
||||
dir_t* dir;
|
||||
ldir_t* ldir;
|
||||
|
||||
dirFile->rewind();
|
||||
while (1) {
|
||||
if (!emptyFound) {
|
||||
emptyIndex = index;
|
||||
}
|
||||
dir = dirFile->readDirCache(true);
|
||||
if (!dir) {
|
||||
if (dirFile->getError()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// At EOF if no error.
|
||||
break;
|
||||
}
|
||||
if (dir->name[0] == DIR_NAME_FREE) {
|
||||
emptyFound = true;
|
||||
break;
|
||||
}
|
||||
if (dir->name[0] == DIR_NAME_DELETED) {
|
||||
lfnOrd = 0;
|
||||
emptyFound = true;
|
||||
} else if (DIR_IS_FILE_OR_SUBDIR(dir)) {
|
||||
if (!memcmp(fname->sfn, dir->name, 11)) {
|
||||
// don't open existing file if O_EXCL
|
||||
if (oflag & O_EXCL) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
#if SFN_OPEN_USES_CHKSUM
|
||||
if (lfnOrd && chksum != lfnChecksum(dir->name)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
#endif // SFN_OPEN_USES_CHKSUM
|
||||
if (!openCachedEntry(dirFile, index, oflag, lfnOrd)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
} else {
|
||||
lfnOrd = 0;
|
||||
}
|
||||
} else if (DIR_IS_LONG_NAME(dir)) {
|
||||
ldir = reinterpret_cast<ldir_t*>(dir);
|
||||
if (ldir->ord & LDIR_ORD_LAST_LONG_ENTRY) {
|
||||
lfnOrd = ldir->ord & 0X1F;
|
||||
#if SFN_OPEN_USES_CHKSUM
|
||||
chksum = ldir->chksum;
|
||||
#endif // SFN_OPEN_USES_CHKSUM
|
||||
}
|
||||
} else {
|
||||
lfnOrd = 0;
|
||||
}
|
||||
index++;
|
||||
}
|
||||
// don't create unless O_CREAT and write mode
|
||||
if (!(oflag & O_CREAT) || !isWriteMode(oflag)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (emptyFound) {
|
||||
index = emptyIndex;
|
||||
} else {
|
||||
if (!dirFile->addDirCluster()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (!dirFile->seekSet(32UL*index)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
dir = dirFile->readDirCache();
|
||||
if (!dir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// initialize as empty file
|
||||
memset(dir, 0, sizeof(dir_t));
|
||||
memcpy(dir->name, fname->sfn, 11);
|
||||
|
||||
// Set base-name and extension lower case bits.
|
||||
dir->reservedNT = (DIR_NT_LC_BASE | DIR_NT_LC_EXT) & fname->flags;
|
||||
|
||||
// set timestamps
|
||||
if (m_dateTime) {
|
||||
// call user date/time function
|
||||
m_dateTime(&dir->creationDate, &dir->creationTime);
|
||||
} else {
|
||||
// use default date/time
|
||||
dir->creationDate = FAT_DEFAULT_DATE;
|
||||
dir->creationTime = FAT_DEFAULT_TIME;
|
||||
}
|
||||
dir->lastAccessDate = dir->creationDate;
|
||||
dir->lastWriteDate = dir->creationDate;
|
||||
dir->lastWriteTime = dir->creationTime;
|
||||
|
||||
// Force write of entry to device.
|
||||
dirFile->m_vol->cacheDirty();
|
||||
|
||||
// open entry in cache.
|
||||
return openCachedEntry(dirFile, index, oflag, 0);
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t FatFile::printName(print_t* pr) {
|
||||
return printSFN(pr);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatFile::remove() {
|
||||
dir_t* dir;
|
||||
// Can't remove if LFN or not open for write.
|
||||
if (!isFile() || isLFN() || !(m_flags & F_WRITE)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Free any clusters.
|
||||
if (m_firstCluster && !m_vol->freeChain(m_firstCluster)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Cache directory entry.
|
||||
dir = cacheDirEntry(FatCache::CACHE_FOR_WRITE);
|
||||
if (!dir) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Mark entry deleted.
|
||||
dir->name[0] = DIR_NAME_DELETED;
|
||||
|
||||
// Set this file closed.
|
||||
m_attr = FILE_ATTR_CLOSED;
|
||||
|
||||
// Write entry to device.
|
||||
return m_vol->cacheSync();
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
#endif // !USE_LONG_FILE_NAMES
|
332
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileSystem.h
Normal file
332
hardware/sd_card_formatter/src/SdFat/FatLib/FatFileSystem.h
Normal file
|
@ -0,0 +1,332 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatFileSystem_h
|
||||
#define FatFileSystem_h
|
||||
#include "FatVolume.h"
|
||||
#include "FatFile.h"
|
||||
#include "ArduinoFiles.h"
|
||||
/**
|
||||
* \file
|
||||
* \brief FatFileSystem class
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class FatFileSystem
|
||||
* \brief Integration class for the FatLib library.
|
||||
*/
|
||||
class FatFileSystem : public FatVolume {
|
||||
public:
|
||||
/**
|
||||
* Initialize an FatFileSystem object.
|
||||
* \param[in] blockDev Device block driver.
|
||||
* \param[in] part partition to initialize.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool begin(BlockDriver* blockDev, uint8_t part = 0) {
|
||||
m_blockDev = blockDev;
|
||||
vwd()->close();
|
||||
return (part ? init(part) : init(1) || init(0))
|
||||
&& vwd()->openRoot(this) && FatFile::setCwd(vwd());
|
||||
}
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
/** List the directory contents of the volume working directory to Serial.
|
||||
*
|
||||
* \param[in] flags The inclusive OR of
|
||||
*
|
||||
* LS_DATE - %Print file modification date
|
||||
*
|
||||
* LS_SIZE - %Print file size.
|
||||
*
|
||||
* LS_R - Recursive list of subdirectories.
|
||||
*
|
||||
* \return true for success or false if an error occurred.
|
||||
*/
|
||||
bool ls(uint8_t flags = 0) {
|
||||
return ls(&Serial, flags);
|
||||
}
|
||||
/** List the directory contents of a directory to Serial.
|
||||
*
|
||||
* \param[in] path directory to list.
|
||||
*
|
||||
* \param[in] flags The inclusive OR of
|
||||
*
|
||||
* LS_DATE - %Print file modification date
|
||||
*
|
||||
* LS_SIZE - %Print file size.
|
||||
*
|
||||
* LS_R - Recursive list of subdirectories.
|
||||
*
|
||||
* \return true for success or false if an error occurred.
|
||||
*/
|
||||
bool ls(const char* path, uint8_t flags = 0) {
|
||||
return ls(&Serial, path, flags);
|
||||
}
|
||||
/** open a file
|
||||
*
|
||||
* \param[in] path location of file to be opened.
|
||||
* \param[in] oflag open flags.
|
||||
* \return a File object.
|
||||
*/
|
||||
File open(const char *path, oflag_t oflag = FILE_READ) {
|
||||
File tmpFile;
|
||||
tmpFile.open(vwd(), path, oflag);
|
||||
return tmpFile;
|
||||
}
|
||||
/** open a file
|
||||
*
|
||||
* \param[in] path location of file to be opened.
|
||||
* \param[in] oflag open flags.
|
||||
* \return a File object.
|
||||
*/
|
||||
File open(const String &path, oflag_t oflag = FILE_READ) {
|
||||
return open(path.c_str(), oflag );
|
||||
}
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
/** Change a volume's working directory to root
|
||||
*
|
||||
* Changes the volume's working directory to the SD's root directory.
|
||||
* Optionally set the current working directory to the volume's
|
||||
* working directory.
|
||||
*
|
||||
* \param[in] set_cwd Set the current working directory to this volume's
|
||||
* working directory if true.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool chdir(bool set_cwd = false) {
|
||||
vwd()->close();
|
||||
return vwd()->openRoot(this) && (set_cwd ? FatFile::setCwd(vwd()) : true);
|
||||
}
|
||||
/** Change a volume's working directory
|
||||
*
|
||||
* Changes the volume working directory to the \a path subdirectory.
|
||||
* Optionally set the current working directory to the volume's
|
||||
* working directory.
|
||||
*
|
||||
* Example: If the volume's working directory is "/DIR", chdir("SUB")
|
||||
* will change the volume's working directory from "/DIR" to "/DIR/SUB".
|
||||
*
|
||||
* If path is "/", the volume's working directory will be changed to the
|
||||
* root directory
|
||||
*
|
||||
* \param[in] path The name of the subdirectory.
|
||||
*
|
||||
* \param[in] set_cwd Set the current working directory to this volume's
|
||||
* working directory if true.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
//----------------------------------------------------------------------------
|
||||
bool chdir(const char *path, bool set_cwd = false) {
|
||||
FatFile dir;
|
||||
if (path[0] == '/' && path[1] == '\0') {
|
||||
return chdir(set_cwd);
|
||||
}
|
||||
if (!dir.open(vwd(), path, O_RDONLY)) {
|
||||
goto fail;
|
||||
}
|
||||
if (!dir.isDir()) {
|
||||
goto fail;
|
||||
}
|
||||
m_vwd = dir;
|
||||
if (set_cwd) {
|
||||
FatFile::setCwd(vwd());
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set the current working directory to a volume's working directory.
|
||||
*
|
||||
* This is useful with multiple SD cards.
|
||||
*
|
||||
* The current working directory is changed to this
|
||||
* volume's working directory.
|
||||
*
|
||||
* This is like the Windows/DOS \<drive letter>: command.
|
||||
*/
|
||||
void chvol() {
|
||||
FatFile::setCwd(vwd());
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Test for the existence of a file.
|
||||
*
|
||||
* \param[in] path Path of the file to be tested for.
|
||||
*
|
||||
* \return true if the file exists else false.
|
||||
*/
|
||||
bool exists(const char* path) {
|
||||
return vwd()->exists(path);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** List the directory contents of the volume working directory.
|
||||
*
|
||||
* \param[in] pr Print stream for list.
|
||||
*
|
||||
* \param[in] flags The inclusive OR of
|
||||
*
|
||||
* LS_DATE - %Print file modification date
|
||||
*
|
||||
* LS_SIZE - %Print file size.
|
||||
*
|
||||
* LS_R - Recursive list of subdirectories.
|
||||
*
|
||||
* \return true for success or false if an error occurred.
|
||||
*/
|
||||
bool ls(print_t* pr, uint8_t flags = 0) {
|
||||
return vwd()->ls(pr, flags);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** List the directory contents of a directory.
|
||||
*
|
||||
* \param[in] pr Print stream for list.
|
||||
*
|
||||
* \param[in] path directory to list.
|
||||
*
|
||||
* \param[in] flags The inclusive OR of
|
||||
*
|
||||
* LS_DATE - %Print file modification date
|
||||
*
|
||||
* LS_SIZE - %Print file size.
|
||||
*
|
||||
* LS_R - Recursive list of subdirectories.
|
||||
*
|
||||
* \return true for success or false if an error occurred.
|
||||
*/
|
||||
bool ls(print_t* pr, const char* path, uint8_t flags) {
|
||||
FatFile dir;
|
||||
return dir.open(vwd(), path, O_RDONLY) && dir.ls(pr, flags);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Make a subdirectory in the volume working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
|
||||
*
|
||||
* \param[in] pFlag Create missing parent directories if true.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool mkdir(const char* path, bool pFlag = true) {
|
||||
FatFile sub;
|
||||
return sub.mkdir(vwd(), path, pFlag);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Remove a file from the volume working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for the file.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool remove(const char* path) {
|
||||
return FatFile::remove(vwd(), path);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Rename a file or subdirectory.
|
||||
*
|
||||
* \param[in] oldPath Path name to the file or subdirectory to be renamed.
|
||||
*
|
||||
* \param[in] newPath New path name of the file or subdirectory.
|
||||
*
|
||||
* The \a newPath object must not exist before the rename call.
|
||||
*
|
||||
* The file to be renamed must not be open. The directory entry may be
|
||||
* moved and file system corruption could occur if the file is accessed by
|
||||
* a file object that was opened before the rename() call.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool rename(const char *oldPath, const char *newPath) {
|
||||
FatFile file;
|
||||
if (!file.open(vwd(), oldPath, O_RDONLY)) {
|
||||
return false;
|
||||
}
|
||||
return file.rename(vwd(), newPath);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Remove a subdirectory from the volume's working directory.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for the subdirectory.
|
||||
*
|
||||
* The subdirectory file will be removed only if it is empty.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool rmdir(const char* path) {
|
||||
FatFile sub;
|
||||
if (!sub.open(vwd(), path, O_RDONLY)) {
|
||||
return false;
|
||||
}
|
||||
return sub.rmdir();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Truncate a file to a specified length. The current file position
|
||||
* will be maintained if it is less than or equal to \a length otherwise
|
||||
* it will be set to end of file.
|
||||
*
|
||||
* \param[in] path A path with a valid 8.3 DOS name for the file.
|
||||
* \param[in] length The desired length for the file.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool truncate(const char* path, uint32_t length) {
|
||||
FatFile file;
|
||||
if (!file.open(vwd(), path, O_WRONLY)) {
|
||||
return false;
|
||||
}
|
||||
return file.truncate(length);
|
||||
}
|
||||
/** \return a pointer to the FatVolume object. */
|
||||
FatVolume* vol() {
|
||||
return this;
|
||||
}
|
||||
/** \return a pointer to the volume working directory. */
|
||||
FatFile* vwd() {
|
||||
return &m_vwd;
|
||||
}
|
||||
/** Wipe all data from the volume. You must reinitialize the volume before
|
||||
* accessing it again.
|
||||
* \param[in] pr print stream for status dots.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool wipe(print_t* pr = 0) {
|
||||
vwd()->close();
|
||||
return FatVolume::wipe(pr);
|
||||
}
|
||||
|
||||
private:
|
||||
FatFile m_vwd;
|
||||
};
|
||||
#endif // FatFileSystem_h
|
36
hardware/sd_card_formatter/src/SdFat/FatLib/FatLib.h
Normal file
36
hardware/sd_card_formatter/src/SdFat/FatLib/FatLib.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatLib_h
|
||||
#define FatLib_h
|
||||
#include "ArduinoFiles.h"
|
||||
#include "FatFileSystem.h"
|
||||
#include "FatLibConfig.h"
|
||||
#include "FatVolume.h"
|
||||
#include "FatFile.h"
|
||||
#include "StdioStream.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** FatFileSystem version YYYYMMDD */
|
||||
#define FAT_LIB_VERSION 20150131
|
||||
#endif // FatLib_h
|
146
hardware/sd_card_formatter/src/SdFat/FatLib/FatLibConfig.h
Normal file
146
hardware/sd_card_formatter/src/SdFat/FatLib/FatLibConfig.h
Normal file
|
@ -0,0 +1,146 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief configuration definitions
|
||||
*/
|
||||
#ifndef FatLibConfig_h
|
||||
#define FatLibConfig_h
|
||||
#include <stdint.h>
|
||||
// Allow this file to override defaults.
|
||||
#include "../SdFatConfig.h"
|
||||
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#endif // __AVR__
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_LONG_FILE_NAMES nonzero to use long file names (LFN).
|
||||
* Long File Name are limited to a maximum length of 255 characters.
|
||||
*
|
||||
* This implementation allows 7-bit characters in the range
|
||||
* 0X20 to 0X7E. The following characters are not allowed:
|
||||
*
|
||||
* < (less than)
|
||||
* > (greater than)
|
||||
* : (colon)
|
||||
* " (double quote)
|
||||
* / (forward slash)
|
||||
* \ (backslash)
|
||||
* | (vertical bar or pipe)
|
||||
* ? (question mark)
|
||||
* * (asterisk)
|
||||
*
|
||||
*/
|
||||
#ifndef USE_LONG_FILE_NAMES
|
||||
#define USE_LONG_FILE_NAMES 1
|
||||
#endif // USE_LONG_FILE_NAMES
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_SEPARATE_FAT_CACHE non-zero to use a second 512 byte cache
|
||||
* for FAT table entries. Improves performance for large writes that
|
||||
* are not a multiple of 512 bytes.
|
||||
*/
|
||||
#ifndef USE_SEPARATE_FAT_CACHE
|
||||
#ifdef __arm__
|
||||
#define USE_SEPARATE_FAT_CACHE 1
|
||||
#else // __arm__
|
||||
#define USE_SEPARATE_FAT_CACHE 0
|
||||
#endif // __arm__
|
||||
#endif // USE_SEPARATE_FAT_CACHE
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_MULTI_BLOCK_IO non-zero to use multi-block SD read/write.
|
||||
*
|
||||
* Don't use mult-block read/write on small AVR boards.
|
||||
*/
|
||||
#ifndef USE_MULTI_BLOCK_IO
|
||||
#if defined(RAMEND) && RAMEND < 3000
|
||||
#define USE_MULTI_BLOCK_IO 0
|
||||
#else // RAMEND
|
||||
#define USE_MULTI_BLOCK_IO 1
|
||||
#endif // RAMEND
|
||||
#endif // USE_MULTI_BLOCK_IO
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set MAINTAIN_FREE_CLUSTER_COUNT nonzero to keep the count of free clusters
|
||||
* updated. This will increase the speed of the freeClusterCount() call
|
||||
* after the first call. Extra flash will be required.
|
||||
*/
|
||||
#ifndef MAINTAIN_FREE_CLUSTER_COUNT
|
||||
#define MAINTAIN_FREE_CLUSTER_COUNT 0
|
||||
#endif // MAINTAIN_FREE_CLUSTER_COUNT
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DESTRUCTOR_CLOSES_FILE non-zero to close a file in its destructor.
|
||||
*
|
||||
* Causes use of lots of heap in ARM.
|
||||
*/
|
||||
#ifndef DESTRUCTOR_CLOSES_FILE
|
||||
#define DESTRUCTOR_CLOSES_FILE 0
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Call flush for endl if ENDL_CALLS_FLUSH is non-zero
|
||||
*
|
||||
* The standard for iostreams is to call flush. This is very costly for
|
||||
* SdFat. Each call to flush causes 2048 bytes of I/O to the SD.
|
||||
*
|
||||
* SdFat has a single 512 byte buffer for I/O so it must write the current
|
||||
* data block to the SD, read the directory block from the SD, update the
|
||||
* directory entry, write the directory block to the SD and read the data
|
||||
* block back into the buffer.
|
||||
*
|
||||
* The SD flash memory controller is not designed for this many rewrites
|
||||
* so performance may be reduced by more than a factor of 100.
|
||||
*
|
||||
* If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
|
||||
* all data to be written to the SD.
|
||||
*/
|
||||
#ifndef ENDL_CALLS_FLUSH
|
||||
#define ENDL_CALLS_FLUSH 0
|
||||
#endif // ENDL_CALLS_FLUSH
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Allow FAT12 volumes if FAT12_SUPPORT is non-zero.
|
||||
* FAT12 has not been well tested.
|
||||
*/
|
||||
#ifndef FAT12_SUPPORT
|
||||
#define FAT12_SUPPORT 0
|
||||
#endif // FAT12_SUPPORT
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Enable Extra features for Arduino.
|
||||
*/
|
||||
// #define ENABLE_ARDUINO_FEATURES 0 ////////////////////////FIX THIS /////////////////
|
||||
#ifndef ENABLE_ARDUINO_FEATURES
|
||||
#include <Arduino.h>
|
||||
#if defined(ARDUINO) || defined(PLATFORM_ID) || defined(DOXYGEN)
|
||||
#define ENABLE_ARDUINO_FEATURES 1
|
||||
#else // #if defined(ARDUINO) || defined(DOXYGEN)
|
||||
#define ENABLE_ARDUINO_FEATURES 0
|
||||
#endif // defined(ARDUINO) || defined(DOXYGEN)
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
#endif // FatLibConfig_h
|
882
hardware/sd_card_formatter/src/SdFat/FatLib/FatStructs.h
Normal file
882
hardware/sd_card_formatter/src/SdFat/FatLib/FatStructs.h
Normal file
|
@ -0,0 +1,882 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatStructs_h
|
||||
#define FatStructs_h
|
||||
/**
|
||||
* \file
|
||||
* \brief FAT file structures
|
||||
*/
|
||||
/*
|
||||
* mostly from Microsoft document fatgen103.doc
|
||||
* http://www.microsoft.com/whdc/system/platform/firmware/fatgen.mspx
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
/** Value for byte 510 of boot block or MBR */
|
||||
const uint8_t BOOTSIG0 = 0X55;
|
||||
/** Value for byte 511 of boot block or MBR */
|
||||
const uint8_t BOOTSIG1 = 0XAA;
|
||||
/** Value for bootSignature field int FAT/FAT32 boot sector */
|
||||
const uint8_t EXTENDED_BOOT_SIG = 0X29;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct partitionTable
|
||||
* \brief MBR partition table entry
|
||||
*
|
||||
* A partition table entry for a MBR formatted storage device.
|
||||
* The MBR partition table has four entries.
|
||||
*/
|
||||
struct partitionTable {
|
||||
/**
|
||||
* Boot Indicator . Indicates whether the volume is the active
|
||||
* partition. Legal values include: 0X00. Do not use for booting.
|
||||
* 0X80 Active partition.
|
||||
*/
|
||||
uint8_t boot;
|
||||
/**
|
||||
* Head part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t beginHead;
|
||||
/**
|
||||
* Sector part of Cylinder-head-sector address of the first block in
|
||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||
*/
|
||||
unsigned beginSector : 6;
|
||||
/** High bits cylinder for first block in partition. */
|
||||
unsigned beginCylinderHigh : 2;
|
||||
/**
|
||||
* Combine beginCylinderLow with beginCylinderHigh. Legal values
|
||||
* are 0-1023. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t beginCylinderLow;
|
||||
/**
|
||||
* Partition type. See defines that begin with PART_TYPE_ for
|
||||
* some Microsoft partition types.
|
||||
*/
|
||||
uint8_t type;
|
||||
/**
|
||||
* head part of cylinder-head-sector address of the last sector in the
|
||||
* partition. Legal values are 0-255. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t endHead;
|
||||
/**
|
||||
* Sector part of cylinder-head-sector address of the last sector in
|
||||
* the partition. Legal values are 1-63. Only used in old PC BIOS.
|
||||
*/
|
||||
unsigned endSector : 6;
|
||||
/** High bits of end cylinder */
|
||||
unsigned endCylinderHigh : 2;
|
||||
/**
|
||||
* Combine endCylinderLow with endCylinderHigh. Legal values
|
||||
* are 0-1023. Only used in old PC BIOS.
|
||||
*/
|
||||
uint8_t endCylinderLow;
|
||||
/** Logical block address of the first block in the partition. */
|
||||
uint32_t firstSector;
|
||||
/** Length of the partition, in blocks. */
|
||||
uint32_t totalSectors;
|
||||
} __attribute__((packed));
|
||||
/** Type name for partitionTable */
|
||||
typedef struct partitionTable part_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct masterBootRecord
|
||||
*
|
||||
* \brief Master Boot Record
|
||||
*
|
||||
* The first block of a storage device that is formatted with a MBR.
|
||||
*/
|
||||
struct masterBootRecord {
|
||||
/** Code Area for master boot program. */
|
||||
uint8_t codeArea[440];
|
||||
/** Optional Windows NT disk signature. May contain boot code. */
|
||||
uint32_t diskSignature;
|
||||
/** Usually zero but may be more boot code. */
|
||||
uint16_t usuallyZero;
|
||||
/** Partition tables. */
|
||||
part_t part[4];
|
||||
/** First MBR signature byte. Must be 0X55 */
|
||||
uint8_t mbrSig0;
|
||||
/** Second MBR signature byte. Must be 0XAA */
|
||||
uint8_t mbrSig1;
|
||||
} __attribute__((packed));
|
||||
/** Type name for masterBootRecord */
|
||||
typedef struct masterBootRecord mbr_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct biosParmBlock
|
||||
*
|
||||
* \brief BIOS parameter block
|
||||
*
|
||||
* The BIOS parameter block describes the physical layout of a FAT volume.
|
||||
*/
|
||||
struct biosParmBlock {
|
||||
/**
|
||||
* Count of bytes per sector. This value may take on only the
|
||||
* following values: 512, 1024, 2048 or 4096
|
||||
*/
|
||||
uint16_t bytesPerSector;
|
||||
/**
|
||||
* Number of sectors per allocation unit. This value must be a
|
||||
* power of 2 that is greater than 0. The legal values are
|
||||
* 1, 2, 4, 8, 16, 32, 64, and 128.
|
||||
*/
|
||||
uint8_t sectorsPerCluster;
|
||||
/**
|
||||
* Number of sectors before the first FAT.
|
||||
* This value must not be zero.
|
||||
*/
|
||||
uint16_t reservedSectorCount;
|
||||
/** The count of FAT data structures on the volume. This field should
|
||||
* always contain the value 2 for any FAT volume of any type.
|
||||
*/
|
||||
uint8_t fatCount;
|
||||
/**
|
||||
* For FAT12 and FAT16 volumes, this field contains the count of
|
||||
* 32-byte directory entries in the root directory. For FAT32 volumes,
|
||||
* this field must be set to 0. For FAT12 and FAT16 volumes, this
|
||||
* value should always specify a count that when multiplied by 32
|
||||
* results in a multiple of bytesPerSector. FAT16 volumes should
|
||||
* use the value 512.
|
||||
*/
|
||||
uint16_t rootDirEntryCount;
|
||||
/**
|
||||
* This field is the old 16-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then totalSectors32
|
||||
* must be nonzero. For FAT32 volumes, this field must be 0. For
|
||||
* FAT12 and FAT16 volumes, this field contains the sector count, and
|
||||
* totalSectors32 is 0 if the total sector count fits
|
||||
* (is less than 0x10000).
|
||||
*/
|
||||
uint16_t totalSectors16;
|
||||
/**
|
||||
* This dates back to the old MS-DOS 1.x media determination and is
|
||||
* no longer usually used for anything. 0xF8 is the standard value
|
||||
* for fixed (nonremovable) media. For removable media, 0xF0 is
|
||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||
*/
|
||||
uint8_t mediaType;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
|
||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||
* contains the FAT size count.
|
||||
*/
|
||||
uint16_t sectorsPerFat16;
|
||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t sectorsPerTrtack;
|
||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t headCount;
|
||||
/**
|
||||
* Count of hidden sectors preceding the partition that contains this
|
||||
* FAT volume. This field is generally only relevant for media
|
||||
* visible on interrupt 0x13.
|
||||
*/
|
||||
uint32_t hidddenSectors;
|
||||
/**
|
||||
* This field is the new 32-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then
|
||||
* totalSectors16 must be nonzero.
|
||||
*/
|
||||
uint32_t totalSectors32;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT32 volumes.
|
||||
*/
|
||||
uint32_t sectorsPerFat32;
|
||||
/**
|
||||
* This field is only defined for FAT32 media and does not exist on
|
||||
* FAT12 and FAT16 media.
|
||||
* Bits 0-3 -- Zero-based number of active FAT.
|
||||
* Only valid if mirroring is disabled.
|
||||
* Bits 4-6 -- Reserved.
|
||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
||||
* -- 1 means only one FAT is active; it is the one referenced in bits 0-3.
|
||||
* Bits 8-15 -- Reserved.
|
||||
*/
|
||||
uint16_t fat32Flags;
|
||||
/**
|
||||
* FAT32 version. High byte is major revision number.
|
||||
* Low byte is minor revision number. Only 0.0 define.
|
||||
*/
|
||||
uint16_t fat32Version;
|
||||
/**
|
||||
* Cluster number of the first cluster of the root directory for FAT32.
|
||||
* This usually 2 but not required to be 2.
|
||||
*/
|
||||
uint32_t fat32RootCluster;
|
||||
/**
|
||||
* Sector number of FSINFO structure in the reserved area of the
|
||||
* FAT32 volume. Usually 1.
|
||||
*/
|
||||
uint16_t fat32FSInfo;
|
||||
/**
|
||||
* If nonzero, indicates the sector number in the reserved area
|
||||
* of the volume of a copy of the boot record. Usually 6.
|
||||
* No value other than 6 is recommended.
|
||||
*/
|
||||
uint16_t fat32BackBootBlock;
|
||||
/**
|
||||
* Reserved for future expansion. Code that formats FAT32 volumes
|
||||
* should always set all of the bytes of this field to 0.
|
||||
*/
|
||||
uint8_t fat32Reserved[12];
|
||||
} __attribute__((packed));
|
||||
/** Type name for biosParmBlock */
|
||||
typedef struct biosParmBlock bpb_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct fat_boot
|
||||
*
|
||||
* \brief Boot sector for a FAT12/FAT16 volume.
|
||||
*
|
||||
*/
|
||||
struct fat_boot {
|
||||
/**
|
||||
* The first three bytes of the boot sector must be valid,
|
||||
* executable x 86-based CPU instructions. This includes a
|
||||
* jump instruction that skips the next non-executable bytes.
|
||||
*/
|
||||
uint8_t jump[3];
|
||||
/**
|
||||
* This is typically a string of characters that identifies
|
||||
* the operating system that formatted the volume.
|
||||
*/
|
||||
char oemId[8];
|
||||
/**
|
||||
* The size of a hardware sector. Valid decimal values for this
|
||||
* field are 512, 1024, 2048, and 4096. For most disks used in
|
||||
* the United States, the value of this field is 512.
|
||||
*/
|
||||
uint16_t bytesPerSector;
|
||||
/**
|
||||
* Number of sectors per allocation unit. This value must be a
|
||||
* power of 2 that is greater than 0. The legal values are
|
||||
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
||||
*/
|
||||
uint8_t sectorsPerCluster;
|
||||
/**
|
||||
* The number of sectors preceding the start of the first FAT,
|
||||
* including the boot sector. The value of this field is always 1.
|
||||
*/
|
||||
uint16_t reservedSectorCount;
|
||||
/**
|
||||
* The number of copies of the FAT on the volume.
|
||||
* The value of this field is always 2.
|
||||
*/
|
||||
uint8_t fatCount;
|
||||
/**
|
||||
* For FAT12 and FAT16 volumes, this field contains the count of
|
||||
* 32-byte directory entries in the root directory. For FAT32 volumes,
|
||||
* this field must be set to 0. For FAT12 and FAT16 volumes, this
|
||||
* value should always specify a count that when multiplied by 32
|
||||
* results in a multiple of bytesPerSector. FAT16 volumes should
|
||||
* use the value 512.
|
||||
*/
|
||||
uint16_t rootDirEntryCount;
|
||||
/**
|
||||
* This field is the old 16-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then totalSectors32
|
||||
* must be non-zero. For FAT32 volumes, this field must be 0. For
|
||||
* FAT12 and FAT16 volumes, this field contains the sector count, and
|
||||
* totalSectors32 is 0 if the total sector count fits
|
||||
* (is less than 0x10000).
|
||||
*/
|
||||
uint16_t totalSectors16;
|
||||
/**
|
||||
* This dates back to the old MS-DOS 1.x media determination and is
|
||||
* no longer usually used for anything. 0xF8 is the standard value
|
||||
* for fixed (non-removable) media. For removable media, 0xF0 is
|
||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||
*/
|
||||
uint8_t mediaType;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT12/FAT16 volumes.
|
||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||
* contains the FAT size count.
|
||||
*/
|
||||
uint16_t sectorsPerFat16;
|
||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t sectorsPerTrack;
|
||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t headCount;
|
||||
/**
|
||||
* Count of hidden sectors preceding the partition that contains this
|
||||
* FAT volume. This field is generally only relevant for media
|
||||
* visible on interrupt 0x13.
|
||||
*/
|
||||
uint32_t hidddenSectors;
|
||||
/**
|
||||
* This field is the new 32-bit total count of sectors on the volume.
|
||||
* This count includes the count of all sectors in all four regions
|
||||
* of the volume. This field can be 0; if it is 0, then
|
||||
* totalSectors16 must be non-zero.
|
||||
*/
|
||||
uint32_t totalSectors32;
|
||||
/**
|
||||
* Related to the BIOS physical drive number. Floppy drives are
|
||||
* identified as 0x00 and physical hard disks are identified as
|
||||
* 0x80, regardless of the number of physical disk drives.
|
||||
* Typically, this value is set prior to issuing an INT 13h BIOS
|
||||
* call to specify the device to access. The value is only
|
||||
* relevant if the device is a boot device.
|
||||
*/
|
||||
uint8_t driveNumber;
|
||||
/** used by Windows NT - should be zero for FAT */
|
||||
uint8_t reserved1;
|
||||
/** 0X29 if next three fields are valid */
|
||||
uint8_t bootSignature;
|
||||
/**
|
||||
* A random serial number created when formatting a disk,
|
||||
* which helps to distinguish between disks.
|
||||
* Usually generated by combining date and time.
|
||||
*/
|
||||
uint32_t volumeSerialNumber;
|
||||
/**
|
||||
* A field once used to store the volume label. The volume label
|
||||
* is now stored as a special file in the root directory.
|
||||
*/
|
||||
char volumeLabel[11];
|
||||
/**
|
||||
* A field with a value of either FAT, FAT12 or FAT16,
|
||||
* depending on the disk format.
|
||||
*/
|
||||
char fileSystemType[8];
|
||||
/** X86 boot code */
|
||||
uint8_t bootCode[448];
|
||||
/** must be 0X55 */
|
||||
uint8_t bootSectorSig0;
|
||||
/** must be 0XAA */
|
||||
uint8_t bootSectorSig1;
|
||||
} __attribute__((packed));
|
||||
/** Type name for FAT Boot Sector */
|
||||
typedef struct fat_boot fat_boot_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct fat32_boot
|
||||
*
|
||||
* \brief Boot sector for a FAT32 volume.
|
||||
*
|
||||
*/
|
||||
struct fat32_boot {
|
||||
/**
|
||||
* The first three bytes of the boot sector must be valid,
|
||||
* executable x 86-based CPU instructions. This includes a
|
||||
* jump instruction that skips the next non-executable bytes.
|
||||
*/
|
||||
uint8_t jump[3];
|
||||
/**
|
||||
* This is typically a string of characters that identifies
|
||||
* the operating system that formatted the volume.
|
||||
*/
|
||||
char oemId[8];
|
||||
/**
|
||||
* The size of a hardware sector. Valid decimal values for this
|
||||
* field are 512, 1024, 2048, and 4096. For most disks used in
|
||||
* the United States, the value of this field is 512.
|
||||
*/
|
||||
uint16_t bytesPerSector;
|
||||
/**
|
||||
* Number of sectors per allocation unit. This value must be a
|
||||
* power of 2 that is greater than 0. The legal values are
|
||||
* 1, 2, 4, 8, 16, 32, 64, and 128. 128 should be avoided.
|
||||
*/
|
||||
uint8_t sectorsPerCluster;
|
||||
/**
|
||||
* The number of sectors preceding the start of the first FAT,
|
||||
* including the boot sector. Must not be zero
|
||||
*/
|
||||
uint16_t reservedSectorCount;
|
||||
/**
|
||||
* The number of copies of the FAT on the volume.
|
||||
* The value of this field is always 2.
|
||||
*/
|
||||
uint8_t fatCount;
|
||||
/**
|
||||
* FAT12/FAT16 only. For FAT32 volumes, this field must be set to 0.
|
||||
*/
|
||||
uint16_t rootDirEntryCount;
|
||||
/**
|
||||
* For FAT32 volumes, this field must be 0.
|
||||
*/
|
||||
uint16_t totalSectors16;
|
||||
/**
|
||||
* This dates back to the old MS-DOS 1.x media determination and is
|
||||
* no longer usually used for anything. 0xF8 is the standard value
|
||||
* for fixed (non-removable) media. For removable media, 0xF0 is
|
||||
* frequently used. Legal values are 0xF0 or 0xF8-0xFF.
|
||||
*/
|
||||
uint8_t mediaType;
|
||||
/**
|
||||
* On FAT32 volumes this field must be 0, and sectorsPerFat32
|
||||
* contains the FAT size count.
|
||||
*/
|
||||
uint16_t sectorsPerFat16;
|
||||
/** Sectors per track for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t sectorsPerTrack;
|
||||
/** Number of heads for interrupt 0x13. Not used otherwise. */
|
||||
uint16_t headCount;
|
||||
/**
|
||||
* Count of hidden sectors preceding the partition that contains this
|
||||
* FAT volume. This field is generally only relevant for media
|
||||
* visible on interrupt 0x13.
|
||||
*/
|
||||
uint32_t hidddenSectors;
|
||||
/**
|
||||
* Contains the total number of sectors in the FAT32 volume.
|
||||
*/
|
||||
uint32_t totalSectors32;
|
||||
/**
|
||||
* Count of sectors occupied by one FAT on FAT32 volumes.
|
||||
*/
|
||||
uint32_t sectorsPerFat32;
|
||||
/**
|
||||
* This field is only defined for FAT32 media and does not exist on
|
||||
* FAT12 and FAT16 media.
|
||||
* Bits 0-3 -- Zero-based number of active FAT.
|
||||
* Only valid if mirroring is disabled.
|
||||
* Bits 4-6 -- Reserved.
|
||||
* Bit 7 -- 0 means the FAT is mirrored at runtime into all FATs.
|
||||
* -- 1 means only one FAT is active; it is the one referenced
|
||||
* in bits 0-3.
|
||||
* Bits 8-15 -- Reserved.
|
||||
*/
|
||||
uint16_t fat32Flags;
|
||||
/**
|
||||
* FAT32 version. High byte is major revision number.
|
||||
* Low byte is minor revision number. Only 0.0 define.
|
||||
*/
|
||||
uint16_t fat32Version;
|
||||
/**
|
||||
* Cluster number of the first cluster of the root directory for FAT32.
|
||||
* This usually 2 but not required to be 2.
|
||||
*/
|
||||
uint32_t fat32RootCluster;
|
||||
/**
|
||||
* Sector number of FSINFO structure in the reserved area of the
|
||||
* FAT32 volume. Usually 1.
|
||||
*/
|
||||
uint16_t fat32FSInfo;
|
||||
/**
|
||||
* If non-zero, indicates the sector number in the reserved area
|
||||
* of the volume of a copy of the boot record. Usually 6.
|
||||
* No value other than 6 is recommended.
|
||||
*/
|
||||
uint16_t fat32BackBootBlock;
|
||||
/**
|
||||
* Reserved for future expansion. Code that formats FAT32 volumes
|
||||
* should always set all of the bytes of this field to 0.
|
||||
*/
|
||||
uint8_t fat32Reserved[12];
|
||||
/**
|
||||
* Related to the BIOS physical drive number. Floppy drives are
|
||||
* identified as 0x00 and physical hard disks are identified as
|
||||
* 0x80, regardless of the number of physical disk drives.
|
||||
* Typically, this value is set prior to issuing an INT 13h BIOS
|
||||
* call to specify the device to access. The value is only
|
||||
* relevant if the device is a boot device.
|
||||
*/
|
||||
uint8_t driveNumber;
|
||||
/** used by Windows NT - should be zero for FAT */
|
||||
uint8_t reserved1;
|
||||
/** 0X29 if next three fields are valid */
|
||||
uint8_t bootSignature;
|
||||
/**
|
||||
* A random serial number created when formatting a disk,
|
||||
* which helps to distinguish between disks.
|
||||
* Usually generated by combining date and time.
|
||||
*/
|
||||
uint32_t volumeSerialNumber;
|
||||
/**
|
||||
* A field once used to store the volume label. The volume label
|
||||
* is now stored as a special file in the root directory.
|
||||
*/
|
||||
char volumeLabel[11];
|
||||
/**
|
||||
* A text field with a value of FAT32.
|
||||
*/
|
||||
char fileSystemType[8];
|
||||
/** X86 boot code */
|
||||
uint8_t bootCode[420];
|
||||
/** must be 0X55 */
|
||||
uint8_t bootSectorSig0;
|
||||
/** must be 0XAA */
|
||||
uint8_t bootSectorSig1;
|
||||
} __attribute__((packed));
|
||||
/** Type name for FAT32 Boot Sector */
|
||||
typedef struct fat32_boot fat32_boot_t;
|
||||
//------------------------------------------------------------------------------
|
||||
/** Lead signature for a FSINFO sector */
|
||||
const uint32_t FSINFO_LEAD_SIG = 0x41615252;
|
||||
/** Struct signature for a FSINFO sector */
|
||||
const uint32_t FSINFO_STRUCT_SIG = 0x61417272;
|
||||
/**
|
||||
* \struct fat32_fsinfo
|
||||
*
|
||||
* \brief FSINFO sector for a FAT32 volume.
|
||||
*
|
||||
*/
|
||||
struct fat32_fsinfo {
|
||||
/** must be 0X52, 0X52, 0X61, 0X41 */
|
||||
uint32_t leadSignature;
|
||||
/** must be zero */
|
||||
uint8_t reserved1[480];
|
||||
/** must be 0X72, 0X72, 0X41, 0X61 */
|
||||
uint32_t structSignature;
|
||||
/**
|
||||
* Contains the last known free cluster count on the volume.
|
||||
* If the value is 0xFFFFFFFF, then the free count is unknown
|
||||
* and must be computed. Any other value can be used, but is
|
||||
* not necessarily correct. It should be range checked at least
|
||||
* to make sure it is <= volume cluster count.
|
||||
*/
|
||||
uint32_t freeCount;
|
||||
/**
|
||||
* This is a hint for the FAT driver. It indicates the cluster
|
||||
* number at which the driver should start looking for free clusters.
|
||||
* If the value is 0xFFFFFFFF, then there is no hint and the driver
|
||||
* should start looking at cluster 2.
|
||||
*/
|
||||
uint32_t nextFree;
|
||||
/** must be zero */
|
||||
uint8_t reserved2[12];
|
||||
/** must be 0X00, 0X00, 0X55, 0XAA */
|
||||
uint8_t tailSignature[4];
|
||||
} __attribute__((packed));
|
||||
/** Type name for FAT32 FSINFO Sector */
|
||||
typedef struct fat32_fsinfo fat32_fsinfo_t;
|
||||
//------------------------------------------------------------------------------
|
||||
// End Of Chain values for FAT entries
|
||||
/** FAT12 end of chain value used by Microsoft. */
|
||||
const uint16_t FAT12EOC = 0XFFF;
|
||||
/** Minimum value for FAT12 EOC. Use to test for EOC. */
|
||||
const uint16_t FAT12EOC_MIN = 0XFF8;
|
||||
/** FAT16 end of chain value used by Microsoft. */
|
||||
const uint16_t FAT16EOC = 0XFFFF;
|
||||
/** Minimum value for FAT16 EOC. Use to test for EOC. */
|
||||
const uint16_t FAT16EOC_MIN = 0XFFF8;
|
||||
/** FAT32 end of chain value used by Microsoft. */
|
||||
const uint32_t FAT32EOC = 0X0FFFFFFF;
|
||||
/** Minimum value for FAT32 EOC. Use to test for EOC. */
|
||||
const uint32_t FAT32EOC_MIN = 0X0FFFFFF8;
|
||||
/** Mask a for FAT32 entry. Entries are 28 bits. */
|
||||
const uint32_t FAT32MASK = 0X0FFFFFFF;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \struct directoryEntry
|
||||
* \brief FAT short directory entry
|
||||
*
|
||||
* Short means short 8.3 name, not the entry size.
|
||||
*
|
||||
* Date Format. A FAT directory entry date stamp is a 16-bit field that is
|
||||
* basically a date relative to the MS-DOS epoch of 01/01/1980. Here is the
|
||||
* format (bit 0 is the LSB of the 16-bit word, bit 15 is the MSB of the
|
||||
* 16-bit word):
|
||||
*
|
||||
* Bits 9-15: Count of years from 1980, valid value range 0-127
|
||||
* inclusive (1980-2107).
|
||||
*
|
||||
* Bits 5-8: Month of year, 1 = January, valid value range 1-12 inclusive.
|
||||
*
|
||||
* Bits 0-4: Day of month, valid value range 1-31 inclusive.
|
||||
*
|
||||
* Time Format. A FAT directory entry time stamp is a 16-bit field that has
|
||||
* a granularity of 2 seconds. Here is the format (bit 0 is the LSB of the
|
||||
* 16-bit word, bit 15 is the MSB of the 16-bit word).
|
||||
*
|
||||
* Bits 11-15: Hours, valid value range 0-23 inclusive.
|
||||
*
|
||||
* Bits 5-10: Minutes, valid value range 0-59 inclusive.
|
||||
*
|
||||
* Bits 0-4: 2-second count, valid value range 0-29 inclusive (0 - 58 seconds).
|
||||
*
|
||||
* The valid time range is from Midnight 00:00:00 to 23:59:58.
|
||||
*/
|
||||
struct directoryEntry {
|
||||
/** Short 8.3 name.
|
||||
*
|
||||
* The first eight bytes contain the file name with blank fill.
|
||||
* The last three bytes contain the file extension with blank fill.
|
||||
*/
|
||||
uint8_t name[11];
|
||||
/** Entry attributes.
|
||||
*
|
||||
* The upper two bits of the attribute byte are reserved and should
|
||||
* always be set to 0 when a file is created and never modified or
|
||||
* looked at after that. See defines that begin with DIR_ATT_.
|
||||
*/
|
||||
uint8_t attributes;
|
||||
/**
|
||||
* Reserved for use by Windows NT. Set value to 0 when a file is
|
||||
* created and never modify or look at it after that.
|
||||
*/
|
||||
uint8_t reservedNT;
|
||||
/**
|
||||
* The granularity of the seconds part of creationTime is 2 seconds
|
||||
* so this field is a count of tenths of a second and its valid
|
||||
* value range is 0-199 inclusive. (WHG note - seems to be hundredths)
|
||||
*/
|
||||
uint8_t creationTimeTenths;
|
||||
/** Time file was created. */
|
||||
uint16_t creationTime;
|
||||
/** Date file was created. */
|
||||
uint16_t creationDate;
|
||||
/**
|
||||
* Last access date. Note that there is no last access time, only
|
||||
* a date. This is the date of last read or write. In the case of
|
||||
* a write, this should be set to the same date as lastWriteDate.
|
||||
*/
|
||||
uint16_t lastAccessDate;
|
||||
/**
|
||||
* High word of this entry's first cluster number (always 0 for a
|
||||
* FAT12 or FAT16 volume).
|
||||
*/
|
||||
uint16_t firstClusterHigh;
|
||||
/** Time of last write. File creation is considered a write. */
|
||||
uint16_t lastWriteTime;
|
||||
/** Date of last write. File creation is considered a write. */
|
||||
uint16_t lastWriteDate;
|
||||
/** Low word of this entry's first cluster number. */
|
||||
uint16_t firstClusterLow;
|
||||
/** 32-bit unsigned holding this file's size in bytes. */
|
||||
uint32_t fileSize;
|
||||
} __attribute__((packed));
|
||||
/** Type name for directoryEntry */
|
||||
typedef struct directoryEntry dir_t;
|
||||
//------------------------------------------------------------------------------
|
||||
// Definitions for directory entries
|
||||
//
|
||||
/** escape for name[0] = 0XE5 */
|
||||
const uint8_t DIR_NAME_0XE5 = 0X05;
|
||||
/** name[0] value for entry that is free after being "deleted" */
|
||||
const uint8_t DIR_NAME_DELETED = 0XE5;
|
||||
/** name[0] value for entry that is free and no allocated entries follow */
|
||||
const uint8_t DIR_NAME_FREE = 0X00;
|
||||
/** file is read-only */
|
||||
const uint8_t DIR_ATT_READ_ONLY = 0X01;
|
||||
/** File should e hidden in directory listings */
|
||||
const uint8_t DIR_ATT_HIDDEN = 0X02;
|
||||
/** Entry is for a system file */
|
||||
const uint8_t DIR_ATT_SYSTEM = 0X04;
|
||||
/** Directory entry contains the volume label */
|
||||
const uint8_t DIR_ATT_VOLUME_ID = 0X08;
|
||||
/** Entry is for a directory */
|
||||
const uint8_t DIR_ATT_DIRECTORY = 0X10;
|
||||
/** Old DOS archive bit for backup support */
|
||||
const uint8_t DIR_ATT_ARCHIVE = 0X20;
|
||||
/** Test value for long name entry. Test is
|
||||
(d->attributes & DIR_ATT_LONG_NAME_MASK) == DIR_ATT_LONG_NAME. */
|
||||
const uint8_t DIR_ATT_LONG_NAME = 0X0F;
|
||||
/** Test mask for long name entry */
|
||||
const uint8_t DIR_ATT_LONG_NAME_MASK = 0X3F;
|
||||
/** defined attribute bits */
|
||||
const uint8_t DIR_ATT_DEFINED_BITS = 0X3F;
|
||||
|
||||
/** Mask for file/subdirectory tests */
|
||||
const uint8_t DIR_ATT_FILE_TYPE_MASK = (DIR_ATT_VOLUME_ID | DIR_ATT_DIRECTORY);
|
||||
|
||||
/** Filename base-name is all lower case */
|
||||
const uint8_t DIR_NT_LC_BASE = 0X08;
|
||||
/** Filename extension is all lower case.*/
|
||||
const uint8_t DIR_NT_LC_EXT = 0X10;
|
||||
|
||||
|
||||
/** Directory entry is for a file
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is for a normal file else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_FILE(const dir_t* dir) {
|
||||
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == 0;
|
||||
}
|
||||
/** Directory entry is for a file or subdirectory
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is for a normal file or subdirectory else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_FILE_OR_SUBDIR(const dir_t* dir) {
|
||||
return (dir->attributes & DIR_ATT_VOLUME_ID) == 0;
|
||||
}
|
||||
/** Directory entry is part of a long name
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is for part of a long name else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_LONG_NAME(const dir_t* dir) {
|
||||
return dir->attributes == DIR_ATT_LONG_NAME;
|
||||
}
|
||||
/** Directory entry is hidden
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is hidden else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_HIDDEN(const dir_t* dir) {
|
||||
return dir->attributes & DIR_ATT_HIDDEN;
|
||||
}
|
||||
/** Directory entry is for a subdirectory
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is for a subdirectory else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_SUBDIR(const dir_t* dir) {
|
||||
return (dir->attributes & DIR_ATT_FILE_TYPE_MASK) == DIR_ATT_DIRECTORY;
|
||||
}
|
||||
/** Directory entry is system type
|
||||
* \param[in] dir Pointer to a directory entry.
|
||||
*
|
||||
* \return true if the entry is system else false.
|
||||
*/
|
||||
static inline uint8_t DIR_IS_SYSTEM(const dir_t* dir) {
|
||||
return dir->attributes & DIR_ATT_SYSTEM;
|
||||
}
|
||||
/** date field for FAT directory entry
|
||||
* \param[in] year [1980,2107]
|
||||
* \param[in] month [1,12]
|
||||
* \param[in] day [1,31]
|
||||
*
|
||||
* \return Packed date for dir_t entry.
|
||||
*/
|
||||
static inline uint16_t FAT_DATE(uint16_t year, uint8_t month, uint8_t day) {
|
||||
return (year - 1980) << 9 | month << 5 | day;
|
||||
}
|
||||
/** year part of FAT directory date field
|
||||
* \param[in] fatDate Date in packed dir format.
|
||||
*
|
||||
* \return Extracted year [1980,2107]
|
||||
*/
|
||||
static inline uint16_t FAT_YEAR(uint16_t fatDate) {
|
||||
return 1980 + (fatDate >> 9);
|
||||
}
|
||||
/** month part of FAT directory date field
|
||||
* \param[in] fatDate Date in packed dir format.
|
||||
*
|
||||
* \return Extracted month [1,12]
|
||||
*/
|
||||
static inline uint8_t FAT_MONTH(uint16_t fatDate) {
|
||||
return (fatDate >> 5) & 0XF;
|
||||
}
|
||||
/** day part of FAT directory date field
|
||||
* \param[in] fatDate Date in packed dir format.
|
||||
*
|
||||
* \return Extracted day [1,31]
|
||||
*/
|
||||
static inline uint8_t FAT_DAY(uint16_t fatDate) {
|
||||
return fatDate & 0X1F;
|
||||
}
|
||||
/** time field for FAT directory entry
|
||||
* \param[in] hour [0,23]
|
||||
* \param[in] minute [0,59]
|
||||
* \param[in] second [0,59]
|
||||
*
|
||||
* \return Packed time for dir_t entry.
|
||||
*/
|
||||
static inline uint16_t FAT_TIME(uint8_t hour, uint8_t minute, uint8_t second) {
|
||||
return hour << 11 | minute << 5 | second >> 1;
|
||||
}
|
||||
/** hour part of FAT directory time field
|
||||
* \param[in] fatTime Time in packed dir format.
|
||||
*
|
||||
* \return Extracted hour [0,23]
|
||||
*/
|
||||
static inline uint8_t FAT_HOUR(uint16_t fatTime) {
|
||||
return fatTime >> 11;
|
||||
}
|
||||
/** minute part of FAT directory time field
|
||||
* \param[in] fatTime Time in packed dir format.
|
||||
*
|
||||
* \return Extracted minute [0,59]
|
||||
*/
|
||||
static inline uint8_t FAT_MINUTE(uint16_t fatTime) {
|
||||
return (fatTime >> 5) & 0X3F;
|
||||
}
|
||||
/** second part of FAT directory time field
|
||||
* \note second/2 is stored in packed time.
|
||||
*
|
||||
* \param[in] fatTime Time in packed dir format.
|
||||
*
|
||||
* \return Extracted second [0,58]
|
||||
*/
|
||||
static inline uint8_t FAT_SECOND(uint16_t fatTime) {
|
||||
return 2*(fatTime & 0X1F);
|
||||
}
|
||||
/** Default date for file timestamps is 1 Jan 2000 */
|
||||
const uint16_t FAT_DEFAULT_DATE = ((2000 - 1980) << 9) | (1 << 5) | 1;
|
||||
/** Default time for file timestamp is 1 am */
|
||||
const uint16_t FAT_DEFAULT_TIME = (1 << 11);
|
||||
//------------------------------------------------------------------------------
|
||||
/** Dimension of first name field in long directory entry */
|
||||
const uint8_t LDIR_NAME1_DIM = 5;
|
||||
/** Dimension of first name field in long directory entry */
|
||||
const uint8_t LDIR_NAME2_DIM = 6;
|
||||
/** Dimension of first name field in long directory entry */
|
||||
const uint8_t LDIR_NAME3_DIM = 2;
|
||||
/**
|
||||
* \struct longDirectoryEntry
|
||||
* \brief FAT long directory entry
|
||||
*/
|
||||
struct longDirectoryEntry {
|
||||
/**
|
||||
* The order of this entry in the sequence of long dir entries
|
||||
* associated with the short dir entry at the end of the long dir set.
|
||||
*
|
||||
* If masked with 0X40 (LAST_LONG_ENTRY), this indicates the
|
||||
* entry is the last long dir entry in a set of long dir entries.
|
||||
* All valid sets of long dir entries must begin with an entry having
|
||||
* this mask.
|
||||
*/
|
||||
uint8_t ord;
|
||||
/** Characters 1-5 of the long-name sub-component in this entry. */
|
||||
uint16_t name1[LDIR_NAME1_DIM];
|
||||
/** Attributes - must be ATTR_LONG_NAME */
|
||||
uint8_t attr;
|
||||
/**
|
||||
* If zero, indicates a directory entry that is a sub-component of a
|
||||
* long name. NOTE: Other values reserved for future extensions.
|
||||
*
|
||||
* Non-zero implies other directory entry types.
|
||||
*/
|
||||
uint8_t type;
|
||||
/**
|
||||
* Checksum of name in the short dir entry at the end of the
|
||||
* long dir set.
|
||||
*/
|
||||
uint8_t chksum;
|
||||
/** Characters 6-11 of the long-name sub-component in this entry. */
|
||||
uint16_t name2[LDIR_NAME2_DIM];
|
||||
/** Must be ZERO. This is an artifact of the FAT "first cluster" */
|
||||
uint16_t mustBeZero;
|
||||
/** Characters 12 and 13 of the long-name sub-component in this entry. */
|
||||
uint16_t name3[LDIR_NAME3_DIM];
|
||||
} __attribute__((packed));
|
||||
/** Type name for longDirectoryEntry */
|
||||
typedef struct longDirectoryEntry ldir_t;
|
||||
/**
|
||||
* Ord mast that indicates the entry is the last long dir entry in a
|
||||
* set of long dir entries. All valid sets of long dir entries must
|
||||
* begin with an entry having this mask.
|
||||
*/
|
||||
const uint8_t LDIR_ORD_LAST_LONG_ENTRY = 0X40;
|
||||
#endif // FatStructs_h
|
625
hardware/sd_card_formatter/src/SdFat/FatLib/FatVolume.cpp
Normal file
625
hardware/sd_card_formatter/src/SdFat/FatLib/FatVolume.cpp
Normal file
|
@ -0,0 +1,625 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "FatVolume.h"
|
||||
//------------------------------------------------------------------------------
|
||||
cache_t* FatCache::read(uint32_t lbn, uint8_t option) {
|
||||
if (m_lbn != lbn) {
|
||||
if (!sync()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!(option & CACHE_OPTION_NO_READ)) {
|
||||
if (!m_vol->readBlock(lbn, m_block.data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_status = 0;
|
||||
m_lbn = lbn;
|
||||
}
|
||||
m_status |= option & CACHE_STATUS_MASK;
|
||||
return &m_block;
|
||||
|
||||
fail:
|
||||
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatCache::sync() {
|
||||
if (m_status & CACHE_STATUS_DIRTY) {
|
||||
if (!m_vol->writeBlock(m_lbn, m_block.data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// mirror second FAT
|
||||
if (m_status & CACHE_STATUS_MIRROR_FAT) {
|
||||
uint32_t lbn = m_lbn + m_vol->blocksPerFat();
|
||||
if (!m_vol->writeBlock(lbn, m_block.data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_status &= ~CACHE_STATUS_DIRTY;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatVolume::allocateCluster(uint32_t current, uint32_t* next) {
|
||||
uint32_t find;
|
||||
bool setStart;
|
||||
if (m_allocSearchStart < current) {
|
||||
// Try to keep file contiguous. Start just after current cluster.
|
||||
find = current;
|
||||
setStart = false;
|
||||
} else {
|
||||
find = m_allocSearchStart;
|
||||
setStart = true;
|
||||
}
|
||||
while (1) {
|
||||
find++;
|
||||
if (find > m_lastCluster) {
|
||||
if (setStart) {
|
||||
// Can't find space, checked all clusters.
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
find = m_allocSearchStart;
|
||||
setStart = true;
|
||||
continue;
|
||||
}
|
||||
if (find == current) {
|
||||
// Can't find space, already searched clusters after current.
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
uint32_t f;
|
||||
int8_t fg = fatGet(find, &f);
|
||||
if (fg < 0) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (fg && f == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (setStart) {
|
||||
m_allocSearchStart = find;
|
||||
}
|
||||
// Mark end of chain.
|
||||
if (!fatPutEOC(find)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (current) {
|
||||
// Link clusters.
|
||||
if (!fatPut(current, find)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
updateFreeClusterCount(-1);
|
||||
*next = find;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// find a contiguous group of clusters
|
||||
bool FatVolume::allocContiguous(uint32_t count,
|
||||
uint32_t* firstCluster, uint32_t startCluster) {
|
||||
// flag to save place to start next search
|
||||
bool setStart;
|
||||
// start of group
|
||||
uint32_t bgnCluster;
|
||||
// end of group
|
||||
uint32_t endCluster;
|
||||
if (startCluster != 0) {
|
||||
bgnCluster = startCluster;
|
||||
setStart = false;
|
||||
} else {
|
||||
// Start at cluster after last allocated cluster.
|
||||
bgnCluster = m_allocSearchStart + 1;
|
||||
setStart = true;
|
||||
}
|
||||
endCluster = bgnCluster;
|
||||
// search the FAT for free clusters
|
||||
while (1) {
|
||||
if (endCluster > m_lastCluster) {
|
||||
// Can't find space.
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
uint32_t f;
|
||||
int8_t fg = fatGet(endCluster, &f);
|
||||
if (fg < 0) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (f || fg == 0) {
|
||||
if (startCluster) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// don't update search start if unallocated clusters before endCluster.
|
||||
if (bgnCluster != endCluster) {
|
||||
setStart = false;
|
||||
}
|
||||
// cluster in use try next cluster as bgnCluster
|
||||
bgnCluster = endCluster + 1;
|
||||
} else if ((endCluster - bgnCluster + 1) == count) {
|
||||
// done - found space
|
||||
break;
|
||||
}
|
||||
endCluster++;
|
||||
}
|
||||
// Remember possible next free cluster.
|
||||
if (setStart) {
|
||||
m_allocSearchStart = endCluster;
|
||||
}
|
||||
// mark end of chain
|
||||
if (!fatPutEOC(endCluster)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// link clusters
|
||||
while (endCluster > bgnCluster) {
|
||||
if (!fatPut(endCluster - 1, endCluster)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
endCluster--;
|
||||
}
|
||||
// Maintain count of free clusters.
|
||||
updateFreeClusterCount(-count);
|
||||
|
||||
// return first cluster number to caller
|
||||
*firstCluster = bgnCluster;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t FatVolume::clusterFirstBlock(uint32_t cluster) const {
|
||||
return m_dataStartBlock + ((cluster - 2) << m_clusterSizeShift);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Fetch a FAT entry - return -1 error, 0 EOC, else 1.
|
||||
int8_t FatVolume::fatGet(uint32_t cluster, uint32_t* value) {
|
||||
uint32_t lba;
|
||||
uint32_t next;
|
||||
cache_t* pc;
|
||||
|
||||
// error if reserved cluster of beyond FAT
|
||||
if (cluster < 2 || cluster > m_lastCluster) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fatType() == 32) {
|
||||
lba = m_fatStartBlock + (cluster >> 7);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
next = pc->fat32[cluster & 0X7F] & FAT32MASK;
|
||||
goto done;
|
||||
}
|
||||
if (fatType() == 16) {
|
||||
lba = m_fatStartBlock + ((cluster >> 8) & 0XFF);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
next = pc->fat16[cluster & 0XFF];
|
||||
goto done;
|
||||
}
|
||||
if (FAT12_SUPPORT && fatType() == 12) {
|
||||
uint16_t index = cluster;
|
||||
index += index >> 1;
|
||||
lba = m_fatStartBlock + (index >> 9);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
index &= 0X1FF;
|
||||
uint16_t tmp = pc->data[index];
|
||||
index++;
|
||||
if (index == 512) {
|
||||
pc = cacheFetchFat(lba + 1, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
index = 0;
|
||||
}
|
||||
tmp |= pc->data[index] << 8;
|
||||
next = cluster & 1 ? tmp >> 4 : tmp & 0XFFF;
|
||||
goto done;
|
||||
} else {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
done:
|
||||
if (isEOC(next)) {
|
||||
return 0;
|
||||
}
|
||||
*value = next;
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Store a FAT entry
|
||||
bool FatVolume::fatPut(uint32_t cluster, uint32_t value) {
|
||||
uint32_t lba;
|
||||
cache_t* pc;
|
||||
|
||||
// error if reserved cluster of beyond FAT
|
||||
if (cluster < 2 || cluster > m_lastCluster) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (fatType() == 32) {
|
||||
lba = m_fatStartBlock + (cluster >> 7);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
pc->fat32[cluster & 0X7F] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (fatType() == 16) {
|
||||
lba = m_fatStartBlock + ((cluster >> 8) & 0XFF);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
pc->fat16[cluster & 0XFF] = value;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (FAT12_SUPPORT && fatType() == 12) {
|
||||
uint16_t index = cluster;
|
||||
index += index >> 1;
|
||||
lba = m_fatStartBlock + (index >> 9);
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
index &= 0X1FF;
|
||||
uint8_t tmp = value;
|
||||
if (cluster & 1) {
|
||||
tmp = (pc->data[index] & 0XF) | tmp << 4;
|
||||
}
|
||||
pc->data[index] = tmp;
|
||||
|
||||
index++;
|
||||
if (index == 512) {
|
||||
lba++;
|
||||
index = 0;
|
||||
pc = cacheFetchFat(lba, FatCache::CACHE_FOR_WRITE);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
tmp = value >> 4;
|
||||
if (!(cluster & 1)) {
|
||||
tmp = ((pc->data[index] & 0XF0)) | tmp >> 4;
|
||||
}
|
||||
pc->data[index] = tmp;
|
||||
return true;
|
||||
} else {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// free a cluster chain
|
||||
bool FatVolume::freeChain(uint32_t cluster) {
|
||||
uint32_t next = 0;
|
||||
int8_t fg;
|
||||
do {
|
||||
fg = fatGet(cluster, &next);
|
||||
if (fg < 0) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// free cluster
|
||||
if (!fatPut(cluster, 0)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
// Add one to count of free clusters.
|
||||
updateFreeClusterCount(1);
|
||||
|
||||
if (cluster <= m_allocSearchStart) {
|
||||
m_allocSearchStart = cluster - 1;
|
||||
}
|
||||
cluster = next;
|
||||
} while (fg);
|
||||
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int32_t FatVolume::freeClusterCount() {
|
||||
#if MAINTAIN_FREE_CLUSTER_COUNT
|
||||
if (m_freeClusterCount >= 0) {
|
||||
return m_freeClusterCount;
|
||||
}
|
||||
#endif // MAINTAIN_FREE_CLUSTER_COUNT
|
||||
uint32_t free = 0;
|
||||
uint32_t lba;
|
||||
uint32_t todo = m_lastCluster + 1;
|
||||
uint16_t n;
|
||||
|
||||
if (FAT12_SUPPORT && fatType() == 12) {
|
||||
for (unsigned i = 2; i < todo; i++) {
|
||||
uint32_t c;
|
||||
int8_t fg = fatGet(i, &c);
|
||||
if (fg < 0) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (fg && c == 0) {
|
||||
free++;
|
||||
}
|
||||
}
|
||||
} else if (fatType() == 16 || fatType() == 32) {
|
||||
lba = m_fatStartBlock;
|
||||
while (todo) {
|
||||
cache_t* pc = cacheFetchFat(lba++, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
n = fatType() == 16 ? 256 : 128;
|
||||
if (todo < n) {
|
||||
n = todo;
|
||||
}
|
||||
if (fatType() == 16) {
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (pc->fat16[i] == 0) {
|
||||
free++;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for (uint16_t i = 0; i < n; i++) {
|
||||
if (pc->fat32[i] == 0) {
|
||||
free++;
|
||||
}
|
||||
}
|
||||
}
|
||||
todo -= n;
|
||||
}
|
||||
} else {
|
||||
// invalid FAT type
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
setFreeClusterCount(free);
|
||||
return free;
|
||||
|
||||
fail:
|
||||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatVolume::init(uint8_t part) {
|
||||
uint32_t clusterCount;
|
||||
uint32_t totalBlocks;
|
||||
uint32_t volumeStartBlock = 0;
|
||||
fat32_boot_t* fbs;
|
||||
cache_t* pc;
|
||||
uint8_t tmp;
|
||||
m_fatType = 0;
|
||||
m_allocSearchStart = 1;
|
||||
m_cache.init(this);
|
||||
#if USE_SEPARATE_FAT_CACHE
|
||||
m_fatCache.init(this);
|
||||
#endif // USE_SEPARATE_FAT_CACHE
|
||||
// if part == 0 assume super floppy with FAT boot sector in block zero
|
||||
// if part > 0 assume mbr volume with partition table
|
||||
if (part) {
|
||||
if (part > 4) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
pc = cacheFetchData(0, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
part_t* p = &pc->mbr.part[part - 1];
|
||||
if ((p->boot & 0X7F) != 0 || p->firstSector == 0) {
|
||||
// not a valid partition
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
volumeStartBlock = p->firstSector;
|
||||
}
|
||||
pc = cacheFetchData(volumeStartBlock, FatCache::CACHE_FOR_READ);
|
||||
if (!pc) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
fbs = &(pc->fbs32);
|
||||
if (fbs->bytesPerSector != 512 ||
|
||||
fbs->fatCount != 2 ||
|
||||
fbs->reservedSectorCount == 0) {
|
||||
// not valid FAT volume
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
m_blocksPerCluster = fbs->sectorsPerCluster;
|
||||
m_clusterBlockMask = m_blocksPerCluster - 1;
|
||||
// determine shift that is same as multiply by m_blocksPerCluster
|
||||
m_clusterSizeShift = 0;
|
||||
for (tmp = 1; m_blocksPerCluster != tmp; tmp <<= 1, m_clusterSizeShift++) {
|
||||
if (tmp == 0) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
m_blocksPerFat = fbs->sectorsPerFat16 ?
|
||||
fbs->sectorsPerFat16 : fbs->sectorsPerFat32;
|
||||
|
||||
m_fatStartBlock = volumeStartBlock + fbs->reservedSectorCount;
|
||||
|
||||
// count for FAT16 zero for FAT32
|
||||
m_rootDirEntryCount = fbs->rootDirEntryCount;
|
||||
|
||||
// directory start for FAT16 dataStart for FAT32
|
||||
m_rootDirStart = m_fatStartBlock + 2 * m_blocksPerFat;
|
||||
// data start for FAT16 and FAT32
|
||||
m_dataStartBlock = m_rootDirStart + ((32 * fbs->rootDirEntryCount + 511)/512);
|
||||
|
||||
// total blocks for FAT16 or FAT32
|
||||
totalBlocks = fbs->totalSectors16 ?
|
||||
fbs->totalSectors16 : fbs->totalSectors32;
|
||||
// total data blocks
|
||||
clusterCount = totalBlocks - (m_dataStartBlock - volumeStartBlock);
|
||||
|
||||
// divide by cluster size to get cluster count
|
||||
clusterCount >>= m_clusterSizeShift;
|
||||
m_lastCluster = clusterCount + 1;
|
||||
|
||||
// Indicate unknown number of free clusters.
|
||||
setFreeClusterCount(-1);
|
||||
// FAT type is determined by cluster count
|
||||
if (clusterCount < 4085) {
|
||||
m_fatType = 12;
|
||||
if (!FAT12_SUPPORT) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
} else if (clusterCount < 65525) {
|
||||
m_fatType = 16;
|
||||
} else {
|
||||
m_rootDirStart = fbs->fat32RootCluster;
|
||||
m_fatType = 32;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool FatVolume::wipe(print_t* pr) {
|
||||
cache_t* cache;
|
||||
uint16_t count;
|
||||
uint32_t lbn;
|
||||
if (!fatType()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
cache = cacheClear();
|
||||
if (!cache) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
memset(cache->data, 0, 512);
|
||||
// Zero root.
|
||||
if (fatType() == 32) {
|
||||
lbn = clusterFirstBlock(m_rootDirStart);
|
||||
count = m_blocksPerCluster;
|
||||
} else {
|
||||
lbn = m_rootDirStart;
|
||||
count = m_rootDirEntryCount/16;
|
||||
}
|
||||
for (uint32_t n = 0; n < count; n++) {
|
||||
if (!writeBlock(lbn + n, cache->data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
// Clear FATs.
|
||||
count = 2*m_blocksPerFat;
|
||||
lbn = m_fatStartBlock;
|
||||
for (uint32_t nb = 0; nb < count; nb++) {
|
||||
if (pr && (nb & 0XFF) == 0) {
|
||||
pr->write('.');
|
||||
}
|
||||
if (!writeBlock(lbn + nb, cache->data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
// Reserve first two clusters.
|
||||
if (fatType() == 32) {
|
||||
cache->fat32[0] = 0x0FFFFFF8;
|
||||
cache->fat32[1] = 0x0FFFFFFF;
|
||||
} else if (fatType() == 16) {
|
||||
cache->fat16[0] = 0XFFF8;
|
||||
cache->fat16[1] = 0XFFFF;
|
||||
} else if (FAT12_SUPPORT && fatType() == 12) {
|
||||
cache->fat32[0] = 0XFFFFF8;
|
||||
} else {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (!writeBlock(m_fatStartBlock, cache->data) ||
|
||||
!writeBlock(m_fatStartBlock + m_blocksPerFat, cache->data)) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
if (fatType() == 32) {
|
||||
// Reserve root cluster.
|
||||
if (!fatPutEOC(m_rootDirStart) || !cacheSync()) {
|
||||
DBG_FAIL_MACRO;
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (pr) {
|
||||
pr->write('\r');
|
||||
pr->write('\n');
|
||||
}
|
||||
m_fatType = 0;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
m_fatType = 0;
|
||||
return false;
|
||||
}
|
396
hardware/sd_card_formatter/src/SdFat/FatLib/FatVolume.h
Normal file
396
hardware/sd_card_formatter/src/SdFat/FatLib/FatVolume.h
Normal file
|
@ -0,0 +1,396 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FatVolume_h
|
||||
#define FatVolume_h
|
||||
/**
|
||||
* \file
|
||||
* \brief FatVolume class
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "FatLibConfig.h"
|
||||
#include "FatStructs.h"
|
||||
#include "../BlockDriver.h"
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
/** Macro for debug. */
|
||||
#define DEBUG_MODE 0
|
||||
#if DEBUG_MODE
|
||||
#define DBG_FAIL_MACRO Serial.print(F(__FILE__)); Serial.println(__LINE__);
|
||||
#define DBG_PRINT_IF(b) if (b) {Serial.println(F(#b)); DBG_FAIL_MACRO;}
|
||||
#define DBG_HALT_IF(b) if (b) {Serial.println(F(#b));\
|
||||
DBG_FAIL_MACRO; while (1);}
|
||||
#else // DEBUG_MODE
|
||||
#define DBG_FAIL_MACRO
|
||||
#define DBG_PRINT_IF(b)
|
||||
#define DBG_HALT_IF(b)
|
||||
#endif // DEBUG_MODE
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
//------------------------------------------------------------------------------
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
/** Use Print for Arduino */
|
||||
typedef Print print_t;
|
||||
#else // ENABLE_ARDUINO_FEATURES
|
||||
/**
|
||||
* \class CharWriter
|
||||
* \brief Character output - often serial port.
|
||||
*/
|
||||
class CharWriter {
|
||||
public:
|
||||
virtual size_t write(char c) = 0;
|
||||
virtual size_t write(const char* s) = 0;
|
||||
};
|
||||
typedef CharWriter print_t;
|
||||
#endif // ENABLE_ARDUINO_FEATURES
|
||||
//------------------------------------------------------------------------------
|
||||
// Forward declaration of FatVolume.
|
||||
class FatVolume;
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \brief Cache for an raw data block.
|
||||
*/
|
||||
union cache_t {
|
||||
/** Used to access cached file data blocks. */
|
||||
uint8_t data[512];
|
||||
/** Used to access cached FAT16 entries. */
|
||||
uint16_t fat16[256];
|
||||
/** Used to access cached FAT32 entries. */
|
||||
uint32_t fat32[128];
|
||||
/** Used to access cached directory entries. */
|
||||
dir_t dir[16];
|
||||
/** Used to access a cached Master Boot Record. */
|
||||
mbr_t mbr;
|
||||
/** Used to access to a cached FAT boot sector. */
|
||||
fat_boot_t fbs;
|
||||
/** Used to access to a cached FAT32 boot sector. */
|
||||
fat32_boot_t fbs32;
|
||||
/** Used to access to a cached FAT32 FSINFO sector. */
|
||||
fat32_fsinfo_t fsinfo;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class FatCache
|
||||
* \brief Block cache.
|
||||
*/
|
||||
class FatCache {
|
||||
public:
|
||||
/** Cached block is dirty */
|
||||
static const uint8_t CACHE_STATUS_DIRTY = 1;
|
||||
/** Cashed block is FAT entry and must be mirrored in second FAT. */
|
||||
static const uint8_t CACHE_STATUS_MIRROR_FAT = 2;
|
||||
/** Cache block status bits */
|
||||
static const uint8_t CACHE_STATUS_MASK
|
||||
= CACHE_STATUS_DIRTY | CACHE_STATUS_MIRROR_FAT;
|
||||
/** Sync existing block but do not read new block. */
|
||||
static const uint8_t CACHE_OPTION_NO_READ = 4;
|
||||
/** Cache block for read. */
|
||||
static const uint8_t CACHE_FOR_READ = 0;
|
||||
/** Cache block for write. */
|
||||
static const uint8_t CACHE_FOR_WRITE = CACHE_STATUS_DIRTY;
|
||||
/** Reserve cache block for write - do not read from block device. */
|
||||
static const uint8_t CACHE_RESERVE_FOR_WRITE
|
||||
= CACHE_STATUS_DIRTY | CACHE_OPTION_NO_READ;
|
||||
/** \return Cache block address. */
|
||||
cache_t* block() {
|
||||
return &m_block;
|
||||
}
|
||||
/** Set current block dirty. */
|
||||
void dirty() {
|
||||
m_status |= CACHE_STATUS_DIRTY;
|
||||
}
|
||||
/** Initialize the cache.
|
||||
* \param[in] vol FatVolume that owns this FatCache.
|
||||
*/
|
||||
void init(FatVolume *vol) {
|
||||
m_vol = vol;
|
||||
invalidate();
|
||||
}
|
||||
/** Invalidate current cache block. */
|
||||
void invalidate() {
|
||||
m_status = 0;
|
||||
m_lbn = 0XFFFFFFFF;
|
||||
}
|
||||
/** \return dirty status */
|
||||
bool isDirty() {
|
||||
return m_status & CACHE_STATUS_DIRTY;
|
||||
}
|
||||
/** \return Logical block number for cached block. */
|
||||
uint32_t lbn() {
|
||||
return m_lbn;
|
||||
}
|
||||
/** Read a block into the cache.
|
||||
* \param[in] lbn Block to read.
|
||||
* \param[in] option mode for cached block.
|
||||
* \return Address of cached block. */
|
||||
cache_t* read(uint32_t lbn, uint8_t option);
|
||||
/** Write current block if dirty.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool sync();
|
||||
|
||||
private:
|
||||
uint8_t m_status;
|
||||
FatVolume* m_vol;
|
||||
uint32_t m_lbn;
|
||||
cache_t m_block;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class FatVolume
|
||||
* \brief Access FAT16 and FAT32 volumes on raw file devices.
|
||||
*/
|
||||
class FatVolume {
|
||||
public:
|
||||
/** Create an instance of FatVolume
|
||||
*/
|
||||
FatVolume() : m_fatType(0) {}
|
||||
|
||||
/** \return The volume's cluster size in blocks. */
|
||||
uint8_t blocksPerCluster() const {
|
||||
return m_blocksPerCluster;
|
||||
}
|
||||
/** \return The number of blocks in one FAT. */
|
||||
uint32_t blocksPerFat() const {
|
||||
return m_blocksPerFat;
|
||||
}
|
||||
/** Clear the cache and returns a pointer to the cache. Not for normal apps.
|
||||
* \return A pointer to the cache buffer or zero if an error occurs.
|
||||
*/
|
||||
cache_t* cacheClear() {
|
||||
if (!cacheSync()) {
|
||||
return 0;
|
||||
}
|
||||
m_cache.invalidate();
|
||||
return m_cache.block();
|
||||
}
|
||||
/** \return The total number of clusters in the volume. */
|
||||
uint32_t clusterCount() const {
|
||||
return m_lastCluster - 1;
|
||||
}
|
||||
/** \return The shift count required to multiply by blocksPerCluster. */
|
||||
uint8_t clusterSizeShift() const {
|
||||
return m_clusterSizeShift;
|
||||
}
|
||||
/** \return The logical block number for the start of file data. */
|
||||
uint32_t dataStartBlock() const {
|
||||
return m_dataStartBlock;
|
||||
}
|
||||
/** \return The sector number for the start of file data. */
|
||||
uint32_t dataStartSector() const {
|
||||
return m_dataStartBlock;
|
||||
}
|
||||
/** \return The number of File Allocation Tables. */
|
||||
uint8_t fatCount() {
|
||||
return 2;
|
||||
}
|
||||
/** \return The logical block number for the start of the first FAT. */
|
||||
uint32_t fatStartBlock() const {
|
||||
return m_fatStartBlock;
|
||||
}
|
||||
/** \return The sector number for the start of the first FAT. */
|
||||
uint32_t fatStartSector() const {
|
||||
return m_fatStartBlock;
|
||||
}
|
||||
/** \return The FAT type of the volume. Values are 12, 16 or 32. */
|
||||
uint8_t fatType() const {
|
||||
return m_fatType;
|
||||
}
|
||||
/** Volume free space in clusters.
|
||||
*
|
||||
* \return Count of free clusters for success or -1 if an error occurs.
|
||||
*/
|
||||
int32_t freeClusterCount();
|
||||
/** Initialize a FAT volume. Try partition one first then try super
|
||||
* floppy format.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool init() {
|
||||
return init(1) || init(0);
|
||||
}
|
||||
/** Initialize a FAT volume.
|
||||
|
||||
* \param[in] part The partition to be used. Legal values for \a part are
|
||||
* 1-4 to use the corresponding partition on a device formatted with
|
||||
* a MBR, Master Boot Record, or zero if the device is formatted as
|
||||
* a super floppy with the FAT boot sector in block zero.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool init(uint8_t part);
|
||||
/** \return The cluster number of last cluster in the volume. */
|
||||
uint32_t lastCluster() const {
|
||||
return m_lastCluster;
|
||||
}
|
||||
/** \return The number of entries in the root directory for FAT16 volumes. */
|
||||
uint16_t rootDirEntryCount() const {
|
||||
return m_rootDirEntryCount;
|
||||
}
|
||||
/** \return The logical block number for the start of the root directory
|
||||
on FAT16 volumes or the first cluster number on FAT32 volumes. */
|
||||
uint32_t rootDirStart() const {
|
||||
return m_rootDirStart;
|
||||
}
|
||||
/** \return The volume's cluster size in sectors. */
|
||||
uint8_t sectorsPerCluster() const {
|
||||
return m_blocksPerCluster;
|
||||
}
|
||||
/** \return The number of blocks in the volume */
|
||||
uint32_t volumeBlockCount() const {
|
||||
return blocksPerCluster()*clusterCount();
|
||||
}
|
||||
/** \return The number of sectors in the volume */
|
||||
uint32_t volumeSectorCount() const {
|
||||
return sectorsPerCluster()*clusterCount();
|
||||
}
|
||||
/** Wipe all data from the volume.
|
||||
* \param[in] pr print stream for status dots.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool wipe(print_t* pr = 0);
|
||||
/** Debug access to FAT table
|
||||
*
|
||||
* \param[in] n cluster number.
|
||||
* \param[out] v value of entry
|
||||
* \return -1 error, 0 EOC, else 1.
|
||||
*/
|
||||
int8_t dbgFat(uint32_t n, uint32_t* v) {
|
||||
return fatGet(n, v);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
private:
|
||||
// Allow FatFile and FatCache access to FatVolume private functions.
|
||||
friend class FatCache; ///< Allow access to FatVolume.
|
||||
friend class FatFile; ///< Allow access to FatVolume.
|
||||
friend class FatFileSystem; ///< Allow access to FatVolume.
|
||||
//------------------------------------------------------------------------------
|
||||
BlockDriver* m_blockDev; // block device
|
||||
uint8_t m_blocksPerCluster; // Cluster size in blocks.
|
||||
uint8_t m_clusterBlockMask; // Mask to extract block of cluster.
|
||||
uint8_t m_clusterSizeShift; // Cluster count to block count shift.
|
||||
uint8_t m_fatType; // Volume type (12, 16, OR 32).
|
||||
uint16_t m_rootDirEntryCount; // Number of entries in FAT16 root dir.
|
||||
uint32_t m_allocSearchStart; // Start cluster for alloc search.
|
||||
uint32_t m_blocksPerFat; // FAT size in blocks
|
||||
uint32_t m_dataStartBlock; // First data block number.
|
||||
uint32_t m_fatStartBlock; // Start block for first FAT.
|
||||
uint32_t m_lastCluster; // Last cluster number in FAT.
|
||||
uint32_t m_rootDirStart; // Start block for FAT16, cluster for FAT32.
|
||||
//------------------------------------------------------------------------------
|
||||
// block I/O functions.
|
||||
bool readBlock(uint32_t block, uint8_t* dst) {
|
||||
return m_blockDev->readBlock(block, dst);
|
||||
}
|
||||
bool syncBlocks() {
|
||||
return m_blockDev->syncBlocks();
|
||||
}
|
||||
bool writeBlock(uint32_t block, const uint8_t* src) {
|
||||
return m_blockDev->writeBlock(block, src);
|
||||
}
|
||||
#if USE_MULTI_BLOCK_IO
|
||||
bool readBlocks(uint32_t block, uint8_t* dst, size_t nb) {
|
||||
return m_blockDev->readBlocks(block, dst, nb);
|
||||
}
|
||||
bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb) {
|
||||
return m_blockDev->writeBlocks(block, src, nb);
|
||||
}
|
||||
#endif // USE_MULTI_BLOCK_IO
|
||||
#if MAINTAIN_FREE_CLUSTER_COUNT
|
||||
int32_t m_freeClusterCount; // Count of free clusters in volume.
|
||||
void setFreeClusterCount(int32_t value) {
|
||||
m_freeClusterCount = value;
|
||||
}
|
||||
void updateFreeClusterCount(int32_t change) {
|
||||
if (m_freeClusterCount >= 0) {
|
||||
m_freeClusterCount += change;
|
||||
}
|
||||
}
|
||||
#else // MAINTAIN_FREE_CLUSTER_COUNT
|
||||
void setFreeClusterCount(int32_t value) {
|
||||
(void)value;
|
||||
}
|
||||
void updateFreeClusterCount(int32_t change) {
|
||||
(void)change;
|
||||
}
|
||||
#endif // MAINTAIN_FREE_CLUSTER_COUNT
|
||||
|
||||
// block caches
|
||||
FatCache m_cache;
|
||||
#if USE_SEPARATE_FAT_CACHE
|
||||
FatCache m_fatCache;
|
||||
cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) {
|
||||
return m_fatCache.read(blockNumber,
|
||||
options | FatCache::CACHE_STATUS_MIRROR_FAT);
|
||||
}
|
||||
bool cacheSync() {
|
||||
return m_cache.sync() && m_fatCache.sync() && syncBlocks();
|
||||
}
|
||||
#else //
|
||||
cache_t* cacheFetchFat(uint32_t blockNumber, uint8_t options) {
|
||||
return cacheFetchData(blockNumber,
|
||||
options | FatCache::CACHE_STATUS_MIRROR_FAT);
|
||||
}
|
||||
bool cacheSync() {
|
||||
return m_cache.sync() && syncBlocks();
|
||||
}
|
||||
#endif // USE_SEPARATE_FAT_CACHE
|
||||
cache_t* cacheFetchData(uint32_t blockNumber, uint8_t options) {
|
||||
return m_cache.read(blockNumber, options);
|
||||
}
|
||||
void cacheInvalidate() {
|
||||
m_cache.invalidate();
|
||||
}
|
||||
bool cacheSyncData() {
|
||||
return m_cache.sync();
|
||||
}
|
||||
cache_t *cacheAddress() {
|
||||
return m_cache.block();
|
||||
}
|
||||
uint32_t cacheBlockNumber() {
|
||||
return m_cache.lbn();
|
||||
}
|
||||
void cacheDirty() {
|
||||
m_cache.dirty();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool allocateCluster(uint32_t current, uint32_t* next);
|
||||
bool allocContiguous(uint32_t count,
|
||||
uint32_t* firstCluster, uint32_t startCluster = 0);
|
||||
uint8_t blockOfCluster(uint32_t position) const {
|
||||
return (position >> 9) & m_clusterBlockMask;
|
||||
}
|
||||
uint32_t clusterFirstBlock(uint32_t cluster) const;
|
||||
int8_t fatGet(uint32_t cluster, uint32_t* value);
|
||||
bool fatPut(uint32_t cluster, uint32_t value);
|
||||
bool fatPutEOC(uint32_t cluster) {
|
||||
return fatPut(cluster, 0x0FFFFFFF);
|
||||
}
|
||||
bool freeChain(uint32_t cluster);
|
||||
bool isEOC(uint32_t cluster) const {
|
||||
return cluster > m_lastCluster;
|
||||
}
|
||||
};
|
||||
#endif // FatVolume
|
460
hardware/sd_card_formatter/src/SdFat/FatLib/FmtNumber.cpp
Normal file
460
hardware/sd_card_formatter/src/SdFat/FatLib/FmtNumber.cpp
Normal file
|
@ -0,0 +1,460 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "FmtNumber.h"
|
||||
// Use Stimmer div/mod 10 on avr
|
||||
#ifdef __AVR__
|
||||
#include <avr/pgmspace.h>
|
||||
#define USE_STIMMER
|
||||
#endif // __AVR__
|
||||
//------------------------------------------------------------------------------
|
||||
// Stimmer div/mod 10 for AVR
|
||||
// this code fragment works out i/10 and i%10 by calculating
|
||||
// i*(51/256)*(256/255)/2 == i*51/510 == i/10
|
||||
// by "j.k" I mean 32.8 fixed point, j is integer part, k is fractional part
|
||||
// j.k = ((j+1.0)*51.0)/256.0
|
||||
// (we add 1 because we will be using the floor of the result later)
|
||||
// divmod10_asm16 and divmod10_asm32 are public domain code by Stimmer.
|
||||
// http://forum.arduino.cc/index.php?topic=167414.msg1293679#msg1293679
|
||||
#define divmod10_asm16(in32, mod8, tmp8) \
|
||||
asm volatile( \
|
||||
" ldi %2,51 \n\t" \
|
||||
" mul %A0,%2 \n\t" \
|
||||
" clr %A0 \n\t" \
|
||||
" add r0,%2 \n\t" \
|
||||
" adc %A0,r1 \n\t" \
|
||||
" mov %1,r0 \n\t" \
|
||||
" mul %B0,%2 \n\t" \
|
||||
" clr %B0 \n\t" \
|
||||
" add %A0,r0 \n\t" \
|
||||
" adc %B0,r1 \n\t" \
|
||||
" clr r1 \n\t" \
|
||||
" add %1,%A0 \n\t" \
|
||||
" adc %A0,%B0 \n\t" \
|
||||
" adc %B0,r1 \n\t" \
|
||||
" add %1,%B0 \n\t" \
|
||||
" adc %A0,r1 \n\t" \
|
||||
" adc %B0,r1 \n\t" \
|
||||
" lsr %B0 \n\t" \
|
||||
" ror %A0 \n\t" \
|
||||
" ror %1 \n\t" \
|
||||
" ldi %2,10 \n\t" \
|
||||
" mul %1,%2 \n\t" \
|
||||
" mov %1,r1 \n\t" \
|
||||
" clr r1 \n\t" \
|
||||
:"+r"(in32), "=d"(mod8), "=d"(tmp8) : : "r0")
|
||||
|
||||
#define divmod10_asm32(in32, mod8, tmp8) \
|
||||
asm volatile( \
|
||||
" ldi %2,51 \n\t" \
|
||||
" mul %A0,%2 \n\t" \
|
||||
" clr %A0 \n\t" \
|
||||
" add r0,%2 \n\t" \
|
||||
" adc %A0,r1 \n\t" \
|
||||
" mov %1,r0 \n\t" \
|
||||
" mul %B0,%2 \n\t" \
|
||||
" clr %B0 \n\t" \
|
||||
" add %A0,r0 \n\t" \
|
||||
" adc %B0,r1 \n\t" \
|
||||
" mul %C0,%2 \n\t" \
|
||||
" clr %C0 \n\t" \
|
||||
" add %B0,r0 \n\t" \
|
||||
" adc %C0,r1 \n\t" \
|
||||
" mul %D0,%2 \n\t" \
|
||||
" clr %D0 \n\t" \
|
||||
" add %C0,r0 \n\t" \
|
||||
" adc %D0,r1 \n\t" \
|
||||
" clr r1 \n\t" \
|
||||
" add %1,%A0 \n\t" \
|
||||
" adc %A0,%B0 \n\t" \
|
||||
" adc %B0,%C0 \n\t" \
|
||||
" adc %C0,%D0 \n\t" \
|
||||
" adc %D0,r1 \n\t" \
|
||||
" add %1,%B0 \n\t" \
|
||||
" adc %A0,%C0 \n\t" \
|
||||
" adc %B0,%D0 \n\t" \
|
||||
" adc %C0,r1 \n\t" \
|
||||
" adc %D0,r1 \n\t" \
|
||||
" add %1,%D0 \n\t" \
|
||||
" adc %A0,r1 \n\t" \
|
||||
" adc %B0,r1 \n\t" \
|
||||
" adc %C0,r1 \n\t" \
|
||||
" adc %D0,r1 \n\t" \
|
||||
" lsr %D0 \n\t" \
|
||||
" ror %C0 \n\t" \
|
||||
" ror %B0 \n\t" \
|
||||
" ror %A0 \n\t" \
|
||||
" ror %1 \n\t" \
|
||||
" ldi %2,10 \n\t" \
|
||||
" mul %1,%2 \n\t" \
|
||||
" mov %1,r1 \n\t" \
|
||||
" clr r1 \n\t" \
|
||||
:"+r"(in32), "=d"(mod8), "=d"(tmp8) : : "r0")
|
||||
//------------------------------------------------------------------------------
|
||||
/*
|
||||
// C++ code is based on this version of divmod10 by robtillaart.
|
||||
// http://forum.arduino.cc/index.php?topic=167414.msg1246851#msg1246851
|
||||
// from robtillaart post:
|
||||
// The code is based upon the divu10() code from the book Hackers Delight1.
|
||||
// My insight was that the error formula in divu10() was in fact modulo 10
|
||||
// but not always. Sometimes it was 10 more.
|
||||
void divmod10(uint32_t in, uint32_t &div, uint32_t &mod)
|
||||
{
|
||||
// q = in * 0.8;
|
||||
uint32_t q = (in >> 1) + (in >> 2);
|
||||
q = q + (q >> 4);
|
||||
q = q + (q >> 8);
|
||||
q = q + (q >> 16); // not needed for 16 bit version
|
||||
|
||||
// q = q / 8; ==> q = in *0.1;
|
||||
q = q >> 3;
|
||||
|
||||
// determine error
|
||||
uint32_t r = in - ((q << 3) + (q << 1)); // r = in - q*10;
|
||||
div = q + (r > 9);
|
||||
if (r > 9) mod = r - 10;
|
||||
else mod = r;
|
||||
}
|
||||
// Hackers delight function is here:
|
||||
// http://www.hackersdelight.org/hdcodetxt/divuc.c.txt
|
||||
// Code below uses 8/10 = 0.1100 1100 1100 1100 1100 1100 1100 1100.
|
||||
// 15 ops including the multiply, or 17 elementary ops.
|
||||
unsigned divu10(unsigned n) {
|
||||
unsigned q, r;
|
||||
|
||||
q = (n >> 1) + (n >> 2);
|
||||
q = q + (q >> 4);
|
||||
q = q + (q >> 8);
|
||||
q = q + (q >> 16);
|
||||
q = q >> 3;
|
||||
r = n - q*10;
|
||||
return q + ((r + 6) >> 4);
|
||||
// return q + (r > 9);
|
||||
}
|
||||
*/
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef DOXYGEN_SHOULD_SKIP_THIS
|
||||
#ifdef __AVR__
|
||||
static const float m[] PROGMEM = {1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32};
|
||||
static const float p[] PROGMEM = {1e+1, 1e+2, 1e+4, 1e+8, 1e+16, 1e+32};
|
||||
#else // __AVR__
|
||||
static const float m[] = {1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32};
|
||||
static const float p[] = {1e+1, 1e+2, 1e+4, 1e+8, 1e+16, 1e+32};
|
||||
#endif // __AVR__
|
||||
#endif // DOXYGEN_SHOULD_SKIP_THIS
|
||||
// scale float v by power of ten. return v*10^n
|
||||
float scale10(float v, int8_t n) {
|
||||
const float *s;
|
||||
if (n < 0) {
|
||||
n = -n;
|
||||
s = m;
|
||||
} else {
|
||||
s = p;
|
||||
}
|
||||
n &= 63;
|
||||
for (uint8_t i = 0; n; n >>= 1, i++) {
|
||||
#ifdef __AVR__
|
||||
if (n & 1) {
|
||||
v *= pgm_read_float(&s[i]);
|
||||
}
|
||||
#else // __AVR__
|
||||
if (n & 1) {
|
||||
v *= s[i];
|
||||
}
|
||||
#endif // __AVR__
|
||||
}
|
||||
return v;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// Format 16-bit unsigned
|
||||
char* fmtDec(uint16_t n, char* p) {
|
||||
while (n > 9) {
|
||||
#ifdef USE_STIMMER
|
||||
uint8_t tmp8, r;
|
||||
divmod10_asm16(n, r, tmp8);
|
||||
#else // USE_STIMMER
|
||||
uint16_t t = n;
|
||||
n = (n >> 1) + (n >> 2);
|
||||
n = n + (n >> 4);
|
||||
n = n + (n >> 8);
|
||||
// n = n + (n >> 16); // no code for 16-bit n
|
||||
n = n >> 3;
|
||||
uint8_t r = t - (((n << 2) + n) << 1);
|
||||
if (r > 9) {
|
||||
n++;
|
||||
r -= 10;
|
||||
}
|
||||
#endif // USE_STIMMER
|
||||
*--p = r + '0';
|
||||
}
|
||||
*--p = n + '0';
|
||||
return p;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// format 32-bit unsigned
|
||||
char* fmtDec(uint32_t n, char* p) {
|
||||
while (n >> 16) {
|
||||
#ifdef USE_STIMMER
|
||||
uint8_t tmp8, r;
|
||||
divmod10_asm32(n, r, tmp8);
|
||||
#else // USE_STIMMER
|
||||
uint32_t t = n;
|
||||
n = (n >> 1) + (n >> 2);
|
||||
n = n + (n >> 4);
|
||||
n = n + (n >> 8);
|
||||
n = n + (n >> 16);
|
||||
n = n >> 3;
|
||||
uint8_t r = t - (((n << 2) + n) << 1);
|
||||
if (r > 9) {
|
||||
n++;
|
||||
r -= 10;
|
||||
}
|
||||
#endif // USE_STIMMER
|
||||
*--p = r + '0';
|
||||
}
|
||||
return fmtDec((uint16_t)n, p);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
char* fmtFloat(float value, char* p, uint8_t prec) {
|
||||
char sign = value < 0 ? '-' : 0;
|
||||
if (sign) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
if (isnan(value)) {
|
||||
*--p = 'n';
|
||||
*--p = 'a';
|
||||
*--p = 'n';
|
||||
return p;
|
||||
}
|
||||
if (isinf(value)) {
|
||||
*--p = 'f';
|
||||
*--p = 'n';
|
||||
*--p = 'i';
|
||||
return p;
|
||||
}
|
||||
if (value > 4294967040.0) {
|
||||
*--p = 'f';
|
||||
*--p = 'v';
|
||||
*--p = 'o';
|
||||
return p;
|
||||
}
|
||||
if (prec > 9) {
|
||||
prec = 9;
|
||||
}
|
||||
value += scale10(0.5, -prec);
|
||||
|
||||
uint32_t whole = value;
|
||||
if (prec) {
|
||||
char* tmp = p - prec;
|
||||
uint32_t fraction = scale10(value - whole, prec);
|
||||
p = fmtDec(fraction, p);
|
||||
while (p > tmp) {
|
||||
*--p = '0';
|
||||
}
|
||||
*--p = '.';
|
||||
}
|
||||
p = fmtDec(whole, p);
|
||||
if (sign) {
|
||||
*--p = sign;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] ptr Pointer to last char in buffer.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \param[in] expChar Use exp format if non zero.
|
||||
* \return Pointer to first character of result.
|
||||
*/
|
||||
char* fmtFloat(float value, char* ptr, uint8_t prec, char expChar) {
|
||||
bool neg = value < 0;
|
||||
if (neg) {
|
||||
value = -value;
|
||||
}
|
||||
|
||||
// check for nan inf ovf
|
||||
if (isnan(value)) {
|
||||
*--ptr = 'n';
|
||||
*--ptr = 'a';
|
||||
*--ptr = 'n';
|
||||
return ptr;
|
||||
}
|
||||
if (isinf(value)) {
|
||||
*--ptr = 'f';
|
||||
*--ptr = 'n';
|
||||
*--ptr = 'i';
|
||||
return ptr;
|
||||
}
|
||||
if (!expChar && value > 4294967040.0) {
|
||||
*--ptr = 'f';
|
||||
*--ptr = 'v';
|
||||
*--ptr = 'o';
|
||||
return ptr;
|
||||
}
|
||||
if (prec > 9) {
|
||||
prec = 9;
|
||||
}
|
||||
float round = scale10(0.5, -prec);
|
||||
if (expChar) {
|
||||
int8_t exp = 0;
|
||||
bool expNeg = false;
|
||||
if (value) {
|
||||
while (value > 10.0) {
|
||||
value *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
while (value < 1.0) {
|
||||
value *= 10.0;
|
||||
exp--;
|
||||
}
|
||||
value += round;
|
||||
if (value > 10.0) {
|
||||
value *= 0.1;
|
||||
exp++;
|
||||
}
|
||||
expNeg = exp < 0;
|
||||
if (expNeg) {
|
||||
exp = -exp;
|
||||
}
|
||||
}
|
||||
ptr = fmtDec((uint16_t)exp, ptr);
|
||||
if (exp < 10) {
|
||||
*--ptr = '0';
|
||||
}
|
||||
*--ptr = expNeg ? '-' : '+';
|
||||
*--ptr = expChar;
|
||||
} else {
|
||||
// round value
|
||||
value += round;
|
||||
}
|
||||
uint32_t whole = value;
|
||||
if (prec) {
|
||||
char* tmp = ptr - prec;
|
||||
uint32_t fraction = scale10(value - whole, prec);
|
||||
ptr = fmtDec(fraction, ptr);
|
||||
while (ptr > tmp) {
|
||||
*--ptr = '0';
|
||||
}
|
||||
*--ptr = '.';
|
||||
}
|
||||
ptr = fmtDec(whole, ptr);
|
||||
if (neg) {
|
||||
*--ptr = '-';
|
||||
}
|
||||
return ptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
char* fmtHex(uint32_t n, char* p) {
|
||||
do {
|
||||
uint8_t h = n & 0XF;
|
||||
*--p = h + (h < 10 ? '0' : 'A' - 10);
|
||||
n >>= 4;
|
||||
} while (n);
|
||||
return p;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
float scanFloat(const char* str, char** ptr) {
|
||||
int16_t const EXP_LIMIT = 100;
|
||||
bool digit = false;
|
||||
bool dot = false;
|
||||
uint32_t fract = 0;
|
||||
int fracExp = 0;
|
||||
uint8_t nd = 0;
|
||||
bool neg;
|
||||
int c;
|
||||
float v;
|
||||
const char* successPtr = str;
|
||||
|
||||
if (ptr) {
|
||||
*ptr = const_cast<char*>(str);
|
||||
}
|
||||
|
||||
while (isSpace((c = *str++))) {}
|
||||
neg = c == '-';
|
||||
if (c == '-' || c == '+') {
|
||||
c = *str++;
|
||||
}
|
||||
// Skip leading zeros
|
||||
while (c == '0') {
|
||||
c = *str++;
|
||||
digit = true;
|
||||
}
|
||||
for (;;) {
|
||||
if (isDigit(c)) {
|
||||
digit = true;
|
||||
if (nd < 9) {
|
||||
fract = 10*fract + c - '0';
|
||||
nd++;
|
||||
if (dot) {
|
||||
fracExp--;
|
||||
}
|
||||
} else {
|
||||
if (!dot) {
|
||||
fracExp++;
|
||||
}
|
||||
}
|
||||
} else if (c == '.') {
|
||||
if (dot) {
|
||||
goto fail;
|
||||
}
|
||||
dot = true;
|
||||
} else {
|
||||
if (!digit) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
}
|
||||
successPtr = str;
|
||||
c = *str++;
|
||||
}
|
||||
if (c == 'e' || c == 'E') {
|
||||
int exp = 0;
|
||||
c = *str++;
|
||||
bool expNeg = c == '-';
|
||||
if (c == '-' || c == '+') {
|
||||
c = *str++;
|
||||
}
|
||||
while (isDigit(c)) {
|
||||
if (exp > EXP_LIMIT) {
|
||||
goto fail;
|
||||
}
|
||||
exp = 10*exp + c - '0';
|
||||
successPtr = str;
|
||||
c = *str++;
|
||||
}
|
||||
fracExp += expNeg ? -exp : exp;
|
||||
}
|
||||
if (ptr) {
|
||||
*ptr = const_cast<char*>(successPtr);
|
||||
}
|
||||
v = scale10(static_cast<float>(fract), fracExp);
|
||||
return neg ? -v : v;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
43
hardware/sd_card_formatter/src/SdFat/FatLib/FmtNumber.h
Normal file
43
hardware/sd_card_formatter/src/SdFat/FatLib/FmtNumber.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FmtNumber_h
|
||||
#define FmtNumber_h
|
||||
// #include <ctype.h>
|
||||
inline bool isDigit(char c) {
|
||||
return '0' <= c && c <= '9';
|
||||
}
|
||||
inline bool isSpace(char c) {
|
||||
return c == ' ' || (0X9 <= c && c <= 0XD);
|
||||
}
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
char* fmtDec(uint16_t n, char* p);
|
||||
char* fmtDec(uint32_t n, char* p);
|
||||
char* fmtFloat(float value, char* p, uint8_t prec);
|
||||
char* fmtFloat(float value, char* ptr, uint8_t prec, char expChar);
|
||||
char* fmtHex(uint32_t n, char* p);
|
||||
float scale10(float v, int8_t n);
|
||||
float scanFloat(const char* str, char** ptr);
|
||||
#endif // FmtNumber_h
|
508
hardware/sd_card_formatter/src/SdFat/FatLib/StdioStream.cpp
Normal file
508
hardware/sd_card_formatter/src/SdFat/FatLib/StdioStream.cpp
Normal file
|
@ -0,0 +1,508 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "StdioStream.h"
|
||||
#include "FmtNumber.h"
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::fclose() {
|
||||
int rtn = 0;
|
||||
if (!m_status) {
|
||||
return EOF;
|
||||
}
|
||||
if (m_status & S_SWR) {
|
||||
if (!flushBuf()) {
|
||||
rtn = EOF;
|
||||
}
|
||||
}
|
||||
if (!FatFile::close()) {
|
||||
rtn = EOF;
|
||||
}
|
||||
m_r = 0;
|
||||
m_w = 0;
|
||||
m_status = 0;
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::fflush() {
|
||||
if ((m_status & (S_SWR | S_SRW)) && !(m_status & S_SRD)) {
|
||||
if (flushBuf() && FatFile::sync()) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return EOF;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
char* StdioStream::fgets(char* str, size_t num, size_t* len) {
|
||||
char* s = str;
|
||||
size_t n;
|
||||
if (num-- == 0) {
|
||||
return 0;
|
||||
}
|
||||
while (num) {
|
||||
if ((n = m_r) == 0) {
|
||||
if (!fillBuf()) {
|
||||
if (s == str) {
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
}
|
||||
n = m_r;
|
||||
}
|
||||
if (n > num) {
|
||||
n = num;
|
||||
}
|
||||
uint8_t* end = reinterpret_cast<uint8_t*>(memchr(m_p, '\n', n));
|
||||
if (end != 0) {
|
||||
n = ++end - m_p;
|
||||
memcpy(s, m_p, n);
|
||||
m_r -= n;
|
||||
m_p = end;
|
||||
s += n;
|
||||
break;
|
||||
}
|
||||
memcpy(s, m_p, n);
|
||||
m_r -= n;
|
||||
m_p += n;
|
||||
s += n;
|
||||
num -= n;
|
||||
}
|
||||
*s = 0;
|
||||
if (len) {
|
||||
*len = s - str;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool StdioStream::fopen(const char* path, const char* mode) {
|
||||
oflag_t oflag;
|
||||
uint8_t m;
|
||||
switch (*mode++) {
|
||||
case 'a':
|
||||
m = O_WRONLY;
|
||||
oflag = O_CREAT | O_APPEND;
|
||||
m_status = S_SWR;
|
||||
break;
|
||||
|
||||
case 'r':
|
||||
m = O_RDONLY;
|
||||
oflag = 0;
|
||||
m_status = S_SRD;
|
||||
break;
|
||||
|
||||
case 'w':
|
||||
m = O_WRONLY;
|
||||
oflag = O_CREAT | O_TRUNC;
|
||||
m_status = S_SWR;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
while (*mode) {
|
||||
switch (*mode++) {
|
||||
case '+':
|
||||
m_status = S_SRW;
|
||||
m = O_RDWR;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
break;
|
||||
|
||||
case 'x':
|
||||
oflag |= O_EXCL;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
oflag |= m;
|
||||
|
||||
if (!FatFile::open(path, oflag)) {
|
||||
goto fail;
|
||||
}
|
||||
m_r = 0;
|
||||
m_w = 0;
|
||||
m_p = m_buf;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
m_status = 0;
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::fputs(const char* str) {
|
||||
size_t len = strlen(str);
|
||||
return fwrite(str, 1, len) == len ? len : EOF;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t StdioStream::fread(void* ptr, size_t size, size_t count) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(ptr);
|
||||
size_t total = size*count;
|
||||
if (total == 0) {
|
||||
return 0;
|
||||
}
|
||||
size_t need = total;
|
||||
while (need > m_r) {
|
||||
memcpy(dst, m_p, m_r);
|
||||
dst += m_r;
|
||||
m_p += m_r;
|
||||
need -= m_r;
|
||||
if (!fillBuf()) {
|
||||
return (total - need)/size;
|
||||
}
|
||||
}
|
||||
memcpy(dst, m_p, need);
|
||||
m_r -= need;
|
||||
m_p += need;
|
||||
return count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::fseek(int32_t offset, int origin) {
|
||||
int32_t pos;
|
||||
if (m_status & S_SWR) {
|
||||
if (!flushBuf()) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
switch (origin) {
|
||||
case SEEK_CUR:
|
||||
pos = ftell();
|
||||
if (pos < 0) {
|
||||
goto fail;
|
||||
}
|
||||
pos += offset;
|
||||
if (!FatFile::seekCur(pos)) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_SET:
|
||||
if (!FatFile::seekSet(offset)) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
case SEEK_END:
|
||||
if (!FatFile::seekEnd(offset)) {
|
||||
goto fail;
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
m_r = 0;
|
||||
m_p = m_buf;
|
||||
return 0;
|
||||
|
||||
fail:
|
||||
return EOF;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int32_t StdioStream::ftell() {
|
||||
uint32_t pos = FatFile::curPosition();
|
||||
if (m_status & S_SRD) {
|
||||
if (m_r > pos) {
|
||||
return -1L;
|
||||
}
|
||||
pos -= m_r;
|
||||
} else if (m_status & S_SWR) {
|
||||
pos += m_p - m_buf;
|
||||
}
|
||||
return pos;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t StdioStream::fwrite(const void* ptr, size_t size, size_t count) {
|
||||
return write(ptr, count*size) < 0 ? EOF : count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::write(const void* buf, size_t count) {
|
||||
const uint8_t* src = static_cast<const uint8_t*>(buf);
|
||||
size_t todo = count;
|
||||
|
||||
while (todo > m_w) {
|
||||
memcpy(m_p, src, m_w);
|
||||
m_p += m_w;
|
||||
src += m_w;
|
||||
todo -= m_w;
|
||||
if (!flushBuf()) {
|
||||
return EOF;
|
||||
}
|
||||
}
|
||||
memcpy(m_p, src, todo);
|
||||
m_p += todo;
|
||||
m_w -= todo;
|
||||
return count;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
size_t StdioStream::print(const __FlashStringHelper *str) {
|
||||
const char *p = (const char*)str;
|
||||
uint8_t c;
|
||||
while ((c = pgm_read_byte(p))) {
|
||||
if (putc(c) < 0) {
|
||||
return 0;
|
||||
}
|
||||
p++;
|
||||
}
|
||||
return p - (const char*)str;
|
||||
}
|
||||
#endif // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(float value, uint8_t prec) {
|
||||
char buf[24];
|
||||
char *ptr = fmtFloat(value, buf + sizeof(buf), prec);
|
||||
return write(ptr, buf + sizeof(buf) - ptr);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(signed char n) {
|
||||
if (n < 0) {
|
||||
if (fputc('-') < 0) {
|
||||
return -1;
|
||||
}
|
||||
n = -n;
|
||||
}
|
||||
return printDec((unsigned char)n);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(int16_t n) {
|
||||
int s;
|
||||
uint8_t rtn = 0;
|
||||
if (n < 0) {
|
||||
if (fputc('-') < 0) {
|
||||
return -1;
|
||||
}
|
||||
n = -n;
|
||||
rtn++;
|
||||
}
|
||||
if ((s = printDec((uint16_t)n)) < 0) {
|
||||
return s;
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(uint16_t n) {
|
||||
#define NEW_WAY
|
||||
#ifdef NEW_WAY
|
||||
char buf[5];
|
||||
char *ptr = fmtDec(n, buf + sizeof(buf));
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
#else
|
||||
uint8_t len;
|
||||
if (n < 100) {
|
||||
len = n < 10 ? 1 : 2;
|
||||
} else {
|
||||
len = n < 1000 ? 3 : n < 10000 ? 4 : 5;
|
||||
}
|
||||
char* str = fmtSpace(len);
|
||||
if (!str) {
|
||||
return -1;
|
||||
}
|
||||
fmtDec(n, str);
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(int32_t n) {
|
||||
uint8_t s = 0;
|
||||
if (n < 0) {
|
||||
if (fputc('-') < 0) {
|
||||
return -1;
|
||||
}
|
||||
n = -n;
|
||||
s = 1;
|
||||
}
|
||||
int rtn = printDec((uint32_t)n);
|
||||
return rtn > 0 ? rtn + s : -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printDec(uint32_t n) {
|
||||
#ifdef NEW_WAY
|
||||
char buf[10];
|
||||
char *ptr = fmtDec(n, buf + sizeof(buf));
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
#else
|
||||
uint8_t len;
|
||||
if (n < 0X10000) {
|
||||
return printDec((uint16_t)n);
|
||||
}
|
||||
if (n < 10000000) {
|
||||
len = n < 100000 ? 5 : n < 1000000 ? 6 : 7;
|
||||
} else {
|
||||
len = n < 100000000 ? 8 : n < 1000000000 ? 9 : 10;
|
||||
}
|
||||
|
||||
char* str = fmtSpace(len);
|
||||
if (!str) {
|
||||
return -1;
|
||||
}
|
||||
fmtDec(n, str);
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::printHex(uint32_t n) {
|
||||
#ifdef NEW_WAY
|
||||
char buf[8];
|
||||
char *ptr = fmtHex(n, buf + sizeof(buf));
|
||||
uint8_t len = buf + sizeof(buf) - ptr;
|
||||
return write(ptr, len);
|
||||
#else
|
||||
size_t len;
|
||||
if (n < 0X10000) {
|
||||
len = n < 0X10 ? 1 : n < 0X100 ? 2 : n < 0X1000 ? 3 : 4;
|
||||
} else {
|
||||
len = n < 0X100000 ? 5 : n < 0X1000000 ? 6 : n < 0X10000000 ? 7 : 8;
|
||||
}
|
||||
char* str = fmtSpace(len);
|
||||
if (!str) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
do {
|
||||
uint8_t h = n & 0XF;
|
||||
*str-- = h + (h < 10 ? '0' : 'A' - 10);
|
||||
n >>= 4;
|
||||
} while (n);
|
||||
return len;
|
||||
#endif
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool StdioStream::rewind() {
|
||||
if (m_status & S_SWR) {
|
||||
if (!flushBuf()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
FatFile::seekSet(0);
|
||||
m_r = 0;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::ungetc(int c) {
|
||||
// error if EOF.
|
||||
if (c == EOF) {
|
||||
return EOF;
|
||||
}
|
||||
// error if not reading.
|
||||
if ((m_status & S_SRD) == 0) {
|
||||
return EOF;
|
||||
}
|
||||
// error if no space.
|
||||
if (m_p == m_buf) {
|
||||
return EOF;
|
||||
}
|
||||
m_r++;
|
||||
m_status &= ~S_EOF;
|
||||
return *--m_p = (uint8_t)c;
|
||||
}
|
||||
//==============================================================================
|
||||
// private
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::fillGet() {
|
||||
if (!fillBuf()) {
|
||||
return EOF;
|
||||
}
|
||||
m_r--;
|
||||
return *m_p++;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// private
|
||||
bool StdioStream::fillBuf() {
|
||||
if (!(m_status &
|
||||
S_SRD)) { // check for S_ERR and S_EOF ??/////////////////
|
||||
if (!(m_status & S_SRW)) {
|
||||
m_status |= S_ERR;
|
||||
return false;
|
||||
}
|
||||
if (m_status & S_SWR) {
|
||||
if (!flushBuf()) {
|
||||
return false;
|
||||
}
|
||||
m_status &= ~S_SWR;
|
||||
m_status |= S_SRD;
|
||||
m_w = 0;
|
||||
}
|
||||
}
|
||||
m_p = m_buf + UNGETC_BUF_SIZE;
|
||||
int nr = FatFile::read(m_p, sizeof(m_buf) - UNGETC_BUF_SIZE);
|
||||
if (nr <= 0) {
|
||||
m_status |= nr < 0 ? S_ERR : S_EOF;
|
||||
m_r = 0;
|
||||
return false;
|
||||
}
|
||||
m_r = nr;
|
||||
return true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// private
|
||||
bool StdioStream::flushBuf() {
|
||||
if (!(m_status &
|
||||
S_SWR)) { // check for S_ERR ??////////////////////////
|
||||
if (!(m_status & S_SRW)) {
|
||||
m_status |= S_ERR;
|
||||
return false;
|
||||
}
|
||||
m_status &= ~S_SRD;
|
||||
m_status |= S_SWR;
|
||||
m_r = 0;
|
||||
m_w = sizeof(m_buf);
|
||||
m_p = m_buf;
|
||||
return true;
|
||||
}
|
||||
uint8_t n = m_p - m_buf;
|
||||
m_p = m_buf;
|
||||
m_w = sizeof(m_buf);
|
||||
if (FatFile::write(m_buf, n) == n) {
|
||||
return true;
|
||||
}
|
||||
m_status |= S_ERR;
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int StdioStream::flushPut(uint8_t c) {
|
||||
if (!flushBuf()) {
|
||||
return EOF;
|
||||
}
|
||||
m_w--;
|
||||
return *m_p++ = c;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
char* StdioStream::fmtSpace(uint8_t len) {
|
||||
if (m_w < len) {
|
||||
if (!flushBuf() || m_w < len) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
if (len > m_w) {
|
||||
return 0;
|
||||
}
|
||||
m_p += len;
|
||||
m_w -= len;
|
||||
return reinterpret_cast<char*>(m_p);
|
||||
}
|
||||
|
667
hardware/sd_card_formatter/src/SdFat/FatLib/StdioStream.h
Normal file
667
hardware/sd_card_formatter/src/SdFat/FatLib/StdioStream.h
Normal file
|
@ -0,0 +1,667 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef StdioStream_h
|
||||
#define StdioStream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief StdioStream class
|
||||
*/
|
||||
#include <limits.h>
|
||||
#include "FatFile.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** Total size of stream buffer. The entire buffer is used for output.
|
||||
* During input UNGETC_BUF_SIZE of this space is reserved for ungetc.
|
||||
*/
|
||||
const uint8_t STREAM_BUF_SIZE = 64;
|
||||
/** Amount of buffer allocated for ungetc during input. */
|
||||
const uint8_t UNGETC_BUF_SIZE = 2;
|
||||
//------------------------------------------------------------------------------
|
||||
// Get rid of any macros defined in <stdio.h>.
|
||||
#include <stdio.h>
|
||||
#undef clearerr
|
||||
#undef fclose
|
||||
#undef feof
|
||||
#undef ferror
|
||||
#undef fflush
|
||||
#undef fgetc
|
||||
#undef fgetpos
|
||||
#undef fgets
|
||||
#undef fopen
|
||||
#undef fprintf
|
||||
#undef fputc
|
||||
#undef fputs
|
||||
#undef fread
|
||||
#undef freopen
|
||||
#undef fscanf
|
||||
#undef fseek
|
||||
#undef fsetpos
|
||||
#undef ftell
|
||||
#undef fwrite
|
||||
#undef getc
|
||||
#undef getchar
|
||||
#undef gets
|
||||
#undef perror
|
||||
//#undef printf // NOLINT
|
||||
#undef putc
|
||||
#undef putchar
|
||||
#undef puts
|
||||
#undef remove
|
||||
#undef rename
|
||||
#undef rewind
|
||||
#undef scanf
|
||||
#undef setbuf
|
||||
#undef setvbuf
|
||||
//#undef sprintf // NOLINT
|
||||
#undef sscanf
|
||||
#undef tmpfile
|
||||
#undef tmpnam
|
||||
#undef ungetc
|
||||
#undef vfprintf
|
||||
#undef vprintf
|
||||
#undef vsprintf
|
||||
|
||||
// make sure needed macros are defined
|
||||
#ifndef EOF
|
||||
/** End-of-file return value. */
|
||||
#define EOF (-1)
|
||||
#endif // EOF
|
||||
#ifndef NULL
|
||||
/** Null pointer */
|
||||
#define NULL 0
|
||||
#endif // NULL
|
||||
#ifndef SEEK_CUR
|
||||
/** Seek relative to current position. */
|
||||
#define SEEK_CUR 1
|
||||
#endif // SEEK_CUR
|
||||
#ifndef SEEK_END
|
||||
/** Seek relative to end-of-file. */
|
||||
#define SEEK_END 2
|
||||
#endif // SEEK_END
|
||||
#ifndef SEEK_SET
|
||||
/** Seek relative to start-of-file. */
|
||||
#define SEEK_SET 0
|
||||
#endif // SEEK_SET
|
||||
//------------------------------------------------------------------------------
|
||||
/** \class StdioStream
|
||||
* \brief StdioStream implements a minimal stdio stream.
|
||||
*
|
||||
* StdioStream does not support subdirectories or long file names.
|
||||
*/
|
||||
class StdioStream : private FatFile {
|
||||
public:
|
||||
/** Constructor
|
||||
*
|
||||
*/
|
||||
StdioStream() {
|
||||
m_w = m_r = 0;
|
||||
m_p = m_buf;
|
||||
m_status = 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Clear the stream's end-of-file and error indicators. */
|
||||
void clearerr() {
|
||||
m_status &= ~(S_ERR | S_EOF);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Close a stream.
|
||||
*
|
||||
* A successful call to the fclose function causes the stream to be
|
||||
* flushed and the associated file to be closed. Any unwritten buffered
|
||||
* data is written to the file; any unread buffered data is discarded.
|
||||
* Whether or not the call succeeds, the stream is disassociated from
|
||||
* the file.
|
||||
*
|
||||
* \return zero if the stream was successfully closed, or EOF if any any
|
||||
* errors are detected.
|
||||
*/
|
||||
int fclose();
|
||||
//----------------------------------------------------------------------------
|
||||
/** Test the stream's end-of-file indicator.
|
||||
* \return non-zero if and only if the end-of-file indicator is set.
|
||||
*/
|
||||
int feof() {
|
||||
return (m_status & S_EOF) != 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Test the stream's error indicator.
|
||||
* \return return non-zero if and only if the error indicator is set.
|
||||
*/
|
||||
int ferror() {
|
||||
return (m_status & S_ERR) != 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Flush the stream.
|
||||
*
|
||||
* If stream is an output stream or an update stream in which the most
|
||||
* recent operation was not input, any unwritten data is written to the
|
||||
* file; otherwise the call is an error since any buffered input data
|
||||
* would be lost.
|
||||
*
|
||||
* \return sets the error indicator for the stream and returns EOF if an
|
||||
* error occurs, otherwise it returns zero.
|
||||
*/
|
||||
int fflush();
|
||||
//----------------------------------------------------------------------------
|
||||
/** Get a byte from the stream.
|
||||
*
|
||||
* \return If the end-of-file indicator for the stream is set, or if the
|
||||
* stream is at end-of-file, the end-of-file indicator for the stream is
|
||||
* set and the fgetc function returns EOF. Otherwise, the fgetc function
|
||||
* returns the next character from the input stream.
|
||||
*/
|
||||
int fgetc() {
|
||||
return m_r-- == 0 ? fillGet() : *m_p++;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Get a string from a stream.
|
||||
*
|
||||
* The fgets function reads at most one less than the number of
|
||||
* characters specified by num from the stream into the array pointed
|
||||
* to by str. No additional characters are read after a new-line
|
||||
* character (which is retained) or after end-of-file. A null character
|
||||
* is written immediately after the last character read into the array.
|
||||
*
|
||||
* \param[out] str Pointer to an array of where the string is copied.
|
||||
*
|
||||
* \param[in] num Maximum number of characters including the null
|
||||
* character.
|
||||
*
|
||||
* \param[out] len If len is not null and fgets is successful, the
|
||||
* length of the string is returned.
|
||||
*
|
||||
* \return str if successful. If end-of-file is encountered and no
|
||||
* characters have been read into the array, the contents of the array
|
||||
* remain unchanged and a null pointer is returned. If a read error
|
||||
* occurs during the operation, the array contents are indeterminate
|
||||
* and a null pointer is returned.
|
||||
*/
|
||||
char* fgets(char* str, size_t num, size_t* len = 0);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Open a stream.
|
||||
*
|
||||
* Open a file and associates the stream with it.
|
||||
*
|
||||
* \param[in] path file to be opened.
|
||||
*
|
||||
* \param[in] mode a string that indicates the open mode.
|
||||
*
|
||||
* <table>
|
||||
* <tr>
|
||||
* <td>"r" or "rb"</td>
|
||||
* <td>Open a file for reading. The file must exist.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"w" or "wb"</td>
|
||||
* <td>Truncate an existing to zero length or create an empty file
|
||||
* for writing.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"wx" or "wbx"</td>
|
||||
* <td>Create a file for writing. Fails if the file already exists.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"a" or "ab"</td>
|
||||
* <td>Append; open or create file for writing at end-of-file.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"r+" or "rb+" or "r+b"</td>
|
||||
* <td>Open a file for update (reading and writing).</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"w+" or "w+b" or "wb+"</td>
|
||||
* <td>Truncate an existing to zero length or create a file for update.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"w+x" or "w+bx" or "wb+x"</td>
|
||||
* <td>Create a file for update. Fails if the file already exists.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>"a+" or "a+b" or "ab+"</td>
|
||||
* <td>Append; open or create a file for update, writing at end-of-file.</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
* The character 'b' shall have no effect, but is allowed for ISO C
|
||||
* standard conformance.
|
||||
*
|
||||
* Opening a file with append mode causes all subsequent writes to the
|
||||
* file to be forced to the then current end-of-file, regardless of
|
||||
* intervening calls to the fseek function.
|
||||
*
|
||||
* When a file is opened with update mode, both input and output may be
|
||||
* performed on the associated stream. However, output shall not be
|
||||
* directly followed by input without an intervening call to the fflush
|
||||
* function or to a file positioning function (fseek, or rewind), and
|
||||
* input shall not be directly followed by output without an intervening
|
||||
* call to a file positioning function, unless the input operation
|
||||
* encounters end-of-file.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool fopen(const char* path, const char * mode);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a byte to a stream.
|
||||
*
|
||||
* \param[in] c the byte to be written (converted to an unsigned char).
|
||||
*
|
||||
* \return Upon successful completion, fputc() returns the value it
|
||||
* has written. Otherwise, it returns EOF and sets the error indicator for
|
||||
* the stream.
|
||||
*/
|
||||
int fputc(int c) {
|
||||
return m_w-- == 0 ? flushPut(c) : *m_p++ = c;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a string to a stream.
|
||||
*
|
||||
* \param[in] str a pointer to the string to be written.
|
||||
*
|
||||
* \return for success, fputs() returns a non-negative
|
||||
* number. Otherwise, it returns EOF and sets the error indicator for
|
||||
* the stream.
|
||||
*/
|
||||
int fputs(const char* str);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Binary input.
|
||||
*
|
||||
* Reads an array of up to count elements, each one with a size of size
|
||||
* bytes.
|
||||
* \param[out] ptr pointer to area of at least (size*count) bytes where
|
||||
* the data will be stored.
|
||||
*
|
||||
* \param[in] size the size, in bytes, of each element to be read.
|
||||
*
|
||||
* \param[in] count the number of elements to be read.
|
||||
*
|
||||
* \return number of elements successfully read, which may be less than
|
||||
* count if a read error or end-of-file is encountered. If size or count
|
||||
* is zero, fread returns zero and the contents of the array and the
|
||||
* state of the stream remain unchanged.
|
||||
*/
|
||||
size_t fread(void* ptr, size_t size, size_t count);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set the file position for the stream.
|
||||
*
|
||||
* \param[in] offset number of offset from the origin.
|
||||
*
|
||||
* \param[in] origin position used as reference for the offset. It is
|
||||
* specified by one of the following constants.
|
||||
*
|
||||
* SEEK_SET - Beginning of file.
|
||||
*
|
||||
* SEEK_CUR - Current position of the file pointer.
|
||||
*
|
||||
* SEEK_END - End of file.
|
||||
*
|
||||
* \return zero for success. Otherwise, it returns non-zero and sets the
|
||||
* error indicator for the stream.
|
||||
*/
|
||||
int fseek(int32_t offset, int origin);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Get the current position in a stream.
|
||||
*
|
||||
* \return If successful, ftell return the current value of the position
|
||||
* indicator. On failure, ftell returns −1L.
|
||||
*/
|
||||
int32_t ftell();
|
||||
//----------------------------------------------------------------------------
|
||||
/** Binary output.
|
||||
*
|
||||
* Writes an array of up to count elements, each one with a size of size
|
||||
* bytes.
|
||||
* \param[in] ptr pointer to (size*count) bytes of data to be written.
|
||||
*
|
||||
* \param[in] size the size, in bytes, of each element to be written.
|
||||
*
|
||||
* \param[in] count the number of elements to be written.
|
||||
*
|
||||
* \return number of elements successfully written. if this number is
|
||||
* less than count, an error has occurred. If size or count is zero,
|
||||
* fwrite returns zero.
|
||||
*/
|
||||
size_t fwrite(const void * ptr, size_t size, size_t count);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Get a byte from the stream.
|
||||
*
|
||||
* getc and fgetc are equivalent but getc is in-line so it is faster but
|
||||
* require more flash memory.
|
||||
*
|
||||
* \return If the end-of-file indicator for the stream is set, or if the
|
||||
* stream is at end-of-file, the end-of-file indicator for the stream is
|
||||
* set and the fgetc function returns EOF. Otherwise, the fgetc function
|
||||
* returns the next character from the input stream.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
int getc() {
|
||||
return m_r-- == 0 ? fillGet() : *m_p++;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a byte to a stream.
|
||||
*
|
||||
* putc and fputc are equivalent but putc is in-line so it is faster but
|
||||
* require more flash memory.
|
||||
*
|
||||
* \param[in] c the byte to be written (converted to an unsigned char).
|
||||
*
|
||||
* \return Upon successful completion, fputc() returns the value it
|
||||
* has written. Otherwise, it returns EOF and sets the error indicator for
|
||||
* the stream.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
int putc(int c) {
|
||||
return m_w-- == 0 ? flushPut(c) : *m_p++ = c;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a CR/LF.
|
||||
*
|
||||
* \return two, the number of bytes written, for success or -1 for failure.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
int putCRLF() {
|
||||
if (m_w < 2) {
|
||||
if (!flushBuf()) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
*m_p++ = '\r';
|
||||
*m_p++ = '\n';
|
||||
m_w -= 2;
|
||||
return 2;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a character.
|
||||
* \param[in] c the character to write.
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t print(char c) {
|
||||
return putc(c) < 0 ? 0 : 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a string.
|
||||
*
|
||||
* \param[in] str the string to be written.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t print(const char* str) {
|
||||
int n = fputs(str);
|
||||
return n < 0 ? 0 : n;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
/** Print a string stored in flash memory.
|
||||
*
|
||||
* \param[in] str the string to print.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t print(const __FlashStringHelper *str);
|
||||
#endif // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a floating point number.
|
||||
*
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t print(double val, uint8_t prec = 2) {
|
||||
return print(static_cast<float>(val), prec);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a floating point number.
|
||||
*
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t print(float val, uint8_t prec = 2) {
|
||||
int n = printDec(val, prec);
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
template <typename T>
|
||||
size_t print(T val) {
|
||||
int n = printDec(val);
|
||||
return n > 0 ? n : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write a CR/LF.
|
||||
*
|
||||
* \return two, the number of bytes written, for success or zero for failure.
|
||||
*/
|
||||
size_t println() {
|
||||
return putCRLF() > 0 ? 2 : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a floating point number followed by CR/LF.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t println(double val, uint8_t prec = 2) {
|
||||
return println(static_cast<float>(val), prec);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a floating point number followed by CR/LF.
|
||||
*
|
||||
* \param[in] val the number to be printed.
|
||||
*
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
size_t println(float val, uint8_t prec = 2) {
|
||||
int n = printDec(val, prec);
|
||||
return n > 0 && putCRLF() > 0 ? n + 2 : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print an item followed by CR/LF
|
||||
*
|
||||
* \param[in] val the item to be printed.
|
||||
*
|
||||
* \return the number of bytes written.
|
||||
*/
|
||||
template <typename T>
|
||||
size_t println(T val) {
|
||||
int n = print(val);
|
||||
return putCRLF() > 0 ? n + 2 : 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a char as a number.
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(char n) {
|
||||
if (CHAR_MIN == 0) {
|
||||
return printDec((unsigned char)n);
|
||||
} else {
|
||||
return printDec((signed char)n);
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** print a signed 8-bit integer
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(signed char n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print an unsigned 8-bit number.
|
||||
* \param[in] n number to be print.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(unsigned char n) {
|
||||
return printDec((uint16_t)n);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a int16_t
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(int16_t n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** print a uint16_t.
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(uint16_t n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a signed 32-bit integer.
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(int32_t n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write an unsigned 32-bit number.
|
||||
* \param[in] n number to be printed.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(uint32_t n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a double.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(double value, uint8_t prec) {
|
||||
return printDec(static_cast<float>(value), prec);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a float.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printDec(float value, uint8_t prec);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printField(double value, char term, uint8_t prec = 2) {
|
||||
return printField(static_cast<float>(value), term, prec) > 0;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \param[in] prec Number of digits after decimal point.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printField(float value, char term, uint8_t prec = 2) {
|
||||
int rtn = printDec(value, prec);
|
||||
return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print a number followed by a field terminator.
|
||||
* \param[in] value The number to be printed.
|
||||
* \param[in] term The field terminator.
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
template <typename T>
|
||||
int printField(T value, char term) {
|
||||
int rtn = printDec(value);
|
||||
return rtn < 0 || putc(term) < 0 ? -1 : rtn + 1;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print HEX
|
||||
* \param[in] n number to be printed as HEX.
|
||||
*
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printHex(uint32_t n);
|
||||
//----------------------------------------------------------------------------
|
||||
/** Print HEX with CRLF
|
||||
* \param[in] n number to be printed as HEX.
|
||||
*
|
||||
* \return The number of bytes written or -1 if an error occurs.
|
||||
*/
|
||||
int printHexln(uint32_t n) {
|
||||
int rtn = printHex(n);
|
||||
return rtn < 0 || putCRLF() != 2 ? -1 : rtn + 2;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set position of a stream to the beginning.
|
||||
*
|
||||
* The rewind function sets the file position to the beginning of the
|
||||
* file. It is equivalent to fseek(0L, SEEK_SET) except that the error
|
||||
* indicator for the stream is also cleared.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool rewind();
|
||||
//----------------------------------------------------------------------------
|
||||
/** Push a byte back into an input stream.
|
||||
*
|
||||
* \param[in] c the byte (converted to an unsigned char) to be pushed back.
|
||||
*
|
||||
* One character of push-back is guaranteed. If the ungetc function is
|
||||
* called too many times without an intervening read or file positioning
|
||||
* operation on that stream, the operation may fail.
|
||||
*
|
||||
* A successful intervening call to a file positioning function (fseek,
|
||||
* fsetpos, or rewind) discards any pushed-back characters for the stream.
|
||||
*
|
||||
* \return Upon successful completion, ungetc() returns the byte pushed
|
||||
* back after conversion. Otherwise it returns EOF.
|
||||
*/
|
||||
int ungetc(int c);
|
||||
//============================================================================
|
||||
private:
|
||||
bool fillBuf();
|
||||
int fillGet();
|
||||
bool flushBuf();
|
||||
int flushPut(uint8_t c);
|
||||
char* fmtSpace(uint8_t len);
|
||||
int write(const void* buf, size_t count);
|
||||
//----------------------------------------------------------------------------
|
||||
// S_SRD and S_WR are never simultaneously asserted
|
||||
static const uint8_t S_SRD = 0x01; // OK to read
|
||||
static const uint8_t S_SWR = 0x02; // OK to write
|
||||
static const uint8_t S_SRW = 0x04; // open for reading & writing
|
||||
static const uint8_t S_EOF = 0x10; // found EOF
|
||||
static const uint8_t S_ERR = 0x20; // found error
|
||||
//----------------------------------------------------------------------------
|
||||
uint8_t m_status;
|
||||
uint8_t* m_p;
|
||||
uint8_t m_r;
|
||||
uint8_t m_w;
|
||||
uint8_t m_buf[STREAM_BUF_SIZE];
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#endif // StdioStream_h
|
172
hardware/sd_card_formatter/src/SdFat/FatLib/bufstream.h
Normal file
172
hardware/sd_card_formatter/src/SdFat/FatLib/bufstream.h
Normal file
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef bufstream_h
|
||||
#define bufstream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref ibufstream and \ref obufstream classes
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "iostream.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ibufstream
|
||||
* \brief parse a char string
|
||||
*/
|
||||
class ibufstream : public istream {
|
||||
public:
|
||||
/** Constructor */
|
||||
ibufstream() : m_buf(0), m_len(0) {}
|
||||
/** Constructor
|
||||
* \param[in] str pointer to string to be parsed
|
||||
* Warning: The string will not be copied so must stay in scope.
|
||||
*/
|
||||
explicit ibufstream(const char* str) {
|
||||
init(str);
|
||||
}
|
||||
/** Initialize an ibufstream
|
||||
* \param[in] str pointer to string to be parsed
|
||||
* Warning: The string will not be copied so must stay in scope.
|
||||
*/
|
||||
void init(const char* str) {
|
||||
m_buf = str;
|
||||
m_len = strlen(m_buf);
|
||||
m_pos = 0;
|
||||
clear();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
int16_t getch() {
|
||||
if (m_pos < m_len) {
|
||||
return m_buf[m_pos++];
|
||||
}
|
||||
setstate(eofbit);
|
||||
return -1;
|
||||
}
|
||||
void getpos(FatPos_t *pos) {
|
||||
pos->position = m_pos;
|
||||
}
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
(void)off;
|
||||
(void)way;
|
||||
return false;
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
if (pos < m_len) {
|
||||
m_pos = pos;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void setpos(FatPos_t *pos) {
|
||||
m_pos = pos->position;
|
||||
}
|
||||
pos_type tellpos() {
|
||||
return m_pos;
|
||||
}
|
||||
/// @endcond
|
||||
private:
|
||||
const char* m_buf;
|
||||
size_t m_len;
|
||||
size_t m_pos;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class obufstream
|
||||
* \brief format a char string
|
||||
*/
|
||||
class obufstream : public ostream {
|
||||
public:
|
||||
/** constructor */
|
||||
obufstream() : m_in(0) {}
|
||||
/** Constructor
|
||||
* \param[in] buf buffer for formatted string
|
||||
* \param[in] size buffer size
|
||||
*/
|
||||
obufstream(char *buf, size_t size) {
|
||||
init(buf, size);
|
||||
}
|
||||
/** Initialize an obufstream
|
||||
* \param[in] buf buffer for formatted string
|
||||
* \param[in] size buffer size
|
||||
*/
|
||||
void init(char *buf, size_t size) {
|
||||
m_buf = buf;
|
||||
buf[0] = '\0';
|
||||
m_size = size;
|
||||
m_in = 0;
|
||||
}
|
||||
/** \return a pointer to the buffer */
|
||||
char* buf() {
|
||||
return m_buf;
|
||||
}
|
||||
/** \return the length of the formatted string */
|
||||
size_t length() {
|
||||
return m_in;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
void putch(char c) {
|
||||
if (m_in >= (m_size - 1)) {
|
||||
setstate(badbit);
|
||||
return;
|
||||
}
|
||||
m_buf[m_in++] = c;
|
||||
m_buf[m_in] = '\0';
|
||||
}
|
||||
void putstr(const char *str) {
|
||||
while (*str) {
|
||||
putch(*str++);
|
||||
}
|
||||
}
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
(void)off;
|
||||
(void)way;
|
||||
return false;
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
if (pos > m_in) {
|
||||
return false;
|
||||
}
|
||||
m_in = pos;
|
||||
m_buf[m_in] = '\0';
|
||||
return true;
|
||||
}
|
||||
bool sync() {
|
||||
return true;
|
||||
}
|
||||
|
||||
pos_type tellpos() {
|
||||
return m_in;
|
||||
}
|
||||
/// @endcond
|
||||
private:
|
||||
char *m_buf;
|
||||
size_t m_size;
|
||||
size_t m_in;
|
||||
};
|
||||
#endif // bufstream_h
|
172
hardware/sd_card_formatter/src/SdFat/FatLib/fstream.cpp
Normal file
172
hardware/sd_card_formatter/src/SdFat/FatLib/fstream.cpp
Normal file
|
@ -0,0 +1,172 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "fstream.h"
|
||||
//==============================================================================
|
||||
/// @cond SHOW_PROTECTED
|
||||
int16_t FatStreamBase::getch() {
|
||||
uint8_t c;
|
||||
int8_t s = read(&c, 1);
|
||||
if (s != 1) {
|
||||
if (s < 0) {
|
||||
setstate(badbit);
|
||||
} else {
|
||||
setstate(eofbit);
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
if (c != '\r' || (getmode() & ios::binary)) {
|
||||
return c;
|
||||
}
|
||||
s = read(&c, 1);
|
||||
if (s == 1 && c == '\n') {
|
||||
return c;
|
||||
}
|
||||
if (s == 1) {
|
||||
seekCur(-1);
|
||||
}
|
||||
return '\r';
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatStreamBase::open(const char* path, ios::openmode mode) {
|
||||
oflag_t oflag;
|
||||
switch (mode & (app | in | out | trunc)) {
|
||||
case app | in:
|
||||
case app | in | out:
|
||||
oflag = O_RDWR | O_APPEND | O_CREAT;
|
||||
break;
|
||||
|
||||
case app:
|
||||
case app | out:
|
||||
oflag = O_WRONLY | O_APPEND | O_CREAT;
|
||||
break;
|
||||
|
||||
case in:
|
||||
oflag = O_RDONLY;
|
||||
break;
|
||||
|
||||
case in | out:
|
||||
oflag = O_RDWR;
|
||||
break;
|
||||
|
||||
case in | out | trunc:
|
||||
oflag = O_RDWR | O_TRUNC | O_CREAT;
|
||||
break;
|
||||
|
||||
case out:
|
||||
case out | trunc:
|
||||
oflag = O_WRONLY | O_TRUNC | O_CREAT;
|
||||
break;
|
||||
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
if (mode & ios::ate) {
|
||||
oflag |= O_AT_END;
|
||||
}
|
||||
if (!FatFile::open(path, oflag)) {
|
||||
goto fail;
|
||||
}
|
||||
setmode(mode);
|
||||
clear();
|
||||
return;
|
||||
|
||||
fail:
|
||||
FatFile::close();
|
||||
setstate(failbit);
|
||||
return;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatStreamBase::putch(char c) {
|
||||
if (c == '\n' && !(getmode() & ios::binary)) {
|
||||
write('\r');
|
||||
}
|
||||
write(c);
|
||||
if (getWriteError()) {
|
||||
setstate(badbit);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatStreamBase::putstr(const char* str) {
|
||||
size_t n = 0;
|
||||
while (1) {
|
||||
char c = str[n];
|
||||
if (c == '\0' || (c == '\n' && !(getmode() & ios::binary))) {
|
||||
if (n > 0) {
|
||||
write(str, n);
|
||||
}
|
||||
if (c == '\0') {
|
||||
break;
|
||||
}
|
||||
write('\r');
|
||||
str += n;
|
||||
n = 0;
|
||||
}
|
||||
n++;
|
||||
}
|
||||
if (getWriteError()) {
|
||||
setstate(badbit);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Internal do not use
|
||||
* \param[in] off
|
||||
* \param[in] way
|
||||
*/
|
||||
bool FatStreamBase::seekoff(off_type off, seekdir way) {
|
||||
pos_type pos;
|
||||
switch (way) {
|
||||
case beg:
|
||||
pos = off;
|
||||
break;
|
||||
|
||||
case cur:
|
||||
pos = curPosition() + off;
|
||||
break;
|
||||
|
||||
case end:
|
||||
pos = fileSize() + off;
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
return seekpos(pos);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Internal do not use
|
||||
* \param[in] pos
|
||||
*/
|
||||
bool FatStreamBase::seekpos(pos_type pos) {
|
||||
return seekSet(pos);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int FatStreamBase::write(const void* buf, size_t n) {
|
||||
return FatFile::write(buf, n);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void FatStreamBase::write(char c) {
|
||||
write(&c, 1);
|
||||
}
|
||||
/// @endcond
|
320
hardware/sd_card_formatter/src/SdFat/FatLib/fstream.h
Normal file
320
hardware/sd_card_formatter/src/SdFat/FatLib/fstream.h
Normal file
|
@ -0,0 +1,320 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef fstream_h
|
||||
#define fstream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref fstream, \ref ifstream, and \ref ofstream classes
|
||||
*/
|
||||
#include "FatFile.h"
|
||||
#include "iostream.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class FatStreamBase
|
||||
* \brief Base class for C++ style streams
|
||||
*/
|
||||
class FatStreamBase : protected FatFile, virtual public ios {
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
int16_t getch();
|
||||
void putch(char c);
|
||||
void putstr(const char *str);
|
||||
void open(const char* path, ios::openmode mode);
|
||||
/** Internal do not use
|
||||
* \return mode
|
||||
*/
|
||||
ios::openmode getmode() {
|
||||
return m_mode;
|
||||
}
|
||||
/** Internal do not use
|
||||
* \param[in] mode
|
||||
*/
|
||||
void setmode(ios::openmode mode) {
|
||||
m_mode = mode;
|
||||
}
|
||||
bool seekoff(off_type off, seekdir way);
|
||||
bool seekpos(pos_type pos);
|
||||
int write(const void* buf, size_t n);
|
||||
void write(char c);
|
||||
/// @endcond
|
||||
private:
|
||||
ios::openmode m_mode;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class fstream
|
||||
* \brief file input/output stream.
|
||||
*/
|
||||
class fstream : public iostream, FatStreamBase {
|
||||
public:
|
||||
using iostream::peek;
|
||||
fstream() {}
|
||||
/** Constructor with open
|
||||
*
|
||||
* \param[in] path path to open
|
||||
* \param[in] mode open mode
|
||||
*/
|
||||
explicit fstream(const char* path, openmode mode = in | out) {
|
||||
open(path, mode);
|
||||
}
|
||||
#if DESTRUCTOR_CLOSES_FILE
|
||||
~fstream() {}
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
/** Clear state and writeError
|
||||
* \param[in] state new state for stream
|
||||
*/
|
||||
void clear(iostate state = goodbit) {
|
||||
ios::clear(state);
|
||||
FatFile::clearWriteError();
|
||||
}
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() {
|
||||
FatFile::close();
|
||||
}
|
||||
/** Open a fstream
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
*
|
||||
* Valid open modes are (at end, ios::ate, and/or ios::binary may be added):
|
||||
*
|
||||
* ios::in - Open file for reading.
|
||||
*
|
||||
* ios::out or ios::out | ios::trunc - Truncate to 0 length, if existent,
|
||||
* or create a file for writing only.
|
||||
*
|
||||
* ios::app or ios::out | ios::app - Append; open or create file for
|
||||
* writing at end-of-file.
|
||||
*
|
||||
* ios::in | ios::out - Open file for update (reading and writing).
|
||||
*
|
||||
* ios::in | ios::out | ios::trunc - Truncate to zero length, if existent,
|
||||
* or create file for update.
|
||||
*
|
||||
* ios::in | ios::app or ios::in | ios::out | ios::app - Append; open or
|
||||
* create text file for update, writing at end of file.
|
||||
*/
|
||||
void open(const char* path, openmode mode = in | out) {
|
||||
FatStreamBase::open(path, mode);
|
||||
}
|
||||
/** \return True if stream is open else false. */
|
||||
bool is_open() {
|
||||
return FatFile::isOpen();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/** Internal - do not use
|
||||
* \return
|
||||
*/
|
||||
int16_t getch() {
|
||||
return FatStreamBase::getch();
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[out] pos
|
||||
*/
|
||||
void getpos(FatPos_t* pos) {
|
||||
FatFile::getpos(pos);
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[in] c
|
||||
*/
|
||||
void putch(char c) {
|
||||
FatStreamBase::putch(c);
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[in] str
|
||||
*/
|
||||
void putstr(const char *str) {
|
||||
FatStreamBase::putstr(str);
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[in] pos
|
||||
*/
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
return FatStreamBase::seekoff(off, way);
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
return FatStreamBase::seekpos(pos);
|
||||
}
|
||||
void setpos(FatPos_t* pos) {
|
||||
FatFile::setpos(pos);
|
||||
}
|
||||
bool sync() {
|
||||
return FatStreamBase::sync();
|
||||
}
|
||||
pos_type tellpos() {
|
||||
return FatStreamBase::curPosition();
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ifstream
|
||||
* \brief file input stream.
|
||||
*/
|
||||
class ifstream : public istream, FatStreamBase {
|
||||
public:
|
||||
using istream::peek;
|
||||
ifstream() {}
|
||||
/** Constructor with open
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
*/
|
||||
explicit ifstream(const char* path, openmode mode = in) {
|
||||
open(path, mode);
|
||||
}
|
||||
#if DESTRUCTOR_CLOSES_FILE
|
||||
~ifstream() {}
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() {
|
||||
FatFile::close();
|
||||
}
|
||||
/** \return True if stream is open else false. */
|
||||
bool is_open() {
|
||||
return FatFile::isOpen();
|
||||
}
|
||||
/** Open an ifstream
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
*
|
||||
* \a mode See fstream::open() for valid modes.
|
||||
*/
|
||||
void open(const char* path, openmode mode = in) {
|
||||
FatStreamBase::open(path, mode | in);
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/** Internal - do not use
|
||||
* \return
|
||||
*/
|
||||
int16_t getch() {
|
||||
return FatStreamBase::getch();
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[out] pos
|
||||
*/
|
||||
void getpos(FatPos_t* pos) {
|
||||
FatFile::getpos(pos);
|
||||
}
|
||||
/** Internal - do not use
|
||||
* \param[in] pos
|
||||
*/
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
return FatStreamBase::seekoff(off, way);
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
return FatStreamBase::seekpos(pos);
|
||||
}
|
||||
void setpos(FatPos_t* pos) {
|
||||
FatFile::setpos(pos);
|
||||
}
|
||||
pos_type tellpos() {
|
||||
return FatStreamBase::curPosition();
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ofstream
|
||||
* \brief file output stream.
|
||||
*/
|
||||
class ofstream : public ostream, FatStreamBase {
|
||||
public:
|
||||
ofstream() {}
|
||||
/** Constructor with open
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
*/
|
||||
explicit ofstream(const char* path, ios::openmode mode = out) {
|
||||
open(path, mode);
|
||||
}
|
||||
#if DESTRUCTOR_CLOSES_FILE
|
||||
~ofstream() {}
|
||||
#endif // DESTRUCTOR_CLOSES_FILE
|
||||
/** Clear state and writeError
|
||||
* \param[in] state new state for stream
|
||||
*/
|
||||
void clear(iostate state = goodbit) {
|
||||
ios::clear(state);
|
||||
FatFile::clearWriteError();
|
||||
}
|
||||
/** Close a file and force cached data and directory information
|
||||
* to be written to the storage device.
|
||||
*/
|
||||
void close() {
|
||||
FatFile::close();
|
||||
}
|
||||
/** Open an ofstream
|
||||
* \param[in] path file to open
|
||||
* \param[in] mode open mode
|
||||
*
|
||||
* \a mode See fstream::open() for valid modes.
|
||||
*/
|
||||
void open(const char* path, openmode mode = out) {
|
||||
FatStreamBase::open(path, mode | out);
|
||||
}
|
||||
/** \return True if stream is open else false. */
|
||||
bool is_open() {
|
||||
return FatFile::isOpen();
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/**
|
||||
* Internal do not use
|
||||
* \param[in] c
|
||||
*/
|
||||
void putch(char c) {
|
||||
FatStreamBase::putch(c);
|
||||
}
|
||||
void putstr(const char* str) {
|
||||
FatStreamBase::putstr(str);
|
||||
}
|
||||
bool seekoff(off_type off, seekdir way) {
|
||||
return FatStreamBase::seekoff(off, way);
|
||||
}
|
||||
bool seekpos(pos_type pos) {
|
||||
return FatStreamBase::seekpos(pos);
|
||||
}
|
||||
/**
|
||||
* Internal do not use
|
||||
* \param[in] b
|
||||
*/
|
||||
bool sync() {
|
||||
return FatStreamBase::sync();
|
||||
}
|
||||
pos_type tellpos() {
|
||||
return FatStreamBase::curPosition();
|
||||
}
|
||||
/// @endcond
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#endif // fstream_h
|
423
hardware/sd_card_formatter/src/SdFat/FatLib/ios.h
Normal file
423
hardware/sd_card_formatter/src/SdFat/FatLib/ios.h
Normal file
|
@ -0,0 +1,423 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ios_h
|
||||
#define ios_h
|
||||
#include "FatFile.h"
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref ios_base and \ref ios classes
|
||||
*/
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ios_base
|
||||
* \brief Base class for all streams
|
||||
*/
|
||||
class ios_base {
|
||||
public:
|
||||
/** typedef for iostate bitmask */
|
||||
typedef unsigned char iostate;
|
||||
// State flags.
|
||||
/** iostate for no flags */
|
||||
static const iostate goodbit = 0x00;
|
||||
/** iostate bad bit for a nonrecoverable error. */
|
||||
static const iostate badbit = 0X01;
|
||||
/** iostate bit for end of file reached */
|
||||
static const iostate eofbit = 0x02;
|
||||
/** iostate fail bit for nonfatal error */
|
||||
static const iostate failbit = 0X04;
|
||||
/**
|
||||
* unsigned size that can represent maximum file size.
|
||||
* (violates spec - should be signed)
|
||||
*/
|
||||
typedef uint32_t streamsize;
|
||||
/** type for absolute seek position */
|
||||
typedef uint32_t pos_type;
|
||||
/** type for relative seek offset */
|
||||
typedef int32_t off_type;
|
||||
|
||||
/** enumerated type for the direction of relative seeks */
|
||||
enum seekdir {
|
||||
/** seek relative to the beginning of the stream */
|
||||
beg,
|
||||
/** seek relative to the current stream position */
|
||||
cur,
|
||||
/** seek relative to the end of the stream */
|
||||
end
|
||||
};
|
||||
/** type for format flags */
|
||||
typedef unsigned int fmtflags;
|
||||
/** left adjust fields */
|
||||
static const fmtflags left = 0x0001;
|
||||
/** right adjust fields */
|
||||
static const fmtflags right = 0x0002;
|
||||
/** fill between sign/base prefix and number */
|
||||
static const fmtflags internal = 0x0004;
|
||||
/** base 10 flag*/
|
||||
static const fmtflags dec = 0x0008;
|
||||
/** base 16 flag */
|
||||
static const fmtflags hex = 0x0010;
|
||||
/** base 8 flag */
|
||||
static const fmtflags oct = 0x0020;
|
||||
// static const fmtflags fixed = 0x0040;
|
||||
// static const fmtflags scientific = 0x0080;
|
||||
/** use strings true/false for bool */
|
||||
static const fmtflags boolalpha = 0x0100;
|
||||
/** use prefix 0X for hex and 0 for oct */
|
||||
static const fmtflags showbase = 0x0200;
|
||||
/** always show '.' for floating numbers */
|
||||
static const fmtflags showpoint = 0x0400;
|
||||
/** show + sign for nonnegative numbers */
|
||||
static const fmtflags showpos = 0x0800;
|
||||
/** skip initial white space */
|
||||
static const fmtflags skipws = 0x1000;
|
||||
// static const fmtflags unitbuf = 0x2000;
|
||||
/** use uppercase letters in number representations */
|
||||
static const fmtflags uppercase = 0x4000;
|
||||
/** mask for adjustfield */
|
||||
static const fmtflags adjustfield = left | right | internal;
|
||||
/** mask for basefield */
|
||||
static const fmtflags basefield = dec | hex | oct;
|
||||
// static const fmtflags floatfield = scientific | fixed;
|
||||
//----------------------------------------------------------------------------
|
||||
/** typedef for iostream open mode */
|
||||
typedef uint8_t openmode;
|
||||
|
||||
// Openmode flags.
|
||||
/** seek to end before each write */
|
||||
static const openmode app = 0X4;
|
||||
/** open and seek to end immediately after opening */
|
||||
static const openmode ate = 0X8;
|
||||
/** perform input and output in binary mode (as opposed to text mode) */
|
||||
static const openmode binary = 0X10;
|
||||
/** open for input */
|
||||
static const openmode in = 0X20;
|
||||
/** open for output */
|
||||
static const openmode out = 0X40;
|
||||
/** truncate an existing stream when opening */
|
||||
static const openmode trunc = 0X80;
|
||||
//----------------------------------------------------------------------------
|
||||
ios_base() : m_fill(' '), m_fmtflags(dec | right | skipws)
|
||||
, m_precision(2), m_width(0) {}
|
||||
/** \return fill character */
|
||||
char fill() {
|
||||
return m_fill;
|
||||
}
|
||||
/** Set fill character
|
||||
* \param[in] c new fill character
|
||||
* \return old fill character
|
||||
*/
|
||||
char fill(char c) {
|
||||
char r = m_fill;
|
||||
m_fill = c;
|
||||
return r;
|
||||
}
|
||||
/** \return format flags */
|
||||
fmtflags flags() const {
|
||||
return m_fmtflags;
|
||||
}
|
||||
/** set format flags
|
||||
* \param[in] fl new flag
|
||||
* \return old flags
|
||||
*/
|
||||
fmtflags flags(fmtflags fl) {
|
||||
fmtflags tmp = m_fmtflags;
|
||||
m_fmtflags = fl;
|
||||
return tmp;
|
||||
}
|
||||
/** \return precision */
|
||||
int precision() const {
|
||||
return m_precision;
|
||||
}
|
||||
/** set precision
|
||||
* \param[in] n new precision
|
||||
* \return old precision
|
||||
*/
|
||||
int precision(unsigned int n) {
|
||||
int r = m_precision;
|
||||
m_precision = n;
|
||||
return r;
|
||||
}
|
||||
/** set format flags
|
||||
* \param[in] fl new flags to be or'ed in
|
||||
* \return old flags
|
||||
*/
|
||||
fmtflags setf(fmtflags fl) {
|
||||
fmtflags r = m_fmtflags;
|
||||
m_fmtflags |= fl;
|
||||
return r;
|
||||
}
|
||||
/** modify format flags
|
||||
* \param[in] mask flags to be removed
|
||||
* \param[in] fl flags to be set after mask bits have been cleared
|
||||
* \return old flags
|
||||
*/
|
||||
fmtflags setf(fmtflags fl, fmtflags mask) {
|
||||
fmtflags r = m_fmtflags;
|
||||
m_fmtflags &= ~mask;
|
||||
m_fmtflags |= fl;
|
||||
return r;
|
||||
}
|
||||
/** clear format flags
|
||||
* \param[in] fl flags to be cleared
|
||||
* \return old flags
|
||||
*/
|
||||
void unsetf(fmtflags fl) {
|
||||
m_fmtflags &= ~fl;
|
||||
}
|
||||
/** \return width */
|
||||
unsigned width() {
|
||||
return m_width;
|
||||
}
|
||||
/** set width
|
||||
* \param[in] n new width
|
||||
* \return old width
|
||||
*/
|
||||
unsigned width(unsigned n) {
|
||||
unsigned r = m_width;
|
||||
m_width = n;
|
||||
return r;
|
||||
}
|
||||
|
||||
protected:
|
||||
/** \return current number base */
|
||||
uint8_t flagsToBase() {
|
||||
uint8_t f = flags() & basefield;
|
||||
return f == oct ? 8 : f != hex ? 10 : 16;
|
||||
}
|
||||
|
||||
private:
|
||||
char m_fill;
|
||||
fmtflags m_fmtflags;
|
||||
unsigned char m_precision;
|
||||
unsigned int m_width;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/** function for boolalpha manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& boolalpha(ios_base& str) {
|
||||
str.setf(ios_base::boolalpha);
|
||||
return str;
|
||||
}
|
||||
/** function for dec manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& dec(ios_base& str) {
|
||||
str.setf(ios_base::dec, ios_base::basefield);
|
||||
return str;
|
||||
}
|
||||
/** function for hex manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& hex(ios_base& str) {
|
||||
str.setf(ios_base::hex, ios_base::basefield);
|
||||
return str;
|
||||
}
|
||||
/** function for internal manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& internal(ios_base& str) {
|
||||
str.setf(ios_base::internal, ios_base::adjustfield);
|
||||
return str;
|
||||
}
|
||||
/** function for left manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& left(ios_base& str) {
|
||||
str.setf(ios_base::left, ios_base::adjustfield);
|
||||
return str;
|
||||
}
|
||||
/** function for noboolalpha manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& noboolalpha(ios_base& str) {
|
||||
str.unsetf(ios_base::boolalpha);
|
||||
return str;
|
||||
}
|
||||
/** function for noshowbase manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& noshowbase(ios_base& str) {
|
||||
str.unsetf(ios_base::showbase);
|
||||
return str;
|
||||
}
|
||||
/** function for noshowpoint manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& noshowpoint(ios_base& str) {
|
||||
str.unsetf(ios_base::showpoint);
|
||||
return str;
|
||||
}
|
||||
/** function for noshowpos manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& noshowpos(ios_base& str) {
|
||||
str.unsetf(ios_base::showpos);
|
||||
return str;
|
||||
}
|
||||
/** function for noskipws manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& noskipws(ios_base& str) {
|
||||
str.unsetf(ios_base::skipws);
|
||||
return str;
|
||||
}
|
||||
/** function for nouppercase manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& nouppercase(ios_base& str) {
|
||||
str.unsetf(ios_base::uppercase);
|
||||
return str;
|
||||
}
|
||||
/** function for oct manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& oct(ios_base& str) {
|
||||
str.setf(ios_base::oct, ios_base::basefield);
|
||||
return str;
|
||||
}
|
||||
/** function for right manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& right(ios_base& str) {
|
||||
str.setf(ios_base::right, ios_base::adjustfield);
|
||||
return str;
|
||||
}
|
||||
/** function for showbase manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& showbase(ios_base& str) {
|
||||
str.setf(ios_base::showbase);
|
||||
return str;
|
||||
}
|
||||
/** function for showpos manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& showpos(ios_base& str) {
|
||||
str.setf(ios_base::showpos);
|
||||
return str;
|
||||
}
|
||||
/** function for showpoint manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& showpoint(ios_base& str) {
|
||||
str.setf(ios_base::showpoint);
|
||||
return str;
|
||||
}
|
||||
/** function for skipws manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& skipws(ios_base& str) {
|
||||
str.setf(ios_base::skipws);
|
||||
return str;
|
||||
}
|
||||
/** function for uppercase manipulator
|
||||
* \param[in] str The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ios_base& uppercase(ios_base& str) {
|
||||
str.setf(ios_base::uppercase);
|
||||
return str;
|
||||
}
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ios
|
||||
* \brief Error and state information for all streams
|
||||
*/
|
||||
class ios : public ios_base {
|
||||
public:
|
||||
/** Create ios with no error flags set */
|
||||
ios() : m_iostate(0) {}
|
||||
|
||||
/** \return null pointer if fail() is true. */
|
||||
operator const void*() const {
|
||||
return !fail() ? reinterpret_cast<const void*>(this) : 0;
|
||||
}
|
||||
/** \return true if fail() else false. */
|
||||
bool operator!() const {
|
||||
return fail();
|
||||
}
|
||||
/** \return The iostate flags for this file. */
|
||||
iostate rdstate() const {
|
||||
return m_iostate;
|
||||
}
|
||||
/** \return True if no iostate flags are set else false. */
|
||||
bool good() const {
|
||||
return m_iostate == goodbit;
|
||||
}
|
||||
/** \return true if end of file has been reached else false.
|
||||
*
|
||||
* Warning: An empty file returns false before the first read.
|
||||
*
|
||||
* Moral: eof() is only useful in combination with fail(), to find out
|
||||
* whether EOF was the cause for failure
|
||||
*/
|
||||
bool eof() const {
|
||||
return m_iostate & eofbit;
|
||||
}
|
||||
/** \return true if any iostate bit other than eof are set else false. */
|
||||
bool fail() const {
|
||||
return m_iostate & (failbit | badbit);
|
||||
}
|
||||
/** \return true if bad bit is set else false. */
|
||||
bool bad() const {
|
||||
return m_iostate & badbit;
|
||||
}
|
||||
/** Clear iostate bits.
|
||||
*
|
||||
* \param[in] state The flags you want to set after clearing all flags.
|
||||
**/
|
||||
void clear(iostate state = goodbit) {
|
||||
m_iostate = state;
|
||||
}
|
||||
/** Set iostate bits.
|
||||
*
|
||||
* \param[in] state Bitts to set.
|
||||
**/
|
||||
void setstate(iostate state) {
|
||||
m_iostate |= state;
|
||||
}
|
||||
|
||||
private:
|
||||
iostate m_iostate;
|
||||
};
|
||||
#endif // ios_h
|
158
hardware/sd_card_formatter/src/SdFat/FatLib/iostream.h
Normal file
158
hardware/sd_card_formatter/src/SdFat/FatLib/iostream.h
Normal file
|
@ -0,0 +1,158 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef iostream_h
|
||||
#define iostream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref iostream class
|
||||
*/
|
||||
#include "istream.h"
|
||||
#include "ostream.h"
|
||||
/** Skip white space
|
||||
* \param[in] is the Stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline istream& ws(istream& is) {
|
||||
is.skipWhite();
|
||||
return is;
|
||||
}
|
||||
/** insert endline
|
||||
* \param[in] os The Stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ostream& endl(ostream& os) {
|
||||
os.put('\n');
|
||||
#if ENDL_CALLS_FLUSH
|
||||
os.flush();
|
||||
#endif // ENDL_CALLS_FLUSH
|
||||
return os;
|
||||
}
|
||||
/** flush manipulator
|
||||
* \param[in] os The stream
|
||||
* \return The stream
|
||||
*/
|
||||
inline ostream& flush(ostream& os) {
|
||||
os.flush();
|
||||
return os;
|
||||
}
|
||||
/**
|
||||
* \struct setfill
|
||||
* \brief type for setfill manipulator
|
||||
*/
|
||||
struct setfill {
|
||||
/** fill character */
|
||||
char c;
|
||||
/** constructor
|
||||
*
|
||||
* \param[in] arg new fill character
|
||||
*/
|
||||
explicit setfill(char arg) : c(arg) {}
|
||||
};
|
||||
/** setfill manipulator
|
||||
* \param[in] os the stream
|
||||
* \param[in] arg set setfill object
|
||||
* \return the stream
|
||||
*/
|
||||
inline ostream &operator<< (ostream &os, const setfill &arg) {
|
||||
os.fill(arg.c);
|
||||
return os;
|
||||
}
|
||||
/** setfill manipulator
|
||||
* \param[in] obj the stream
|
||||
* \param[in] arg set setfill object
|
||||
* \return the stream
|
||||
*/
|
||||
inline istream &operator>>(istream &obj, const setfill &arg) {
|
||||
obj.fill(arg.c);
|
||||
return obj;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** \struct setprecision
|
||||
* \brief type for setprecision manipulator
|
||||
*/
|
||||
struct setprecision {
|
||||
/** precision */
|
||||
unsigned int p;
|
||||
/** constructor
|
||||
* \param[in] arg new precision
|
||||
*/
|
||||
explicit setprecision(unsigned int arg) : p(arg) {}
|
||||
};
|
||||
/** setprecision manipulator
|
||||
* \param[in] os the stream
|
||||
* \param[in] arg set setprecision object
|
||||
* \return the stream
|
||||
*/
|
||||
inline ostream &operator<< (ostream &os, const setprecision &arg) {
|
||||
os.precision(arg.p);
|
||||
return os;
|
||||
}
|
||||
/** setprecision manipulator
|
||||
* \param[in] is the stream
|
||||
* \param[in] arg set setprecision object
|
||||
* \return the stream
|
||||
*/
|
||||
inline istream &operator>>(istream &is, const setprecision &arg) {
|
||||
is.precision(arg.p);
|
||||
return is;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** \struct setw
|
||||
* \brief type for setw manipulator
|
||||
*/
|
||||
struct setw {
|
||||
/** width */
|
||||
unsigned w;
|
||||
/** constructor
|
||||
* \param[in] arg new width
|
||||
*/
|
||||
explicit setw(unsigned arg) : w(arg) {}
|
||||
};
|
||||
/** setw manipulator
|
||||
* \param[in] os the stream
|
||||
* \param[in] arg set setw object
|
||||
* \return the stream
|
||||
*/
|
||||
inline ostream &operator<< (ostream &os, const setw &arg) {
|
||||
os.width(arg.w);
|
||||
return os;
|
||||
}
|
||||
/** setw manipulator
|
||||
* \param[in] is the stream
|
||||
* \param[in] arg set setw object
|
||||
* \return the stream
|
||||
*/
|
||||
inline istream &operator>>(istream &is, const setw &arg) {
|
||||
is.width(arg.w);
|
||||
return is;
|
||||
}
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class iostream
|
||||
* \brief Input/Output stream
|
||||
*/
|
||||
class iostream : public istream, public ostream {
|
||||
};
|
||||
#endif // iostream_h
|
396
hardware/sd_card_formatter/src/SdFat/FatLib/istream.cpp
Normal file
396
hardware/sd_card_formatter/src/SdFat/FatLib/istream.cpp
Normal file
|
@ -0,0 +1,396 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
// #include <ctype.h>
|
||||
#include <float.h>
|
||||
#include <ctype.h>
|
||||
#include "istream.h"
|
||||
//------------------------------------------------------------------------------
|
||||
int istream::get() {
|
||||
int c;
|
||||
m_gcount = 0;
|
||||
c = getch();
|
||||
if (c < 0) {
|
||||
setstate(failbit);
|
||||
} else {
|
||||
m_gcount = 1;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
istream& istream::get(char& c) {
|
||||
int tmp = get();
|
||||
if (tmp >= 0) {
|
||||
c = tmp;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
istream& istream::get(char *str, streamsize n, char delim) {
|
||||
int c;
|
||||
FatPos_t pos;
|
||||
m_gcount = 0;
|
||||
while ((m_gcount + 1) < n) {
|
||||
c = getch(&pos);
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
if (c == delim) {
|
||||
setpos(&pos);
|
||||
break;
|
||||
}
|
||||
str[m_gcount++] = c;
|
||||
}
|
||||
if (n > 0) {
|
||||
str[m_gcount] = '\0';
|
||||
}
|
||||
if (m_gcount == 0) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void istream::getBool(bool *b) {
|
||||
if ((flags() & boolalpha) == 0) {
|
||||
getNumber(b);
|
||||
return;
|
||||
}
|
||||
#ifdef __AVR__
|
||||
PGM_P truePtr = PSTR("true");
|
||||
PGM_P falsePtr = PSTR("false");
|
||||
#else // __AVR__
|
||||
const char* truePtr = "true";
|
||||
const char* falsePtr = "false";
|
||||
#endif // __AVR
|
||||
const uint8_t true_len = 4;
|
||||
const uint8_t false_len = 5;
|
||||
bool trueOk = true;
|
||||
bool falseOk = true;
|
||||
uint8_t i = 0;
|
||||
int c = readSkip();
|
||||
while (1) {
|
||||
#ifdef __AVR__
|
||||
falseOk = falseOk && c == pgm_read_byte(falsePtr + i);
|
||||
trueOk = trueOk && c == pgm_read_byte(truePtr + i);
|
||||
#else // __AVR__
|
||||
falseOk = falseOk && c == falsePtr[i];
|
||||
trueOk = trueOk && c == truePtr[i];
|
||||
#endif // __AVR__
|
||||
if (trueOk == false && falseOk == false) {
|
||||
break;
|
||||
}
|
||||
i++;
|
||||
if (trueOk && i == true_len) {
|
||||
*b = true;
|
||||
return;
|
||||
}
|
||||
if (falseOk && i == false_len) {
|
||||
*b = false;
|
||||
return;
|
||||
}
|
||||
c = getch();
|
||||
}
|
||||
setstate(failbit);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void istream::getChar(char* ch) {
|
||||
int16_t c = readSkip();
|
||||
if (c < 0) {
|
||||
setstate(failbit);
|
||||
} else {
|
||||
*ch = c;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
//
|
||||
// http://www.exploringbinary.com/category/numbers-in-computers/
|
||||
//
|
||||
int16_t const EXP_LIMIT = 100;
|
||||
static const uint32_t uint32_max = (uint32_t)-1;
|
||||
bool istream::getDouble(double* value) {
|
||||
bool got_digit = false;
|
||||
bool got_dot = false;
|
||||
bool neg;
|
||||
int16_t c;
|
||||
bool expNeg = false;
|
||||
int16_t exp = 0;
|
||||
int16_t fracExp = 0;
|
||||
uint32_t frac = 0;
|
||||
FatPos_t endPos;
|
||||
double pow10;
|
||||
double v;
|
||||
|
||||
getpos(&endPos);
|
||||
c = readSkip();
|
||||
neg = c == '-';
|
||||
if (c == '-' || c == '+') {
|
||||
c = getch();
|
||||
}
|
||||
while (1) {
|
||||
if (isdigit(c)) {
|
||||
got_digit = true;
|
||||
if (frac < uint32_max/10) {
|
||||
frac = frac * 10 + (c - '0');
|
||||
if (got_dot) {
|
||||
fracExp--;
|
||||
}
|
||||
} else {
|
||||
if (!got_dot) {
|
||||
fracExp++;
|
||||
}
|
||||
}
|
||||
} else if (!got_dot && c == '.') {
|
||||
got_dot = true;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (fracExp < -EXP_LIMIT || fracExp > EXP_LIMIT) {
|
||||
goto fail;
|
||||
}
|
||||
c = getch(&endPos);
|
||||
}
|
||||
if (!got_digit) {
|
||||
goto fail;
|
||||
}
|
||||
if (c == 'e' || c == 'E') {
|
||||
c = getch();
|
||||
expNeg = c == '-';
|
||||
if (c == '-' || c == '+') {
|
||||
c = getch();
|
||||
}
|
||||
while (isdigit(c)) {
|
||||
if (exp > EXP_LIMIT) {
|
||||
goto fail;
|
||||
}
|
||||
exp = exp * 10 + (c - '0');
|
||||
c = getch(&endPos);
|
||||
}
|
||||
}
|
||||
v = static_cast<double>(frac);
|
||||
exp = expNeg ? fracExp - exp : fracExp + exp;
|
||||
expNeg = exp < 0;
|
||||
if (expNeg) {
|
||||
exp = -exp;
|
||||
}
|
||||
pow10 = 10.0;
|
||||
while (exp) {
|
||||
if (exp & 1) {
|
||||
if (expNeg) {
|
||||
// check for underflow
|
||||
if (v < FLT_MIN * pow10 && frac != 0) {
|
||||
goto fail;
|
||||
}
|
||||
v /= pow10;
|
||||
} else {
|
||||
// check for overflow
|
||||
if (v > FLT_MAX / pow10) {
|
||||
goto fail;
|
||||
}
|
||||
v *= pow10;
|
||||
}
|
||||
}
|
||||
pow10 *= pow10;
|
||||
exp >>= 1;
|
||||
}
|
||||
setpos(&endPos);
|
||||
*value = neg ? -v : v;
|
||||
return true;
|
||||
|
||||
fail:
|
||||
// error restore position to last good place
|
||||
setpos(&endPos);
|
||||
setstate(failbit);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
istream& istream::getline(char *str, streamsize n, char delim) {
|
||||
FatPos_t pos;
|
||||
int c;
|
||||
m_gcount = 0;
|
||||
if (n > 0) {
|
||||
str[0] = '\0';
|
||||
}
|
||||
while (1) {
|
||||
c = getch(&pos);
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
if (c == delim) {
|
||||
m_gcount++;
|
||||
break;
|
||||
}
|
||||
if ((m_gcount + 1) >= n) {
|
||||
setpos(&pos);
|
||||
setstate(failbit);
|
||||
break;
|
||||
}
|
||||
str[m_gcount++] = c;
|
||||
str[m_gcount] = '\0';
|
||||
}
|
||||
if (m_gcount == 0) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool istream::getNumber(uint32_t posMax, uint32_t negMax, uint32_t* num) {
|
||||
int16_t c;
|
||||
int8_t any = 0;
|
||||
int8_t have_zero = 0;
|
||||
uint8_t neg;
|
||||
uint32_t val = 0;
|
||||
uint32_t cutoff;
|
||||
uint8_t cutlim;
|
||||
FatPos_t endPos;
|
||||
uint8_t f = flags() & basefield;
|
||||
uint8_t base = f == oct ? 8 : f != hex ? 10 : 16;
|
||||
getpos(&endPos);
|
||||
c = readSkip();
|
||||
|
||||
neg = c == '-' ? 1 : 0;
|
||||
if (c == '-' || c == '+') {
|
||||
c = getch();
|
||||
}
|
||||
|
||||
if (base == 16 && c == '0') { // TESTSUITE
|
||||
c = getch(&endPos);
|
||||
if (c == 'X' || c == 'x') {
|
||||
c = getch();
|
||||
// remember zero in case no hex digits follow x/X
|
||||
have_zero = 1;
|
||||
} else {
|
||||
any = 1;
|
||||
}
|
||||
}
|
||||
// set values for overflow test
|
||||
cutoff = neg ? negMax : posMax;
|
||||
cutlim = cutoff % base;
|
||||
cutoff /= base;
|
||||
|
||||
while (1) {
|
||||
if (isdigit(c)) {
|
||||
c -= '0';
|
||||
} else if (isalpha(c)) {
|
||||
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
if (c >= base) {
|
||||
break;
|
||||
}
|
||||
if (val > cutoff || (val == cutoff && c > cutlim)) {
|
||||
// indicate overflow error
|
||||
any = -1;
|
||||
break;
|
||||
}
|
||||
val = val * base + c;
|
||||
c = getch(&endPos);
|
||||
any = 1;
|
||||
}
|
||||
setpos(&endPos);
|
||||
if (any > 0 || (have_zero && any >= 0)) {
|
||||
*num = neg ? -val : val;
|
||||
return true;
|
||||
}
|
||||
setstate(failbit);
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void istream::getStr(char *str) {
|
||||
FatPos_t pos;
|
||||
uint16_t i = 0;
|
||||
uint16_t m = width() ? width() - 1 : 0XFFFE;
|
||||
if (m != 0) {
|
||||
getpos(&pos);
|
||||
int c = readSkip();
|
||||
|
||||
while (i < m) {
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
if (isspace(c)) {
|
||||
setpos(&pos);
|
||||
break;
|
||||
}
|
||||
str[i++] = c;
|
||||
c = getch(&pos);
|
||||
}
|
||||
}
|
||||
str[i] = '\0';
|
||||
if (i == 0) {
|
||||
setstate(failbit);
|
||||
}
|
||||
width(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
istream& istream::ignore(streamsize n, int delim) {
|
||||
int c;
|
||||
m_gcount = 0;
|
||||
while (m_gcount < n) {
|
||||
c = getch();
|
||||
if (c < 0) {
|
||||
break;
|
||||
}
|
||||
m_gcount++;
|
||||
if (c == delim) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int istream::peek() {
|
||||
int16_t c;
|
||||
FatPos_t pos;
|
||||
m_gcount = 0;
|
||||
getpos(&pos);
|
||||
c = getch();
|
||||
if (c < 0) {
|
||||
if (!bad()) {
|
||||
setstate(eofbit);
|
||||
}
|
||||
} else {
|
||||
setpos(&pos);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int16_t istream::readSkip() {
|
||||
int16_t c;
|
||||
do {
|
||||
c = getch();
|
||||
} while (isspace(c) && (flags() & skipws));
|
||||
return c;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** used to implement ws() */
|
||||
void istream::skipWhite() {
|
||||
int c;
|
||||
FatPos_t pos;
|
||||
do {
|
||||
c = getch(&pos);
|
||||
} while (isspace(c));
|
||||
setpos(&pos);
|
||||
}
|
384
hardware/sd_card_formatter/src/SdFat/FatLib/istream.h
Normal file
384
hardware/sd_card_formatter/src/SdFat/FatLib/istream.h
Normal file
|
@ -0,0 +1,384 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef istream_h
|
||||
#define istream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref istream class
|
||||
*/
|
||||
#include "ios.h"
|
||||
|
||||
/**
|
||||
* \class istream
|
||||
* \brief Input Stream
|
||||
*/
|
||||
class istream : public virtual ios {
|
||||
public:
|
||||
istream() {}
|
||||
/** call manipulator
|
||||
* \param[in] pf function to call
|
||||
* \return the stream
|
||||
*/
|
||||
istream& operator>>(istream& (*pf)(istream& str)) {
|
||||
return pf(*this);
|
||||
}
|
||||
/** call manipulator
|
||||
* \param[in] pf function to call
|
||||
* \return the stream
|
||||
*/
|
||||
istream& operator>>(ios_base& (*pf)(ios_base& str)) {
|
||||
pf(*this);
|
||||
return *this;
|
||||
}
|
||||
/** call manipulator
|
||||
* \param[in] pf function to call
|
||||
* \return the stream
|
||||
*/
|
||||
istream& operator>>(ios& (*pf)(ios& str)) {
|
||||
pf(*this);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character string
|
||||
* \param[out] str location to store the string.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(char *str) {
|
||||
getStr(str);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character
|
||||
* \param[out] ch location to store the character.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(char& ch) {
|
||||
getChar(&ch);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character string
|
||||
* \param[out] str location to store the string.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(signed char *str) {
|
||||
getStr(reinterpret_cast<char*>(str));
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character
|
||||
* \param[out] ch location to store the character.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(signed char& ch) {
|
||||
getChar(reinterpret_cast<char*>(&ch));
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character string
|
||||
* \param[out] str location to store the string.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(unsigned char *str) {
|
||||
getStr(reinterpret_cast<char*>(str));
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a character
|
||||
* \param[out] ch location to store the character.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(unsigned char& ch) {
|
||||
getChar(reinterpret_cast<char*>(&ch));
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type bool.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>>(bool& arg) {
|
||||
getBool(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type short.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(short& arg) { // NOLINT
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type unsigned short.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(unsigned short& arg) { // NOLINT
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type int.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(int& arg) {
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type unsigned int.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(unsigned int& arg) {
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type long.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(long& arg) { // NOLINT
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type unsigned long.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>>(unsigned long& arg) { // NOLINT
|
||||
getNumber(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type double.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>> (double& arg) {
|
||||
getDouble(&arg);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type float.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream &operator>> (float& arg) {
|
||||
double v;
|
||||
getDouble(&v);
|
||||
arg = v;
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Extract a value of type void*.
|
||||
* \param[out] arg location to store the value.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& operator>> (void*& arg) {
|
||||
uint32_t val;
|
||||
getNumber(&val);
|
||||
arg = reinterpret_cast<void*>(val);
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* \return The number of characters extracted by the last unformatted
|
||||
* input function.
|
||||
*/
|
||||
streamsize gcount() const {
|
||||
return m_gcount;
|
||||
}
|
||||
/**
|
||||
* Extract a character if one is available.
|
||||
*
|
||||
* \return The character or -1 if a failure occurs. A failure is indicated
|
||||
* by the stream state.
|
||||
*/
|
||||
int get();
|
||||
/**
|
||||
* Extract a character if one is available.
|
||||
*
|
||||
* \param[out] ch location to receive the extracted character.
|
||||
*
|
||||
* \return always returns *this. A failure is indicated by the stream state.
|
||||
*/
|
||||
istream& get(char& ch);
|
||||
/**
|
||||
* Extract characters.
|
||||
*
|
||||
* \param[out] str Location to receive extracted characters.
|
||||
* \param[in] n Size of str.
|
||||
* \param[in] delim Delimiter
|
||||
*
|
||||
* Characters are extracted until extraction fails, n is less than 1,
|
||||
* n-1 characters are extracted, or the next character equals
|
||||
* \a delim (delim is not extracted). If no characters are extracted
|
||||
* failbit is set. If end-of-file occurs the eofbit is set.
|
||||
*
|
||||
* \return always returns *this. A failure is indicated by the stream state.
|
||||
*/
|
||||
istream& get(char *str, streamsize n, char delim = '\n');
|
||||
/**
|
||||
* Extract characters
|
||||
*
|
||||
* \param[out] str Location to receive extracted characters.
|
||||
* \param[in] n Size of str.
|
||||
* \param[in] delim Delimiter
|
||||
*
|
||||
* Characters are extracted until extraction fails,
|
||||
* the next character equals \a delim (delim is extracted), or n-1
|
||||
* characters are extracted.
|
||||
*
|
||||
* The failbit is set if no characters are extracted or n-1 characters
|
||||
* are extracted. If end-of-file occurs the eofbit is set.
|
||||
*
|
||||
* \return always returns *this. A failure is indicated by the stream state.
|
||||
*/
|
||||
istream& getline(char *str, streamsize n, char delim = '\n');
|
||||
/**
|
||||
* Extract characters and discard them.
|
||||
*
|
||||
* \param[in] n maximum number of characters to ignore.
|
||||
* \param[in] delim Delimiter.
|
||||
*
|
||||
* Characters are extracted until extraction fails, \a n characters
|
||||
* are extracted, or the next input character equals \a delim
|
||||
* (the delimiter is extracted). If end-of-file occurs the eofbit is set.
|
||||
*
|
||||
* Failures are indicated by the state of the stream.
|
||||
*
|
||||
* \return *this
|
||||
*
|
||||
*/
|
||||
istream& ignore(streamsize n = 1, int delim = -1);
|
||||
/**
|
||||
* Return the next available character without consuming it.
|
||||
*
|
||||
* \return The character if the stream state is good else -1;
|
||||
*
|
||||
*/
|
||||
int peek();
|
||||
// istream& read(char *str, streamsize count);
|
||||
// streamsize readsome(char *str, streamsize count);
|
||||
/**
|
||||
* \return the stream position
|
||||
*/
|
||||
pos_type tellg() {
|
||||
return tellpos();
|
||||
}
|
||||
/**
|
||||
* Set the stream position
|
||||
* \param[in] pos The absolute position in which to move the read pointer.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& seekg(pos_type pos) {
|
||||
if (!seekpos(pos)) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Set the stream position.
|
||||
*
|
||||
* \param[in] off An offset to move the read pointer relative to way.
|
||||
* \a off is a signed 32-bit int so the offset is limited to +- 2GB.
|
||||
* \param[in] way One of ios::beg, ios::cur, or ios::end.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
istream& seekg(off_type off, seekdir way) {
|
||||
if (!seekoff(off, way)) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
void skipWhite();
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/**
|
||||
* Internal - do not use
|
||||
* \return
|
||||
*/
|
||||
virtual int16_t getch() = 0;
|
||||
/**
|
||||
* Internal - do not use
|
||||
* \param[out] pos
|
||||
* \return
|
||||
*/
|
||||
int16_t getch(FatPos_t* pos) {
|
||||
getpos(pos);
|
||||
return getch();
|
||||
}
|
||||
/**
|
||||
* Internal - do not use
|
||||
* \param[out] pos
|
||||
*/
|
||||
virtual void getpos(FatPos_t* pos) = 0;
|
||||
/**
|
||||
* Internal - do not use
|
||||
* \param[in] pos
|
||||
*/
|
||||
virtual bool seekoff(off_type off, seekdir way) = 0;
|
||||
virtual bool seekpos(pos_type pos) = 0;
|
||||
virtual void setpos(FatPos_t* pos) = 0;
|
||||
virtual pos_type tellpos() = 0;
|
||||
|
||||
/// @endcond
|
||||
private:
|
||||
void getBool(bool *b);
|
||||
void getChar(char* ch);
|
||||
bool getDouble(double* value);
|
||||
template <typename T> void getNumber(T* value);
|
||||
bool getNumber(uint32_t posMax, uint32_t negMax, uint32_t* num);
|
||||
void getStr(char *str);
|
||||
int16_t readSkip();
|
||||
|
||||
size_t m_gcount;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
template <typename T>
|
||||
void istream::getNumber(T* value) {
|
||||
uint32_t tmp;
|
||||
if ((T)-1 < 0) {
|
||||
// number is signed, max positive value
|
||||
uint32_t const m = ((uint32_t)-1) >> (33 - sizeof(T) * 8);
|
||||
// max absolute value of negative number is m + 1.
|
||||
if (getNumber(m, m + 1, &tmp)) {
|
||||
*value = (T)tmp;
|
||||
}
|
||||
} else {
|
||||
// max unsigned value for T
|
||||
uint32_t const m = (T)-1;
|
||||
if (getNumber(m, m, &tmp)) {
|
||||
*value = (T)tmp;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // istream_h
|
196
hardware/sd_card_formatter/src/SdFat/FatLib/ostream.cpp
Normal file
196
hardware/sd_card_formatter/src/SdFat/FatLib/ostream.cpp
Normal file
|
@ -0,0 +1,196 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include <string.h>
|
||||
#include "ostream.h"
|
||||
#ifndef PSTR
|
||||
#define PSTR(x) x
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::do_fill(unsigned len) {
|
||||
for (; len < width(); len++) {
|
||||
putch(fill());
|
||||
}
|
||||
width(0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::fill_not_left(unsigned len) {
|
||||
if ((flags() & adjustfield) != left) {
|
||||
do_fill(len);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
char* ostream::fmtNum(uint32_t n, char *ptr, uint8_t base) {
|
||||
char a = flags() & uppercase ? 'A' - 10 : 'a' - 10;
|
||||
do {
|
||||
uint32_t m = n;
|
||||
n /= base;
|
||||
char c = m - base * n;
|
||||
*--ptr = c < 10 ? c + '0' : c + a;
|
||||
} while (n);
|
||||
return ptr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putBool(bool b) {
|
||||
if (flags() & boolalpha) {
|
||||
if (b) {
|
||||
putPgm(PSTR("true"));
|
||||
} else {
|
||||
putPgm(PSTR("false"));
|
||||
}
|
||||
} else {
|
||||
putChar(b ? '1' : '0');
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putChar(char c) {
|
||||
fill_not_left(1);
|
||||
putch(c);
|
||||
do_fill(1);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putDouble(double n) {
|
||||
uint8_t nd = precision();
|
||||
double round = 0.5;
|
||||
char sign;
|
||||
char buf[13]; // room for sign, 10 digits, '.', and zero byte
|
||||
char *end = buf + sizeof(buf) - 1;
|
||||
char *str = end;
|
||||
// terminate string
|
||||
*end = '\0';
|
||||
|
||||
// get sign and make nonnegative
|
||||
if (n < 0.0) {
|
||||
sign = '-';
|
||||
n = -n;
|
||||
} else {
|
||||
sign = flags() & showpos ? '+' : '\0';
|
||||
}
|
||||
// check for larger than uint32_t
|
||||
if (n > 4.0E9) {
|
||||
putPgm(PSTR("BIG FLT"));
|
||||
return;
|
||||
}
|
||||
// round up and separate int and fraction parts
|
||||
for (uint8_t i = 0; i < nd; ++i) {
|
||||
round *= 0.1;
|
||||
}
|
||||
n += round;
|
||||
uint32_t intPart = n;
|
||||
double fractionPart = n - intPart;
|
||||
|
||||
// format intPart and decimal point
|
||||
if (nd || (flags() & showpoint)) {
|
||||
*--str = '.';
|
||||
}
|
||||
str = fmtNum(intPart, str, 10);
|
||||
|
||||
// calculate length for fill
|
||||
uint8_t len = sign ? 1 : 0;
|
||||
len += nd + end - str;
|
||||
|
||||
// extract adjust field
|
||||
fmtflags adj = flags() & adjustfield;
|
||||
if (adj == internal) {
|
||||
if (sign) {
|
||||
putch(sign);
|
||||
}
|
||||
do_fill(len);
|
||||
} else {
|
||||
// do fill for internal or right
|
||||
fill_not_left(len);
|
||||
if (sign) {
|
||||
*--str = sign;
|
||||
}
|
||||
}
|
||||
putstr(str);
|
||||
// output fraction
|
||||
while (nd-- > 0) {
|
||||
fractionPart *= 10.0;
|
||||
int digit = static_cast<int>(fractionPart);
|
||||
putch(digit + '0');
|
||||
fractionPart -= digit;
|
||||
}
|
||||
// do fill if not done above
|
||||
do_fill(len);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putNum(int32_t n) {
|
||||
bool neg = n < 0 && flagsToBase() == 10;
|
||||
if (neg) {
|
||||
n = -n;
|
||||
}
|
||||
putNum(n, neg);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putNum(uint32_t n, bool neg) {
|
||||
char buf[13];
|
||||
char* end = buf + sizeof(buf) - 1;
|
||||
char* num;
|
||||
char* str;
|
||||
uint8_t base = flagsToBase();
|
||||
*end = '\0';
|
||||
str = num = fmtNum(n, end, base);
|
||||
if (base == 10) {
|
||||
if (neg) {
|
||||
*--str = '-';
|
||||
} else if (flags() & showpos) {
|
||||
*--str = '+';
|
||||
}
|
||||
} else if (flags() & showbase) {
|
||||
if (flags() & hex) {
|
||||
*--str = flags() & uppercase ? 'X' : 'x';
|
||||
}
|
||||
*--str = '0';
|
||||
}
|
||||
uint8_t len = end - str;
|
||||
fmtflags adj = flags() & adjustfield;
|
||||
if (adj == internal) {
|
||||
while (str < num) {
|
||||
putch(*str++);
|
||||
}
|
||||
}
|
||||
if (adj != left) {
|
||||
do_fill(len);
|
||||
}
|
||||
putstr(str);
|
||||
do_fill(len);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putPgm(const char* str) {
|
||||
int n;
|
||||
for (n = 0; pgm_read_byte(&str[n]); n++) {}
|
||||
fill_not_left(n);
|
||||
for (uint8_t c; (c = pgm_read_byte(str)); str++) {
|
||||
putch(c);
|
||||
}
|
||||
do_fill(n);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void ostream::putStr(const char *str) {
|
||||
unsigned n = strlen(str);
|
||||
fill_not_left(n);
|
||||
putstr(str);
|
||||
do_fill(n);
|
||||
}
|
276
hardware/sd_card_formatter/src/SdFat/FatLib/ostream.h
Normal file
276
hardware/sd_card_formatter/src/SdFat/FatLib/ostream.h
Normal file
|
@ -0,0 +1,276 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef ostream_h
|
||||
#define ostream_h
|
||||
/**
|
||||
* \file
|
||||
* \brief \ref ostream class
|
||||
*/
|
||||
#include "ios.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class ostream
|
||||
* \brief Output Stream
|
||||
*/
|
||||
class ostream : public virtual ios {
|
||||
public:
|
||||
ostream() {}
|
||||
|
||||
/** call manipulator
|
||||
* \param[in] pf function to call
|
||||
* \return the stream
|
||||
*/
|
||||
ostream& operator<< (ostream& (*pf)(ostream& str)) {
|
||||
return pf(*this);
|
||||
}
|
||||
/** call manipulator
|
||||
* \param[in] pf function to call
|
||||
* \return the stream
|
||||
*/
|
||||
ostream& operator<< (ios_base& (*pf)(ios_base& str)) {
|
||||
pf(*this);
|
||||
return *this;
|
||||
}
|
||||
/** Output bool
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (bool arg) {
|
||||
putBool(arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output string
|
||||
* \param[in] arg string to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (const char *arg) {
|
||||
putStr(arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output string
|
||||
* \param[in] arg string to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (const signed char *arg) {
|
||||
putStr((const char*)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output string
|
||||
* \param[in] arg string to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (const unsigned char *arg) {
|
||||
putStr((const char*)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output character
|
||||
* \param[in] arg character to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (char arg) {
|
||||
putChar(arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output character
|
||||
* \param[in] arg character to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (signed char arg) {
|
||||
putChar(static_cast<char>(arg));
|
||||
return *this;
|
||||
}
|
||||
/** Output character
|
||||
* \param[in] arg character to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (unsigned char arg) {
|
||||
putChar(static_cast<char>(arg));
|
||||
return *this;
|
||||
}
|
||||
/** Output double
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (double arg) {
|
||||
putDouble(arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output float
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (float arg) {
|
||||
putDouble(arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output signed short
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (short arg) { // NOLINT
|
||||
putNum((int32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output unsigned short
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (unsigned short arg) { // NOLINT
|
||||
putNum((uint32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output signed int
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (int arg) {
|
||||
putNum((int32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output unsigned int
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (unsigned int arg) {
|
||||
putNum((uint32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output signed long
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (long arg) { // NOLINT
|
||||
putNum((int32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output unsigned long
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (unsigned long arg) { // NOLINT
|
||||
putNum((uint32_t)arg);
|
||||
return *this;
|
||||
}
|
||||
/** Output pointer
|
||||
* \param[in] arg value to output
|
||||
* \return the stream
|
||||
*/
|
||||
ostream& operator<< (const void* arg) {
|
||||
putNum(reinterpret_cast<uint32_t>(arg));
|
||||
return *this;
|
||||
}
|
||||
#if (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
/** Output a string from flash using the Arduino F() macro.
|
||||
* \param[in] arg pointing to flash string
|
||||
* \return the stream
|
||||
*/
|
||||
ostream &operator<< (const __FlashStringHelper *arg) {
|
||||
putPgm(reinterpret_cast<const char*>(arg));
|
||||
return *this;
|
||||
}
|
||||
#endif // (defined(ARDUINO) && ENABLE_ARDUINO_FEATURES) || defined(DOXYGEN)
|
||||
/**
|
||||
* Puts a character in a stream.
|
||||
*
|
||||
* The unformatted output function inserts the element \a ch.
|
||||
* It returns *this.
|
||||
*
|
||||
* \param[in] ch The character
|
||||
* \return A reference to the ostream object.
|
||||
*/
|
||||
ostream& put(char ch) {
|
||||
putch(ch);
|
||||
return *this;
|
||||
}
|
||||
// ostream& write(char *str, streamsize count);
|
||||
/**
|
||||
* Flushes the buffer associated with this stream. The flush function
|
||||
* calls the sync function of the associated file.
|
||||
* \return A reference to the ostream object.
|
||||
*/
|
||||
ostream& flush() {
|
||||
if (!sync()) {
|
||||
setstate(badbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* \return the stream position
|
||||
*/
|
||||
pos_type tellp() {
|
||||
return tellpos();
|
||||
}
|
||||
/**
|
||||
* Set the stream position
|
||||
* \param[in] pos The absolute position in which to move the write pointer.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
ostream& seekp(pos_type pos) {
|
||||
if (!seekpos(pos)) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
/**
|
||||
* Set the stream position.
|
||||
*
|
||||
* \param[in] off An offset to move the write pointer relative to way.
|
||||
* \a off is a signed 32-bit int so the offset is limited to +- 2GB.
|
||||
* \param[in] way One of ios::beg, ios::cur, or ios::end.
|
||||
* \return Is always *this. Failure is indicated by the state of *this.
|
||||
*/
|
||||
ostream& seekp(off_type off, seekdir way) {
|
||||
if (!seekoff(off, way)) {
|
||||
setstate(failbit);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
protected:
|
||||
/// @cond SHOW_PROTECTED
|
||||
/** Put character with binary/text conversion
|
||||
* \param[in] ch character to write
|
||||
*/
|
||||
virtual void putch(char ch) = 0;
|
||||
virtual void putstr(const char *str) = 0;
|
||||
virtual bool seekoff(off_type pos, seekdir way) = 0;
|
||||
virtual bool seekpos(pos_type pos) = 0;
|
||||
virtual bool sync() = 0;
|
||||
|
||||
virtual pos_type tellpos() = 0;
|
||||
/// @endcond
|
||||
private:
|
||||
void do_fill(unsigned len);
|
||||
void fill_not_left(unsigned len);
|
||||
char* fmtNum(uint32_t n, char *ptr, uint8_t base);
|
||||
void putBool(bool b);
|
||||
void putChar(char c);
|
||||
void putDouble(double n);
|
||||
void putNum(uint32_t n, bool neg = false);
|
||||
void putNum(int32_t n);
|
||||
void putPgm(const char* str);
|
||||
void putStr(const char* str);
|
||||
};
|
||||
#endif // ostream_h
|
61
hardware/sd_card_formatter/src/SdFat/FreeStack.h
Normal file
61
hardware/sd_card_formatter/src/SdFat/FreeStack.h
Normal file
|
@ -0,0 +1,61 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef FreeStack_h
|
||||
#define FreeStack_h
|
||||
/**
|
||||
* \file
|
||||
* \brief FreeStack() function.
|
||||
*/
|
||||
#if defined(__AVR__) || defined(DOXYGEN)
|
||||
/** boundary between stack and heap. */
|
||||
extern char *__brkval;
|
||||
/** End of bss section.*/
|
||||
extern char __bss_end;
|
||||
/** Amount of free stack space.
|
||||
* \return The number of free bytes.
|
||||
*/
|
||||
static int FreeStack() {
|
||||
char* sp = reinterpret_cast<char*>(SP);
|
||||
return __brkval ? sp - __brkval : sp - &__bss_end;
|
||||
// char top;
|
||||
// return __brkval ? &top - __brkval : &top - &__bss_end;
|
||||
}
|
||||
#elif defined(PLATFORM_ID) // Particle board
|
||||
static int FreeStack() {
|
||||
return System.freeMemory();
|
||||
}
|
||||
#elif defined(__arm__)
|
||||
extern "C" char* sbrk(int incr);
|
||||
static int FreeStack() {
|
||||
char top = 't';
|
||||
return &top - reinterpret_cast<char*>(sbrk(0));
|
||||
}
|
||||
#else
|
||||
#warning FreeStack is not defined for this system.
|
||||
static int FreeStack() {
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif // FreeStack_h
|
71
hardware/sd_card_formatter/src/SdFat/MinimumSerial.cpp
Normal file
71
hardware/sd_card_formatter/src/SdFat/MinimumSerial.cpp
Normal file
|
@ -0,0 +1,71 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SysCall.h"
|
||||
#if defined(UDR0) || defined(DOXYGEN)
|
||||
#include "MinimumSerial.h"
|
||||
const uint16_t MIN_2X_BAUD = F_CPU/(4*(2*0XFFF + 1)) + 1;
|
||||
//------------------------------------------------------------------------------
|
||||
int MinimumSerial::available() {
|
||||
return UCSR0A & (1 << RXC0) ? 1 : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void MinimumSerial::begin(uint32_t baud) {
|
||||
uint16_t baud_setting;
|
||||
// don't worry, the compiler will squeeze out F_CPU != 16000000UL
|
||||
if ((F_CPU != 16000000UL || baud != 57600) && baud > MIN_2X_BAUD) {
|
||||
// Double the USART Transmission Speed
|
||||
UCSR0A = 1 << U2X0;
|
||||
baud_setting = (F_CPU / 4 / baud - 1) / 2;
|
||||
} else {
|
||||
// hardcoded exception for compatibility with the bootloader shipped
|
||||
// with the Duemilanove and previous boards and the firmware on the 8U2
|
||||
// on the Uno and Mega 2560.
|
||||
UCSR0A = 0;
|
||||
baud_setting = (F_CPU / 8 / baud - 1) / 2;
|
||||
}
|
||||
// assign the baud_setting
|
||||
UBRR0H = baud_setting >> 8;
|
||||
UBRR0L = baud_setting;
|
||||
// enable transmit and receive
|
||||
UCSR0B |= (1 << TXEN0) | (1 << RXEN0);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void MinimumSerial::flush() {
|
||||
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
int MinimumSerial::read() {
|
||||
if (UCSR0A & (1 << RXC0)) {
|
||||
return UDR0;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
size_t MinimumSerial::write(uint8_t b) {
|
||||
while (((1 << UDRIE0) & UCSR0B) || !(UCSR0A & (1 << UDRE0))) {}
|
||||
UDR0 = b;
|
||||
return 1;
|
||||
}
|
||||
#endif // defined(UDR0) || defined(DOXYGEN)
|
67
hardware/sd_card_formatter/src/SdFat/MinimumSerial.h
Normal file
67
hardware/sd_card_formatter/src/SdFat/MinimumSerial.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief Minimal AVR Serial driver.
|
||||
*/
|
||||
#ifndef MinimumSerial_h
|
||||
#define MinimumSerial_h
|
||||
#include "SysCall.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class MinimumSerial
|
||||
* \brief mini serial class for the %SdFat library.
|
||||
*/
|
||||
class MinimumSerial : public Print {
|
||||
public:
|
||||
/** \return true for hardware serial */
|
||||
operator bool() { return true; }
|
||||
/**
|
||||
* \return one if data is available.
|
||||
*/
|
||||
int available();
|
||||
/**
|
||||
* Set baud rate for serial port zero and enable in non interrupt mode.
|
||||
* Do not call this function if you use another serial library.
|
||||
* \param[in] baud rate
|
||||
*/
|
||||
void begin(uint32_t baud);
|
||||
/** Wait for write done. */
|
||||
void flush();
|
||||
/**
|
||||
* Unbuffered read
|
||||
* \return -1 if no character is available or an available character.
|
||||
*/
|
||||
int read();
|
||||
/**
|
||||
* Unbuffered write
|
||||
*
|
||||
* \param[in] b byte to write.
|
||||
* \return 1
|
||||
*/
|
||||
size_t write(uint8_t b);
|
||||
using Print::write;
|
||||
};
|
||||
#endif // MinimumSerial_h
|
485
hardware/sd_card_formatter/src/SdFat/SdCard/SdInfo.h
Normal file
485
hardware/sd_card_formatter/src/SdFat/SdCard/SdInfo.h
Normal file
|
@ -0,0 +1,485 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdInfo_h
|
||||
#define SdInfo_h
|
||||
#include <stdint.h>
|
||||
// Based on the document:
|
||||
//
|
||||
// SD Specifications
|
||||
// Part 1
|
||||
// Physical Layer
|
||||
// Simplified Specification
|
||||
// Version 5.00
|
||||
// Aug 10, 2016
|
||||
//
|
||||
// https://www.sdcard.org/downloads/pls/
|
||||
//------------------------------------------------------------------------------
|
||||
// SD card errors
|
||||
// See the SD Specification for command info.
|
||||
typedef enum {
|
||||
SD_CARD_ERROR_NONE = 0,
|
||||
|
||||
// Basic commands and switch command.
|
||||
SD_CARD_ERROR_CMD0 = 0X20,
|
||||
SD_CARD_ERROR_CMD2,
|
||||
SD_CARD_ERROR_CMD3,
|
||||
SD_CARD_ERROR_CMD6,
|
||||
SD_CARD_ERROR_CMD7,
|
||||
SD_CARD_ERROR_CMD8,
|
||||
SD_CARD_ERROR_CMD9,
|
||||
SD_CARD_ERROR_CMD10,
|
||||
SD_CARD_ERROR_CMD12,
|
||||
SD_CARD_ERROR_CMD13,
|
||||
|
||||
// Read, write, erase, and extension commands.
|
||||
SD_CARD_ERROR_CMD17 = 0X30,
|
||||
SD_CARD_ERROR_CMD18,
|
||||
SD_CARD_ERROR_CMD24,
|
||||
SD_CARD_ERROR_CMD25,
|
||||
SD_CARD_ERROR_CMD32,
|
||||
SD_CARD_ERROR_CMD33,
|
||||
SD_CARD_ERROR_CMD38,
|
||||
SD_CARD_ERROR_CMD58,
|
||||
SD_CARD_ERROR_CMD59,
|
||||
|
||||
// Application specific commands.
|
||||
SD_CARD_ERROR_ACMD6 = 0X40,
|
||||
SD_CARD_ERROR_ACMD13,
|
||||
SD_CARD_ERROR_ACMD23,
|
||||
SD_CARD_ERROR_ACMD41,
|
||||
|
||||
// Read/write errors
|
||||
SD_CARD_ERROR_READ = 0X50,
|
||||
SD_CARD_ERROR_READ_CRC,
|
||||
SD_CARD_ERROR_READ_FIFO,
|
||||
SD_CARD_ERROR_READ_REG,
|
||||
SD_CARD_ERROR_READ_START,
|
||||
SD_CARD_ERROR_READ_TIMEOUT,
|
||||
SD_CARD_ERROR_STOP_TRAN,
|
||||
SD_CARD_ERROR_WRITE,
|
||||
SD_CARD_ERROR_WRITE_FIFO,
|
||||
SD_CARD_ERROR_WRITE_START,
|
||||
SD_CARD_ERROR_FLASH_PROGRAMMING,
|
||||
SD_CARD_ERROR_WRITE_TIMEOUT,
|
||||
|
||||
// Misc errors.
|
||||
SD_CARD_ERROR_DMA = 0X60,
|
||||
SD_CARD_ERROR_ERASE,
|
||||
SD_CARD_ERROR_ERASE_SINGLE_BLOCK,
|
||||
SD_CARD_ERROR_ERASE_TIMEOUT,
|
||||
SD_CARD_ERROR_INIT_NOT_CALLED,
|
||||
SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED
|
||||
} sd_error_code_t;
|
||||
//------------------------------------------------------------------------------
|
||||
// card types
|
||||
/** Standard capacity V1 SD card */
|
||||
const uint8_t SD_CARD_TYPE_SD1 = 1;
|
||||
/** Standard capacity V2 SD card */
|
||||
const uint8_t SD_CARD_TYPE_SD2 = 2;
|
||||
/** High Capacity SD card */
|
||||
const uint8_t SD_CARD_TYPE_SDHC = 3;
|
||||
//------------------------------------------------------------------------------
|
||||
#define SD_SCK_HZ(maxSpeed) SPISettings(maxSpeed, MSBFIRST, SPI_MODE0)
|
||||
#define SD_SCK_MHZ(maxMhz) SPISettings(1000000UL*maxMhz, MSBFIRST, SPI_MODE0)
|
||||
// SPI divisor constants
|
||||
/** Set SCK to max rate of F_CPU/2. */
|
||||
#define SPI_FULL_SPEED SD_SCK_MHZ(50)
|
||||
/** Set SCK rate to F_CPU/3 for Due */
|
||||
#define SPI_DIV3_SPEED SD_SCK_HZ(F_CPU/3)
|
||||
/** Set SCK rate to F_CPU/4. */
|
||||
#define SPI_HALF_SPEED SD_SCK_HZ(F_CPU/4)
|
||||
/** Set SCK rate to F_CPU/6 for Due */
|
||||
#define SPI_DIV6_SPEED SD_SCK_HZ(F_CPU/6)
|
||||
/** Set SCK rate to F_CPU/8. */
|
||||
#define SPI_QUARTER_SPEED SD_SCK_HZ(F_CPU/8)
|
||||
/** Set SCK rate to F_CPU/16. */
|
||||
#define SPI_EIGHTH_SPEED SD_SCK_HZ(F_CPU/16)
|
||||
/** Set SCK rate to F_CPU/32. */
|
||||
#define SPI_SIXTEENTH_SPEED SD_SCK_HZ(F_CPU/32)
|
||||
//------------------------------------------------------------------------------
|
||||
// SD operation timeouts
|
||||
/** CMD0 retry count */
|
||||
const uint8_t SD_CMD0_RETRY = 10;
|
||||
/** command timeout ms */
|
||||
const uint16_t SD_CMD_TIMEOUT = 300;
|
||||
/** init timeout ms */
|
||||
const uint16_t SD_INIT_TIMEOUT = 2000;
|
||||
/** erase timeout ms */
|
||||
const uint16_t SD_ERASE_TIMEOUT = 10000;
|
||||
/** read timeout ms */
|
||||
const uint16_t SD_READ_TIMEOUT = 1000;
|
||||
/** write time out ms */
|
||||
const uint16_t SD_WRITE_TIMEOUT = 2000;
|
||||
//------------------------------------------------------------------------------
|
||||
// SD card commands
|
||||
/** GO_IDLE_STATE - init card in spi mode if CS low */
|
||||
const uint8_t CMD0 = 0X00;
|
||||
/** ALL_SEND_CID - Asks any card to send the CID. */
|
||||
const uint8_t CMD2 = 0X02;
|
||||
/** SEND_RELATIVE_ADDR - Ask the card to publish a new RCA. */
|
||||
const uint8_t CMD3 = 0X03;
|
||||
/** SWITCH_FUNC - Switch Function Command */
|
||||
const uint8_t CMD6 = 0X06;
|
||||
/** SELECT/DESELECT_CARD - toggles between the stand-by and transfer states. */
|
||||
const uint8_t CMD7 = 0X07;
|
||||
/** SEND_IF_COND - verify SD Memory Card interface operating condition.*/
|
||||
const uint8_t CMD8 = 0X08;
|
||||
/** SEND_CSD - read the Card Specific Data (CSD register) */
|
||||
const uint8_t CMD9 = 0X09;
|
||||
/** SEND_CID - read the card identification information (CID register) */
|
||||
const uint8_t CMD10 = 0X0A;
|
||||
/** STOP_TRANSMISSION - end multiple block read sequence */
|
||||
const uint8_t CMD12 = 0X0C;
|
||||
/** SEND_STATUS - read the card status register */
|
||||
const uint8_t CMD13 = 0X0D;
|
||||
/** READ_SINGLE_BLOCK - read a single data block from the card */
|
||||
const uint8_t CMD17 = 0X11;
|
||||
/** READ_MULTIPLE_BLOCK - read a multiple data blocks from the card */
|
||||
const uint8_t CMD18 = 0X12;
|
||||
/** WRITE_BLOCK - write a single data block to the card */
|
||||
const uint8_t CMD24 = 0X18;
|
||||
/** WRITE_MULTIPLE_BLOCK - write blocks of data until a STOP_TRANSMISSION */
|
||||
const uint8_t CMD25 = 0X19;
|
||||
/** ERASE_WR_BLK_START - sets the address of the first block to be erased */
|
||||
const uint8_t CMD32 = 0X20;
|
||||
/** ERASE_WR_BLK_END - sets the address of the last block of the continuous
|
||||
range to be erased*/
|
||||
const uint8_t CMD33 = 0X21;
|
||||
/** ERASE - erase all previously selected blocks */
|
||||
const uint8_t CMD38 = 0X26;
|
||||
/** APP_CMD - escape for application specific command */
|
||||
const uint8_t CMD55 = 0X37;
|
||||
/** READ_OCR - read the OCR register of a card */
|
||||
const uint8_t CMD58 = 0X3A;
|
||||
/** CRC_ON_OFF - enable or disable CRC checking */
|
||||
const uint8_t CMD59 = 0X3B;
|
||||
/** SET_BUS_WIDTH - Defines the data bus width for data transfer. */
|
||||
const uint8_t ACMD6 = 0X06;
|
||||
/** SD_STATUS - Send the SD Status. */
|
||||
const uint8_t ACMD13 = 0X0D;
|
||||
/** SET_WR_BLK_ERASE_COUNT - Set the number of write blocks to be
|
||||
pre-erased before writing */
|
||||
const uint8_t ACMD23 = 0X17;
|
||||
/** SD_SEND_OP_COMD - Sends host capacity support information and
|
||||
activates the card's initialization process */
|
||||
const uint8_t ACMD41 = 0X29;
|
||||
//==============================================================================
|
||||
// CARD_STATUS
|
||||
/** The command's argument was out of the allowed range for this card. */
|
||||
const uint32_t CARD_STATUS_OUT_OF_RANGE = 1UL << 31;
|
||||
/** A misaligned address which did not match the block length. */
|
||||
const uint32_t CARD_STATUS_ADDRESS_ERROR = 1UL << 30;
|
||||
/** The transferred block length is not allowed for this card. */
|
||||
const uint32_t CARD_STATUS_BLOCK_LEN_ERROR = 1UL << 29;
|
||||
/** An error in the sequence of erase commands occurred. */
|
||||
const uint32_t CARD_STATUS_ERASE_SEQ_ERROR = 1UL <<28;
|
||||
/** An invalid selection of write-blocks for erase occurred. */
|
||||
const uint32_t CARD_STATUS_ERASE_PARAM = 1UL << 27;
|
||||
/** Set when the host attempts to write to a protected block. */
|
||||
const uint32_t CARD_STATUS_WP_VIOLATION = 1UL << 26;
|
||||
/** When set, signals that the card is locked by the host. */
|
||||
const uint32_t CARD_STATUS_CARD_IS_LOCKED = 1UL << 25;
|
||||
/** Set when a sequence or password error has been detected. */
|
||||
const uint32_t CARD_STATUS_LOCK_UNLOCK_FAILED = 1UL << 24;
|
||||
/** The CRC check of the previous command failed. */
|
||||
const uint32_t CARD_STATUS_COM_CRC_ERROR = 1UL << 23;
|
||||
/** Command not legal for the card state. */
|
||||
const uint32_t CARD_STATUS_ILLEGAL_COMMAND = 1UL << 22;
|
||||
/** Card internal ECC was applied but failed to correct the data. */
|
||||
const uint32_t CARD_STATUS_CARD_ECC_FAILED = 1UL << 21;
|
||||
/** Internal card controller error */
|
||||
const uint32_t CARD_STATUS_CC_ERROR = 1UL << 20;
|
||||
/** A general or an unknown error occurred during the operation. */
|
||||
const uint32_t CARD_STATUS_ERROR = 1UL << 19;
|
||||
// bits 19, 18, and 17 reserved.
|
||||
/** Permanent WP set or attempt to change read only values of CSD. */
|
||||
const uint32_t CARD_STATUS_CSD_OVERWRITE = 1UL <<16;
|
||||
/** partial address space was erased due to write protect. */
|
||||
const uint32_t CARD_STATUS_WP_ERASE_SKIP = 1UL << 15;
|
||||
/** The command has been executed without using the internal ECC. */
|
||||
const uint32_t CARD_STATUS_CARD_ECC_DISABLED = 1UL << 14;
|
||||
/** out of erase sequence command was received. */
|
||||
const uint32_t CARD_STATUS_ERASE_RESET = 1UL << 13;
|
||||
/** The state of the card when receiving the command.
|
||||
* 0 = idle
|
||||
* 1 = ready
|
||||
* 2 = ident
|
||||
* 3 = stby
|
||||
* 4 = tran
|
||||
* 5 = data
|
||||
* 6 = rcv
|
||||
* 7 = prg
|
||||
* 8 = dis
|
||||
* 9-14 = reserved
|
||||
* 15 = reserved for I/O mode
|
||||
*/
|
||||
const uint32_t CARD_STATUS_CURRENT_STATE = 0XF << 9;
|
||||
/** Shift for current state. */
|
||||
const uint32_t CARD_STATUS_CURRENT_STATE_SHIFT = 9;
|
||||
/** Corresponds to buffer empty signaling on the bus. */
|
||||
const uint32_t CARD_STATUS_READY_FOR_DATA = 1UL << 8;
|
||||
// bit 7 reserved.
|
||||
/** Extension Functions may set this bit to get host to deal with events. */
|
||||
const uint32_t CARD_STATUS_FX_EVENT = 1UL << 6;
|
||||
/** The card will expect ACMD, or the command has been interpreted as ACMD */
|
||||
const uint32_t CARD_STATUS_APP_CMD = 1UL << 5;
|
||||
// bit 4 reserved.
|
||||
/** Error in the sequence of the authentication process. */
|
||||
const uint32_t CARD_STATUS_AKE_SEQ_ERROR = 1UL << 3;
|
||||
// bits 2,1, and 0 reserved for manufacturer test mode.
|
||||
//==============================================================================
|
||||
/** status for card in the ready state */
|
||||
const uint8_t R1_READY_STATE = 0X00;
|
||||
/** status for card in the idle state */
|
||||
const uint8_t R1_IDLE_STATE = 0X01;
|
||||
/** status bit for illegal command */
|
||||
const uint8_t R1_ILLEGAL_COMMAND = 0X04;
|
||||
/** start data token for read or write single block*/
|
||||
const uint8_t DATA_START_BLOCK = 0XFE;
|
||||
/** stop token for write multiple blocks*/
|
||||
const uint8_t STOP_TRAN_TOKEN = 0XFD;
|
||||
/** start data token for write multiple blocks*/
|
||||
const uint8_t WRITE_MULTIPLE_TOKEN = 0XFC;
|
||||
/** mask for data response tokens after a write block operation */
|
||||
const uint8_t DATA_RES_MASK = 0X1F;
|
||||
/** write data accepted token */
|
||||
const uint8_t DATA_RES_ACCEPTED = 0X05;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CID
|
||||
* \brief Card IDentification (CID) register.
|
||||
*/
|
||||
typedef struct CID {
|
||||
// byte 0
|
||||
/** Manufacturer ID */
|
||||
unsigned char mid;
|
||||
// byte 1-2
|
||||
/** OEM/Application ID */
|
||||
char oid[2];
|
||||
// byte 3-7
|
||||
/** Product name */
|
||||
char pnm[5];
|
||||
// byte 8
|
||||
/** Product revision least significant digit */
|
||||
unsigned char prv_m : 4;
|
||||
/** Product revision most significant digit */
|
||||
unsigned char prv_n : 4;
|
||||
// byte 9-12
|
||||
/** Product serial number */
|
||||
uint32_t psn;
|
||||
// byte 13
|
||||
/** Manufacturing date year low digit */
|
||||
unsigned char mdt_year_high : 4;
|
||||
/** not used */
|
||||
unsigned char reserved : 4;
|
||||
// byte 14
|
||||
/** Manufacturing date month */
|
||||
unsigned char mdt_month : 4;
|
||||
/** Manufacturing date year low digit */
|
||||
unsigned char mdt_year_low : 4;
|
||||
// byte 15
|
||||
/** not used always 1 */
|
||||
unsigned char always1 : 1;
|
||||
/** CRC7 checksum */
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) cid_t;
|
||||
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CSDV1
|
||||
* \brief CSD register for version 1.00 cards .
|
||||
*/
|
||||
typedef struct CSDV1 {
|
||||
// byte 0
|
||||
unsigned char reserved1 : 6;
|
||||
unsigned char csd_ver : 2;
|
||||
// byte 1
|
||||
unsigned char taac;
|
||||
// byte 2
|
||||
unsigned char nsac;
|
||||
// byte 3
|
||||
unsigned char tran_speed;
|
||||
// byte 4
|
||||
unsigned char ccc_high;
|
||||
// byte 5
|
||||
unsigned char read_bl_len : 4;
|
||||
unsigned char ccc_low : 4;
|
||||
// byte 6
|
||||
unsigned char c_size_high : 2;
|
||||
unsigned char reserved2 : 2;
|
||||
unsigned char dsr_imp : 1;
|
||||
unsigned char read_blk_misalign : 1;
|
||||
unsigned char write_blk_misalign : 1;
|
||||
unsigned char read_bl_partial : 1;
|
||||
// byte 7
|
||||
unsigned char c_size_mid;
|
||||
// byte 8
|
||||
unsigned char vdd_r_curr_max : 3;
|
||||
unsigned char vdd_r_curr_min : 3;
|
||||
unsigned char c_size_low : 2;
|
||||
// byte 9
|
||||
unsigned char c_size_mult_high : 2;
|
||||
unsigned char vdd_w_cur_max : 3;
|
||||
unsigned char vdd_w_curr_min : 3;
|
||||
// byte 10
|
||||
unsigned char sector_size_high : 6;
|
||||
unsigned char erase_blk_en : 1;
|
||||
unsigned char c_size_mult_low : 1;
|
||||
// byte 11
|
||||
unsigned char wp_grp_size : 7;
|
||||
unsigned char sector_size_low : 1;
|
||||
// byte 12
|
||||
unsigned char write_bl_len_high : 2;
|
||||
unsigned char r2w_factor : 3;
|
||||
unsigned char reserved3 : 2;
|
||||
unsigned char wp_grp_enable : 1;
|
||||
// byte 13
|
||||
unsigned char reserved4 : 5;
|
||||
unsigned char write_partial : 1;
|
||||
unsigned char write_bl_len_low : 2;
|
||||
// byte 14
|
||||
unsigned char reserved5: 2;
|
||||
unsigned char file_format : 2;
|
||||
unsigned char tmp_write_protect : 1;
|
||||
unsigned char perm_write_protect : 1;
|
||||
unsigned char copy : 1;
|
||||
/** Indicates the file format on the card */
|
||||
unsigned char file_format_grp : 1;
|
||||
// byte 15
|
||||
unsigned char always1 : 1;
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) csd1_t;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class CSDV2
|
||||
* \brief CSD register for version 2.00 cards.
|
||||
*/
|
||||
typedef struct CSDV2 {
|
||||
// byte 0
|
||||
unsigned char reserved1 : 6;
|
||||
unsigned char csd_ver : 2;
|
||||
// byte 1
|
||||
/** fixed to 0X0E */
|
||||
unsigned char taac;
|
||||
// byte 2
|
||||
/** fixed to 0 */
|
||||
unsigned char nsac;
|
||||
// byte 3
|
||||
unsigned char tran_speed;
|
||||
// byte 4
|
||||
unsigned char ccc_high;
|
||||
// byte 5
|
||||
/** This field is fixed to 9h, which indicates READ_BL_LEN=512 Byte */
|
||||
unsigned char read_bl_len : 4;
|
||||
unsigned char ccc_low : 4;
|
||||
// byte 6
|
||||
/** not used */
|
||||
unsigned char reserved2 : 4;
|
||||
unsigned char dsr_imp : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char read_blk_misalign : 1;
|
||||
/** fixed to 0 */
|
||||
unsigned char write_blk_misalign : 1;
|
||||
/** fixed to 0 - no partial read */
|
||||
unsigned char read_bl_partial : 1;
|
||||
// byte 7
|
||||
/** high part of card size */
|
||||
unsigned char c_size_high : 6;
|
||||
/** not used */
|
||||
unsigned char reserved3 : 2;
|
||||
// byte 8
|
||||
/** middle part of card size */
|
||||
unsigned char c_size_mid;
|
||||
// byte 9
|
||||
/** low part of card size */
|
||||
unsigned char c_size_low;
|
||||
// byte 10
|
||||
/** sector size is fixed at 64 KB */
|
||||
unsigned char sector_size_high : 6;
|
||||
/** fixed to 1 - erase single is supported */
|
||||
unsigned char erase_blk_en : 1;
|
||||
/** not used */
|
||||
unsigned char reserved4 : 1;
|
||||
// byte 11
|
||||
unsigned char wp_grp_size : 7;
|
||||
/** sector size is fixed at 64 KB */
|
||||
unsigned char sector_size_low : 1;
|
||||
// byte 12
|
||||
/** write_bl_len fixed for 512 byte blocks */
|
||||
unsigned char write_bl_len_high : 2;
|
||||
/** fixed value of 2 */
|
||||
unsigned char r2w_factor : 3;
|
||||
/** not used */
|
||||
unsigned char reserved5 : 2;
|
||||
/** fixed value of 0 - no write protect groups */
|
||||
unsigned char wp_grp_enable : 1;
|
||||
// byte 13
|
||||
unsigned char reserved6 : 5;
|
||||
/** always zero - no partial block read*/
|
||||
unsigned char write_partial : 1;
|
||||
/** write_bl_len fixed for 512 byte blocks */
|
||||
unsigned char write_bl_len_low : 2;
|
||||
// byte 14
|
||||
unsigned char reserved7: 2;
|
||||
/** Do not use always 0 */
|
||||
unsigned char file_format : 2;
|
||||
unsigned char tmp_write_protect : 1;
|
||||
unsigned char perm_write_protect : 1;
|
||||
unsigned char copy : 1;
|
||||
/** Do not use always 0 */
|
||||
unsigned char file_format_grp : 1;
|
||||
// byte 15
|
||||
/** not used always 1 */
|
||||
unsigned char always1 : 1;
|
||||
/** checksum */
|
||||
unsigned char crc : 7;
|
||||
} __attribute__((packed)) csd2_t;
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class csd_t
|
||||
* \brief Union of old and new style CSD register.
|
||||
*/
|
||||
union csd_t {
|
||||
csd1_t v1;
|
||||
csd2_t v2;
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
inline uint32_t sdCardCapacity(csd_t* csd) {
|
||||
if (csd->v1.csd_ver == 0) {
|
||||
uint8_t read_bl_len = csd->v1.read_bl_len;
|
||||
uint16_t c_size = (csd->v1.c_size_high << 10)
|
||||
| (csd->v1.c_size_mid << 2) | csd->v1.c_size_low;
|
||||
uint8_t c_size_mult = (csd->v1.c_size_mult_high << 1)
|
||||
| csd->v1.c_size_mult_low;
|
||||
return (uint32_t)(c_size + 1) << (c_size_mult + read_bl_len - 7);
|
||||
} else if (csd->v2.csd_ver == 1) {
|
||||
uint32_t c_size = 0X10000L * csd->v2.c_size_high + 0X100L
|
||||
* (uint32_t)csd->v2.c_size_mid + csd->v2.c_size_low;
|
||||
return (c_size + 1) << 10;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
#endif // SdInfo_h
|
802
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCard.cpp
Normal file
802
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCard.cpp
Normal file
|
@ -0,0 +1,802 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdSpiCard.h"
|
||||
//==============================================================================
|
||||
// debug trace macro
|
||||
#define SD_TRACE(m, b)
|
||||
// #define SD_TRACE(m, b) Serial.print(m);Serial.println(b);
|
||||
#define SD_CS_DBG(m)
|
||||
// #define SD_CS_DBG(m) Serial.println(F(m));
|
||||
|
||||
#define DBG_PROFILE_STATS 0
|
||||
#if DBG_PROFILE_STATS
|
||||
|
||||
#define DBG_TAG_LIST\
|
||||
DBG_TAG(DBG_CMD0_TIME, "CMD0 time")\
|
||||
DBG_TAG(DBG_ACMD41_TIME, "ACMD41 time")\
|
||||
DBG_TAG(DBG_CMD_BUSY, "cmd busy")\
|
||||
DBG_TAG(DBG_ERASE_BUSY, "erase busy")\
|
||||
DBG_TAG(DBG_WAIT_READ, "wait read")\
|
||||
DBG_TAG(DBG_WRITE_FLASH, "write flash")\
|
||||
DBG_TAG(DBG_WRITE_BUSY, "write busy")\
|
||||
DBG_TAG(DBG_WRITE_STOP, "write stop")\
|
||||
DBG_TAG(DBG_ACMD41_COUNT, "ACMD41 count")\
|
||||
DBG_TAG(DBG_CMD0_COUNT, "CMD0 count")
|
||||
|
||||
#define DBG_TIME_DIM DBG_ACMD41_COUNT
|
||||
|
||||
enum DbgTag {
|
||||
#define DBG_TAG(tag, str) tag,
|
||||
DBG_TAG_LIST
|
||||
DBG_COUNT_DIM
|
||||
#undef DBG_TAG
|
||||
};
|
||||
|
||||
static uint32_t dbgCount[DBG_COUNT_DIM];
|
||||
static uint32_t dbgBgnTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgMaxTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgMinTime[DBG_TIME_DIM];
|
||||
static uint32_t dbgTotalTime[DBG_TIME_DIM];
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgBeginTime(DbgTag tag) {
|
||||
dbgBgnTime[tag] = micros();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgClearStats() {
|
||||
for (int i = 0; i < DBG_COUNT_DIM; i++) {
|
||||
dbgCount[i] = 0;
|
||||
if (i < DBG_TIME_DIM) {
|
||||
dbgMaxTime[i] = 0;
|
||||
dbgMinTime[i] = 9999999;
|
||||
dbgTotalTime[i] = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgEndTime(DbgTag tag) {
|
||||
uint32_t m = micros() - dbgBgnTime[tag];
|
||||
dbgTotalTime[tag] += m;
|
||||
if (m > dbgMaxTime[tag]) {
|
||||
dbgMaxTime[tag] = m;
|
||||
}
|
||||
if (m < dbgMinTime[tag]) {
|
||||
dbgMinTime[tag] = m;
|
||||
}
|
||||
dbgCount[tag]++;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgEventCount(DbgTag tag) {
|
||||
dbgCount[tag]++;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgPrintTagText(uint8_t tag) {
|
||||
#define DBG_TAG(e, m) case e: Serial.print(F(m)); break;
|
||||
switch (tag) {
|
||||
DBG_TAG_LIST
|
||||
}
|
||||
#undef DBG_TAG
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static void dbgPrintStats() {
|
||||
Serial.println();
|
||||
Serial.println(F("======================="));
|
||||
Serial.println(F("item,event,min,max,avg"));
|
||||
Serial.println(F("tag,count,usec,usec,usec"));
|
||||
for (int i = 0; i < DBG_COUNT_DIM; i++) {
|
||||
if (dbgCount[i]) {
|
||||
dbgPrintTagText(i);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgCount[i]);
|
||||
if (i < DBG_TIME_DIM) {
|
||||
Serial.print(',');
|
||||
Serial.print(dbgMinTime[i]);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgMaxTime[i]);
|
||||
Serial.print(',');
|
||||
Serial.print(dbgTotalTime[i]/dbgCount[i]);
|
||||
}
|
||||
Serial.println();
|
||||
}
|
||||
}
|
||||
Serial.println(F("======================="));
|
||||
Serial.println();
|
||||
}
|
||||
#undef DBG_TAG_LIST
|
||||
#define DBG_BEGIN_TIME(tag) dbgBeginTime(tag)
|
||||
#define DBG_END_TIME(tag) dbgEndTime(tag)
|
||||
#define DBG_EVENT_COUNT(tag) dbgEventCount(tag)
|
||||
#else // DBG_PROFILE_STATS
|
||||
#define DBG_BEGIN_TIME(tag)
|
||||
#define DBG_END_TIME(tag)
|
||||
#define DBG_EVENT_COUNT(tag)
|
||||
static void dbgClearStats() {}
|
||||
static void dbgPrintStats() {}
|
||||
#endif // DBG_PROFILE_STATS
|
||||
//==============================================================================
|
||||
#if USE_SD_CRC
|
||||
// CRC functions
|
||||
//------------------------------------------------------------------------------
|
||||
static uint8_t CRC7(const uint8_t* data, uint8_t n) {
|
||||
uint8_t crc = 0;
|
||||
for (uint8_t i = 0; i < n; i++) {
|
||||
uint8_t d = data[i];
|
||||
for (uint8_t j = 0; j < 8; j++) {
|
||||
crc <<= 1;
|
||||
if ((d & 0x80) ^ (crc & 0x80)) {
|
||||
crc ^= 0x09;
|
||||
}
|
||||
d <<= 1;
|
||||
}
|
||||
}
|
||||
return (crc << 1) | 1;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
#if USE_SD_CRC == 1
|
||||
// Shift based CRC-CCITT
|
||||
// uses the x^16,x^12,x^5,x^1 polynomial.
|
||||
static uint16_t CRC_CCITT(const uint8_t *data, size_t n) {
|
||||
uint16_t crc = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
crc = (uint8_t)(crc >> 8) | (crc << 8);
|
||||
crc ^= data[i];
|
||||
crc ^= (uint8_t)(crc & 0xff) >> 4;
|
||||
crc ^= crc << 12;
|
||||
crc ^= (crc & 0xff) << 5;
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#elif USE_SD_CRC > 1 // CRC_CCITT
|
||||
//------------------------------------------------------------------------------
|
||||
// Table based CRC-CCITT
|
||||
// uses the x^16,x^12,x^5,x^1 polynomial.
|
||||
#ifdef __AVR__
|
||||
static const uint16_t crctab[] PROGMEM = {
|
||||
#else // __AVR__
|
||||
static const uint16_t crctab[] = {
|
||||
#endif // __AVR__
|
||||
0x0000, 0x1021, 0x2042, 0x3063, 0x4084, 0x50A5, 0x60C6, 0x70E7,
|
||||
0x8108, 0x9129, 0xA14A, 0xB16B, 0xC18C, 0xD1AD, 0xE1CE, 0xF1EF,
|
||||
0x1231, 0x0210, 0x3273, 0x2252, 0x52B5, 0x4294, 0x72F7, 0x62D6,
|
||||
0x9339, 0x8318, 0xB37B, 0xA35A, 0xD3BD, 0xC39C, 0xF3FF, 0xE3DE,
|
||||
0x2462, 0x3443, 0x0420, 0x1401, 0x64E6, 0x74C7, 0x44A4, 0x5485,
|
||||
0xA56A, 0xB54B, 0x8528, 0x9509, 0xE5EE, 0xF5CF, 0xC5AC, 0xD58D,
|
||||
0x3653, 0x2672, 0x1611, 0x0630, 0x76D7, 0x66F6, 0x5695, 0x46B4,
|
||||
0xB75B, 0xA77A, 0x9719, 0x8738, 0xF7DF, 0xE7FE, 0xD79D, 0xC7BC,
|
||||
0x48C4, 0x58E5, 0x6886, 0x78A7, 0x0840, 0x1861, 0x2802, 0x3823,
|
||||
0xC9CC, 0xD9ED, 0xE98E, 0xF9AF, 0x8948, 0x9969, 0xA90A, 0xB92B,
|
||||
0x5AF5, 0x4AD4, 0x7AB7, 0x6A96, 0x1A71, 0x0A50, 0x3A33, 0x2A12,
|
||||
0xDBFD, 0xCBDC, 0xFBBF, 0xEB9E, 0x9B79, 0x8B58, 0xBB3B, 0xAB1A,
|
||||
0x6CA6, 0x7C87, 0x4CE4, 0x5CC5, 0x2C22, 0x3C03, 0x0C60, 0x1C41,
|
||||
0xEDAE, 0xFD8F, 0xCDEC, 0xDDCD, 0xAD2A, 0xBD0B, 0x8D68, 0x9D49,
|
||||
0x7E97, 0x6EB6, 0x5ED5, 0x4EF4, 0x3E13, 0x2E32, 0x1E51, 0x0E70,
|
||||
0xFF9F, 0xEFBE, 0xDFDD, 0xCFFC, 0xBF1B, 0xAF3A, 0x9F59, 0x8F78,
|
||||
0x9188, 0x81A9, 0xB1CA, 0xA1EB, 0xD10C, 0xC12D, 0xF14E, 0xE16F,
|
||||
0x1080, 0x00A1, 0x30C2, 0x20E3, 0x5004, 0x4025, 0x7046, 0x6067,
|
||||
0x83B9, 0x9398, 0xA3FB, 0xB3DA, 0xC33D, 0xD31C, 0xE37F, 0xF35E,
|
||||
0x02B1, 0x1290, 0x22F3, 0x32D2, 0x4235, 0x5214, 0x6277, 0x7256,
|
||||
0xB5EA, 0xA5CB, 0x95A8, 0x8589, 0xF56E, 0xE54F, 0xD52C, 0xC50D,
|
||||
0x34E2, 0x24C3, 0x14A0, 0x0481, 0x7466, 0x6447, 0x5424, 0x4405,
|
||||
0xA7DB, 0xB7FA, 0x8799, 0x97B8, 0xE75F, 0xF77E, 0xC71D, 0xD73C,
|
||||
0x26D3, 0x36F2, 0x0691, 0x16B0, 0x6657, 0x7676, 0x4615, 0x5634,
|
||||
0xD94C, 0xC96D, 0xF90E, 0xE92F, 0x99C8, 0x89E9, 0xB98A, 0xA9AB,
|
||||
0x5844, 0x4865, 0x7806, 0x6827, 0x18C0, 0x08E1, 0x3882, 0x28A3,
|
||||
0xCB7D, 0xDB5C, 0xEB3F, 0xFB1E, 0x8BF9, 0x9BD8, 0xABBB, 0xBB9A,
|
||||
0x4A75, 0x5A54, 0x6A37, 0x7A16, 0x0AF1, 0x1AD0, 0x2AB3, 0x3A92,
|
||||
0xFD2E, 0xED0F, 0xDD6C, 0xCD4D, 0xBDAA, 0xAD8B, 0x9DE8, 0x8DC9,
|
||||
0x7C26, 0x6C07, 0x5C64, 0x4C45, 0x3CA2, 0x2C83, 0x1CE0, 0x0CC1,
|
||||
0xEF1F, 0xFF3E, 0xCF5D, 0xDF7C, 0xAF9B, 0xBFBA, 0x8FD9, 0x9FF8,
|
||||
0x6E17, 0x7E36, 0x4E55, 0x5E74, 0x2E93, 0x3EB2, 0x0ED1, 0x1EF0
|
||||
};
|
||||
static uint16_t CRC_CCITT(const uint8_t* data, size_t n) {
|
||||
uint16_t crc = 0;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
#ifdef __AVR__
|
||||
crc = pgm_read_word(&crctab[(crc >> 8 ^ data[i]) & 0XFF]) ^ (crc << 8);
|
||||
#else // __AVR__
|
||||
crc = crctab[(crc >> 8 ^ data[i]) & 0XFF] ^ (crc << 8);
|
||||
#endif // __AVR__
|
||||
}
|
||||
return crc;
|
||||
}
|
||||
#endif // CRC_CCITT
|
||||
#endif // USE_SD_CRC
|
||||
//==============================================================================
|
||||
// SdSpiCard member functions
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::begin(SdSpiDriver* spi, uint8_t csPin, SPISettings settings) {
|
||||
m_spiActive = false;
|
||||
m_errorCode = SD_CARD_ERROR_NONE;
|
||||
m_type = 0;
|
||||
m_spiDriver = spi;
|
||||
uint16_t t0 = curTimeMS();
|
||||
uint32_t arg;
|
||||
|
||||
m_spiDriver->begin(csPin);
|
||||
m_spiDriver->setSpiSettings(SD_SCK_HZ(250000));
|
||||
spiStart();
|
||||
|
||||
// must supply min of 74 clock cycles with CS high.
|
||||
spiUnselect();
|
||||
for (uint8_t i = 0; i < 10; i++) {
|
||||
spiSend(0XFF);
|
||||
}
|
||||
spiSelect();
|
||||
|
||||
DBG_BEGIN_TIME(DBG_CMD0_TIME);
|
||||
// command to go idle in SPI mode
|
||||
for (uint8_t i = 1;; i++) {
|
||||
DBG_EVENT_COUNT(DBG_CMD0_COUNT);
|
||||
if (cardCommand(CMD0, 0) == R1_IDLE_STATE) {
|
||||
break;
|
||||
}
|
||||
if (i == SD_CMD0_RETRY) {
|
||||
error(SD_CARD_ERROR_CMD0);
|
||||
goto fail;
|
||||
}
|
||||
// stop multi-block write
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
// finish block transfer
|
||||
for (int i = 0; i < 520; i++) {
|
||||
spiReceive();
|
||||
}
|
||||
}
|
||||
DBG_END_TIME(DBG_CMD0_TIME);
|
||||
#if USE_SD_CRC
|
||||
if (cardCommand(CMD59, 1) != R1_IDLE_STATE) {
|
||||
error(SD_CARD_ERROR_CMD59);
|
||||
goto fail;
|
||||
}
|
||||
#endif // USE_SD_CRC
|
||||
// check SD version
|
||||
if (cardCommand(CMD8, 0x1AA) == (R1_ILLEGAL_COMMAND | R1_IDLE_STATE)) {
|
||||
type(SD_CARD_TYPE_SD1);
|
||||
} else {
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
m_status = spiReceive();
|
||||
}
|
||||
if (m_status == 0XAA) {
|
||||
type(SD_CARD_TYPE_SD2);
|
||||
} else {
|
||||
error(SD_CARD_ERROR_CMD8);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
// initialize card and send host supports SDHC if SD2
|
||||
arg = type() == SD_CARD_TYPE_SD2 ? 0X40000000 : 0;
|
||||
DBG_BEGIN_TIME(DBG_ACMD41_TIME);
|
||||
while (cardAcmd(ACMD41, arg) != R1_READY_STATE) {
|
||||
DBG_EVENT_COUNT(DBG_ACMD41_COUNT);
|
||||
// check for timeout
|
||||
if (isTimedOut(t0, SD_INIT_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ACMD41);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
DBG_END_TIME(DBG_ACMD41_TIME);
|
||||
// if SD2 read OCR register to check for SDHC card
|
||||
if (type() == SD_CARD_TYPE_SD2) {
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
goto fail;
|
||||
}
|
||||
if ((spiReceive() & 0XC0) == 0XC0) {
|
||||
type(SD_CARD_TYPE_SDHC);
|
||||
}
|
||||
// Discard rest of ocr - contains allowed voltage range.
|
||||
for (uint8_t i = 0; i < 3; i++) {
|
||||
spiReceive();
|
||||
}
|
||||
}
|
||||
spiStop();
|
||||
m_spiDriver->setSpiSettings(settings);
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send command and return error code. Return zero for OK
|
||||
uint8_t SdSpiCard::cardCommand(uint8_t cmd, uint32_t arg) {
|
||||
// select card
|
||||
if (!m_spiActive) {
|
||||
spiStart();
|
||||
}
|
||||
// wait if busy unless CMD0
|
||||
if (cmd != CMD0) {
|
||||
DBG_BEGIN_TIME(DBG_CMD_BUSY);
|
||||
waitNotBusy(SD_CMD_TIMEOUT);
|
||||
DBG_END_TIME(DBG_CMD_BUSY);
|
||||
}
|
||||
|
||||
#if USE_SD_CRC
|
||||
// form message
|
||||
uint8_t buf[6];
|
||||
buf[0] = (uint8_t)0x40U | cmd;
|
||||
buf[1] = (uint8_t)(arg >> 24U);
|
||||
buf[2] = (uint8_t)(arg >> 16U);
|
||||
buf[3] = (uint8_t)(arg >> 8U);
|
||||
buf[4] = (uint8_t)arg;
|
||||
|
||||
// add CRC
|
||||
buf[5] = CRC7(buf, 5);
|
||||
|
||||
// send message
|
||||
spiSend(buf, 6);
|
||||
#else // USE_SD_CRC
|
||||
// send command
|
||||
spiSend(cmd | 0x40);
|
||||
|
||||
// send argument
|
||||
uint8_t *pa = reinterpret_cast<uint8_t *>(&arg);
|
||||
for (int8_t i = 3; i >= 0; i--) {
|
||||
spiSend(pa[i]);
|
||||
}
|
||||
// send CRC - correct for CMD0 with arg zero or CMD8 with arg 0X1AA
|
||||
spiSend(cmd == CMD0 ? 0X95 : 0X87);
|
||||
#endif // USE_SD_CRC
|
||||
|
||||
// discard first fill byte to avoid MISO pull-up problem.
|
||||
spiReceive();
|
||||
|
||||
// there are 1-8 fill bytes before response. fill bytes should be 0XFF.
|
||||
for (uint8_t i = 0; ((m_status = spiReceive()) & 0X80) && i < 10; i++) {
|
||||
}
|
||||
return m_status;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
uint32_t SdSpiCard::cardCapacity() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? sdCardCapacity(&csd) : 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiCard::dbgClearStats() {::dbgClearStats();}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiCard::dbgPrintStats() {::dbgPrintStats();}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
csd_t csd;
|
||||
if (!readCSD(&csd)) {
|
||||
goto fail;
|
||||
}
|
||||
// check for single block erase
|
||||
if (!csd.v1.erase_blk_en) {
|
||||
// erase size mask
|
||||
uint8_t m = (csd.v1.sector_size_high << 1) | csd.v1.sector_size_low;
|
||||
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
|
||||
// error card can't erase specified area
|
||||
error(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
if (m_type != SD_CARD_TYPE_SDHC) {
|
||||
firstBlock <<= 9;
|
||||
lastBlock <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD32, firstBlock)
|
||||
|| cardCommand(CMD33, lastBlock)
|
||||
|| cardCommand(CMD38, 0)) {
|
||||
error(SD_CARD_ERROR_ERASE);
|
||||
goto fail;
|
||||
}
|
||||
DBG_BEGIN_TIME(DBG_ERASE_BUSY);
|
||||
if (!waitNotBusy(SD_ERASE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_ERASE_BUSY);
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::eraseSingleBlockEnable() {
|
||||
csd_t csd;
|
||||
return readCSD(&csd) ? csd.v1.erase_blk_en : false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::isBusy() {
|
||||
bool rtn = true;
|
||||
bool spiActive = m_spiActive;
|
||||
if (!spiActive) {
|
||||
spiStart();
|
||||
}
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
if (0XFF == spiReceive()) {
|
||||
rtn = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!spiActive) {
|
||||
spiStop();
|
||||
}
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::isTimedOut(uint16_t startMS, uint16_t timeoutMS) {
|
||||
#if WDT_YIELD_TIME_MICROS
|
||||
static uint32_t last;
|
||||
if ((micros() - last) > WDT_YIELD_TIME_MICROS) {
|
||||
SysCall::yield();
|
||||
last = micros();
|
||||
}
|
||||
#endif // WDT_YIELD_TIME_MICROS
|
||||
return (curTimeMS() - startMS) > timeoutMS;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readBlock(uint32_t blockNumber, uint8_t* dst) {
|
||||
SD_TRACE("RB", blockNumber);
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
blockNumber <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD17, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD17);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 512)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readBlocks(uint32_t block, uint8_t* dst, size_t count) {
|
||||
if (!readStart(block)) {
|
||||
return false;
|
||||
}
|
||||
for (uint16_t b = 0; b < count; b++, dst += 512) {
|
||||
if (!readData(dst, 512)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return readStop();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readData(uint8_t *dst) {
|
||||
return readData(dst, 512);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readData(uint8_t* dst, size_t count) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc;
|
||||
#endif // USE_SD_CRC
|
||||
DBG_BEGIN_TIME(DBG_WAIT_READ);
|
||||
// wait for start block token
|
||||
uint16_t t0 = curTimeMS();
|
||||
while ((m_status = spiReceive()) == 0XFF) {
|
||||
if (isTimedOut(t0, SD_READ_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
DBG_END_TIME(DBG_WAIT_READ);
|
||||
if (m_status != DATA_START_BLOCK) {
|
||||
error(SD_CARD_ERROR_READ);
|
||||
goto fail;
|
||||
}
|
||||
// transfer data
|
||||
if ((m_status = spiReceive(dst, count))) {
|
||||
error(SD_CARD_ERROR_DMA);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
#if USE_SD_CRC
|
||||
// get crc
|
||||
crc = (spiReceive() << 8) | spiReceive();
|
||||
if (crc != CRC_CCITT(dst, count)) {
|
||||
error(SD_CARD_ERROR_READ_CRC);
|
||||
goto fail;
|
||||
}
|
||||
#else
|
||||
// discard crc
|
||||
spiReceive();
|
||||
spiReceive();
|
||||
#endif // USE_SD_CRC
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readOCR(uint32_t* ocr) {
|
||||
uint8_t *p = reinterpret_cast<uint8_t*>(ocr);
|
||||
if (cardCommand(CMD58, 0)) {
|
||||
error(SD_CARD_ERROR_CMD58);
|
||||
goto fail;
|
||||
}
|
||||
for (uint8_t i = 0; i < 4; i++) {
|
||||
p[3 - i] = spiReceive();
|
||||
}
|
||||
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** read CID or CSR register */
|
||||
bool SdSpiCard::readRegister(uint8_t cmd, void* buf) {
|
||||
uint8_t* dst = reinterpret_cast<uint8_t*>(buf);
|
||||
if (cardCommand(cmd, 0)) {
|
||||
error(SD_CARD_ERROR_READ_REG);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(dst, 16)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readStart(uint32_t blockNumber) {
|
||||
SD_TRACE("RS", blockNumber);
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
blockNumber <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD18, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD18);
|
||||
goto fail;
|
||||
}
|
||||
// spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCard::readStatus(uint8_t* status) {
|
||||
// retrun is R2 so read extra status byte.
|
||||
if (cardAcmd(ACMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_ACMD13);
|
||||
goto fail;
|
||||
}
|
||||
if (!readData(status, 64)) {
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void SdSpiCard::spiStart() {
|
||||
if (!m_spiActive) {
|
||||
spiActivate();
|
||||
spiSelect();
|
||||
m_spiActive = true;
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
void SdSpiCard::spiStop() {
|
||||
if (m_spiActive) {
|
||||
spiUnselect();
|
||||
spiSend(0XFF);
|
||||
spiDeactivate();
|
||||
m_spiActive = false;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::readStop() {
|
||||
if (cardCommand(CMD12, 0)) {
|
||||
error(SD_CARD_ERROR_CMD12);
|
||||
goto fail;
|
||||
}
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// wait for card to go not busy
|
||||
bool SdSpiCard::waitNotBusy(uint16_t timeoutMS) {
|
||||
uint16_t t0 = curTimeMS();
|
||||
#if WDT_YIELD_TIME_MICROS
|
||||
// Call isTimedOut first to insure yield is called.
|
||||
while (!isTimedOut(t0, timeoutMS)) {
|
||||
if (spiReceive() == 0XFF) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
#else // WDT_YIELD_TIME_MICROS
|
||||
// Check not busy first since yield is not called in isTimedOut.
|
||||
while (spiReceive() != 0XFF) {
|
||||
if (isTimedOut(t0, timeoutMS)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
#endif // WDT_YIELD_TIME_MICROS
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeBlock(uint32_t blockNumber, const uint8_t* src) {
|
||||
SD_TRACE("WB", blockNumber);
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
blockNumber <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD24, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD24);
|
||||
goto fail;
|
||||
}
|
||||
if (!writeData(DATA_START_BLOCK, src)) {
|
||||
goto fail;
|
||||
}
|
||||
|
||||
|
||||
#if CHECK_FLASH_PROGRAMMING
|
||||
// wait for flash programming to complete
|
||||
DBG_BEGIN_TIME(DBG_WRITE_FLASH);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_FLASH_PROGRAMMING);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_FLASH);
|
||||
// response is r2 so get and check two bytes for nonzero
|
||||
if (cardCommand(CMD13, 0) || spiReceive()) {
|
||||
error(SD_CARD_ERROR_CMD13);
|
||||
goto fail;
|
||||
}
|
||||
#endif // CHECK_PROGRAMMING
|
||||
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeBlocks(uint32_t block, const uint8_t* src, size_t count) {
|
||||
if (!writeStart(block)) {
|
||||
goto fail;
|
||||
}
|
||||
for (size_t b = 0; b < count; b++, src += 512) {
|
||||
if (!writeData(src)) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
return writeStop();
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeData(const uint8_t* src) {
|
||||
// wait for previous write to finish
|
||||
DBG_BEGIN_TIME(DBG_WRITE_BUSY);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
error(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_BUSY);
|
||||
if (!writeData(WRITE_MULTIPLE_TOKEN, src)) {
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// send one block of data for write block or write multiple blocks
|
||||
bool SdSpiCard::writeData(uint8_t token, const uint8_t* src) {
|
||||
#if USE_SD_CRC
|
||||
uint16_t crc = CRC_CCITT(src, 512);
|
||||
#else // USE_SD_CRC
|
||||
uint16_t crc = 0XFFFF;
|
||||
#endif // USE_SD_CRC
|
||||
spiSend(token);
|
||||
spiSend(src, 512);
|
||||
spiSend(crc >> 8);
|
||||
spiSend(crc & 0XFF);
|
||||
|
||||
m_status = spiReceive();
|
||||
if ((m_status & DATA_RES_MASK) != DATA_RES_ACCEPTED) {
|
||||
error(SD_CARD_ERROR_WRITE);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeStart(uint32_t blockNumber) {
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
blockNumber <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD25, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD25);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeStart(uint32_t blockNumber, uint32_t eraseCount) {
|
||||
SD_TRACE("WS", blockNumber);
|
||||
// send pre-erase count
|
||||
if (cardAcmd(ACMD23, eraseCount)) {
|
||||
error(SD_CARD_ERROR_ACMD23);
|
||||
goto fail;
|
||||
}
|
||||
// use address if not SDHC card
|
||||
if (type() != SD_CARD_TYPE_SDHC) {
|
||||
blockNumber <<= 9;
|
||||
}
|
||||
if (cardCommand(CMD25, blockNumber)) {
|
||||
error(SD_CARD_ERROR_CMD25);
|
||||
goto fail;
|
||||
}
|
||||
return true;
|
||||
|
||||
fail:
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
bool SdSpiCard::writeStop() {
|
||||
DBG_BEGIN_TIME(DBG_WRITE_STOP);
|
||||
if (!waitNotBusy(SD_WRITE_TIMEOUT)) {
|
||||
goto fail;
|
||||
}
|
||||
DBG_END_TIME(DBG_WRITE_STOP);
|
||||
spiSend(STOP_TRAN_TOKEN);
|
||||
spiStop();
|
||||
return true;
|
||||
|
||||
fail:
|
||||
error(SD_CARD_ERROR_STOP_TRAN);
|
||||
spiStop();
|
||||
return false;
|
||||
}
|
379
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCard.h
Normal file
379
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCard.h
Normal file
|
@ -0,0 +1,379 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdSpiCard_h
|
||||
#define SdSpiCard_h
|
||||
/**
|
||||
* \file
|
||||
* \brief SdSpiCard class for V2 SD/SDHC cards
|
||||
*/
|
||||
#include <stddef.h>
|
||||
#include "../SysCall.h"
|
||||
#include "SdInfo.h"
|
||||
#include "../FatLib/BaseBlockDriver.h"
|
||||
#include "../SpiDriver/SdSpiDriver.h"
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdSpiCard
|
||||
* \brief Raw access to SD and SDHC flash memory cards via SPI protocol.
|
||||
*/
|
||||
#if ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
class SdSpiCard : public BaseBlockDriver {
|
||||
#else // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
class SdSpiCard {
|
||||
#endif // ENABLE_EXTENDED_TRANSFER_CLASS || ENABLE_SDIO_CLASS
|
||||
public:
|
||||
/** Construct an instance of SdSpiCard. */
|
||||
SdSpiCard() : m_errorCode(SD_CARD_ERROR_INIT_NOT_CALLED), m_type(0) {}
|
||||
/** Initialize the SD card.
|
||||
* \param[in] spi SPI driver for card.
|
||||
* \param[in] csPin card chip select pin.
|
||||
* \param[in] spiSettings SPI speed, mode, and bit order.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(SdSpiDriver* spi, uint8_t csPin, SPISettings spiSettings);
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
* \return The number of 512 byte sectors in the card
|
||||
* or zero if an error occurs.
|
||||
*/
|
||||
uint32_t cardCapacity();
|
||||
/** \return Card size in sectors or zero if an error occurs. */
|
||||
uint32_t cardSize() {return cardCapacity();}
|
||||
/** Clear debug stats. */
|
||||
void dbgClearStats();
|
||||
/** Print debug stats. */
|
||||
void dbgPrintStats();
|
||||
/** Erase a range of blocks.
|
||||
*
|
||||
* \param[in] firstBlock The address of the first block in the range.
|
||||
* \param[in] lastBlock The address of the last block in the range.
|
||||
*
|
||||
* \note This function requests the SD card to do a flash erase for a
|
||||
* range of blocks. The data on the card after an erase operation is
|
||||
* either 0 or 1, depends on the card vendor. The card must support
|
||||
* single block erase.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool erase(uint32_t firstBlock, uint32_t lastBlock);
|
||||
/** Determine if card supports single block erase.
|
||||
*
|
||||
* \return true is returned if single block erase is supported.
|
||||
* false is returned if single block erase is not supported.
|
||||
*/
|
||||
bool eraseSingleBlockEnable();
|
||||
/**
|
||||
* Set SD error code.
|
||||
* \param[in] code value for error code.
|
||||
*/
|
||||
void error(uint8_t code) {
|
||||
m_errorCode = code;
|
||||
}
|
||||
/**
|
||||
* \return code for the last error. See SdInfo.h for a list of error codes.
|
||||
*/
|
||||
int errorCode() const {
|
||||
return m_errorCode;
|
||||
}
|
||||
/** \return error data for last error. */
|
||||
int errorData() const {
|
||||
return m_status;
|
||||
}
|
||||
/**
|
||||
* Check for busy. MISO low indicates the card is busy.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/**
|
||||
* Read a 512 byte block from an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlock(uint32_t lba, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte blocks from an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be read.
|
||||
* \param[in] nb Number of blocks to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlocks(uint32_t lba, uint8_t* dst, size_t nb);
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCID(cid_t* cid) {
|
||||
return readRegister(CMD10, cid);
|
||||
}
|
||||
/**
|
||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||
* provides information regarding access to the card's contents.
|
||||
*
|
||||
* \param[out] csd pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCSD(csd_t* csd) {
|
||||
return readRegister(CMD9, csd);
|
||||
}
|
||||
/** Read one data block in a multiple block read sequence
|
||||
*
|
||||
* \param[out] dst Pointer to the location for the data to be read.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readData(uint8_t *dst);
|
||||
/** Read OCR register.
|
||||
*
|
||||
* \param[out] ocr Value of OCR register.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool readOCR(uint32_t* ocr);
|
||||
/** Start a read multiple blocks sequence.
|
||||
*
|
||||
* \param[in] blockNumber Address of first block in sequence.
|
||||
*
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple block reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStart(uint32_t blockNumber);
|
||||
/** Return the 64 byte card status
|
||||
* \param[out] status location for 64 status bytes.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStatus(uint8_t* status);
|
||||
/** End a read multiple blocks sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStop();
|
||||
/** \return success if sync successful. Not for user apps. */
|
||||
bool syncBlocks() {return true;}
|
||||
/** Return the card type: SD V1, SD V2 or SDHC
|
||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
|
||||
*/
|
||||
int type() const {
|
||||
return m_type;
|
||||
}
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlock(uint32_t lba, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte blocks to an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be written.
|
||||
* \param[in] nb Number of blocks to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlocks(uint32_t lba, const uint8_t* src, size_t nb);
|
||||
/** Write one data block in a multiple block write sequence.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeData(const uint8_t* src);
|
||||
/** Start a write multiple blocks sequence.
|
||||
*
|
||||
* \param[in] blockNumber Address of first block in sequence.
|
||||
*
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple block writes.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t blockNumber);
|
||||
|
||||
/** Start a write multiple blocks sequence with pre-erase.
|
||||
*
|
||||
* \param[in] blockNumber Address of first block in sequence.
|
||||
* \param[in] eraseCount The number of blocks to be pre-erased.
|
||||
*
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple block writes.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t blockNumber, uint32_t eraseCount);
|
||||
/** End a write multiple blocks sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStop();
|
||||
/** Set CS low and activate the card. */
|
||||
void spiStart();
|
||||
/** Set CS high and deactivate the card. */
|
||||
void spiStop();
|
||||
|
||||
private:
|
||||
// private functions
|
||||
uint8_t cardAcmd(uint8_t cmd, uint32_t arg) {
|
||||
cardCommand(CMD55, 0);
|
||||
return cardCommand(cmd, arg);
|
||||
}
|
||||
uint8_t cardCommand(uint8_t cmd, uint32_t arg);
|
||||
bool isTimedOut(uint16_t startMS, uint16_t timeoutMS);
|
||||
bool readData(uint8_t* dst, size_t count);
|
||||
bool readRegister(uint8_t cmd, void* buf);
|
||||
|
||||
void type(uint8_t value) {
|
||||
m_type = value;
|
||||
}
|
||||
|
||||
bool waitNotBusy(uint16_t timeoutMS);
|
||||
bool writeData(uint8_t token, const uint8_t* src);
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// functions defined in SdSpiDriver.h
|
||||
void spiActivate() {
|
||||
m_spiDriver->activate();
|
||||
}
|
||||
void spiDeactivate() {
|
||||
m_spiDriver->deactivate();
|
||||
}
|
||||
uint8_t spiReceive() {
|
||||
return m_spiDriver->receive();
|
||||
}
|
||||
uint8_t spiReceive(uint8_t* buf, size_t n) {
|
||||
return m_spiDriver->receive(buf, n);
|
||||
}
|
||||
void spiSend(uint8_t data) {
|
||||
m_spiDriver->send(data);
|
||||
}
|
||||
void spiSend(const uint8_t* buf, size_t n) {
|
||||
m_spiDriver->send(buf, n);
|
||||
}
|
||||
void spiSelect() {
|
||||
m_spiDriver->select();
|
||||
}
|
||||
void spiUnselect() {
|
||||
m_spiDriver->unselect();
|
||||
}
|
||||
uint8_t m_errorCode;
|
||||
SdSpiDriver *m_spiDriver;
|
||||
bool m_spiActive;
|
||||
uint8_t m_status;
|
||||
uint8_t m_type;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdSpiCardEX
|
||||
* \brief Extended SD I/O block driver.
|
||||
*/
|
||||
class SdSpiCardEX : public SdSpiCard {
|
||||
public:
|
||||
/** Initialize the SD card
|
||||
*
|
||||
* \param[in] spi SPI driver.
|
||||
* \param[in] csPin Card chip select pin number.
|
||||
* \param[in] spiSettings SPI speed, mode, and bit order.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool begin(SdSpiDriver* spi, uint8_t csPin, SPISettings spiSettings) {
|
||||
m_curState = IDLE_STATE;
|
||||
return SdSpiCard::begin(spi, csPin, spiSettings);
|
||||
}
|
||||
/**
|
||||
* Read a 512 byte block from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlock(uint32_t block, uint8_t* dst);
|
||||
/** End multi-block transfer and go to idle state.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool syncBlocks();
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlock(uint32_t block, const uint8_t* src);
|
||||
/**
|
||||
* Read multiple 512 byte blocks from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[in] nb Number of blocks to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlocks(uint32_t block, uint8_t* dst, size_t nb);
|
||||
/**
|
||||
* Write multiple 512 byte blocks to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] nb Number of blocks to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb);
|
||||
|
||||
private:
|
||||
static const uint32_t IDLE_STATE = 0;
|
||||
static const uint32_t READ_STATE = 1;
|
||||
static const uint32_t WRITE_STATE = 2;
|
||||
uint32_t m_curBlock;
|
||||
uint8_t m_curState;
|
||||
};
|
||||
#endif // SdSpiCard_h
|
94
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCardEX.cpp
Normal file
94
hardware/sd_card_formatter/src/SdFat/SdCard/SdSpiCardEX.cpp
Normal file
|
@ -0,0 +1,94 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdSpiCard.h"
|
||||
bool SdSpiCardEX::readBlock(uint32_t block, uint8_t* dst) {
|
||||
if (m_curState != READ_STATE || block != m_curBlock) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
if (!SdSpiCard::readStart(block)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock = block;
|
||||
m_curState = READ_STATE;
|
||||
}
|
||||
if (!SdSpiCard::readData(dst)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock++;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::readBlocks(uint32_t block, uint8_t* dst, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!readBlock(block + i, dst + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::syncBlocks() {
|
||||
if (m_curState == READ_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdSpiCard::readStop()) {
|
||||
return false;
|
||||
}
|
||||
} else if (m_curState == WRITE_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdSpiCard::writeStop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::writeBlock(uint32_t block, const uint8_t* src) {
|
||||
if (m_curState != WRITE_STATE || m_curBlock != block) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
if (!SdSpiCard::writeStart(block)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock = block;
|
||||
m_curState = WRITE_STATE;
|
||||
}
|
||||
if (!SdSpiCard::writeData(src)) {
|
||||
return false;
|
||||
}
|
||||
m_curBlock++;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdSpiCardEX::writeBlocks(uint32_t block,
|
||||
const uint8_t* src, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!writeBlock(block + i, src + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
303
hardware/sd_card_formatter/src/SdFat/SdCard/SdioCard.h
Normal file
303
hardware/sd_card_formatter/src/SdFat/SdCard/SdioCard.h
Normal file
|
@ -0,0 +1,303 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdioCard_h
|
||||
#define SdioCard_h
|
||||
#include "../SysCall.h"
|
||||
#include "../BlockDriver.h"
|
||||
/**
|
||||
* \class SdioCard
|
||||
* \brief Raw SDIO access to SD and SDHC flash memory cards.
|
||||
*/
|
||||
class SdioCard : public BaseBlockDriver {
|
||||
public:
|
||||
/** Initialize the SD card.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin();
|
||||
/**
|
||||
* Determine the size of an SD flash memory card.
|
||||
*
|
||||
* \return The number of 512 byte sectors in the card
|
||||
* or zero if an error occurs.
|
||||
*/
|
||||
uint32_t cardCapacity();
|
||||
/** \return Card size in sectors or zero if an error occurs. */
|
||||
uint32_t cardSize() {return cardCapacity();}
|
||||
/** Erase a range of blocks.
|
||||
*
|
||||
* \param[in] firstBlock The address of the first block in the range.
|
||||
* \param[in] lastBlock The address of the last block in the range.
|
||||
*
|
||||
* \note This function requests the SD card to do a flash erase for a
|
||||
* range of blocks. The data on the card after an erase operation is
|
||||
* either 0 or 1, depends on the card vendor. The card must support
|
||||
* single block erase.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool erase(uint32_t firstBlock, uint32_t lastBlock);
|
||||
/**
|
||||
* \return code for the last error. See SdInfo.h for a list of error codes.
|
||||
*/
|
||||
uint8_t errorCode();
|
||||
/** \return error data for last error. */
|
||||
uint32_t errorData();
|
||||
/** \return error line for last error. Tmp function for debug. */
|
||||
uint32_t errorLine();
|
||||
/**
|
||||
* Check for busy with CMD13.
|
||||
*
|
||||
* \return true if busy else false.
|
||||
*/
|
||||
bool isBusy();
|
||||
/** \return the SD clock frequency in kHz. */
|
||||
uint32_t kHzSdClk();
|
||||
/**
|
||||
* Read a 512 byte block from an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlock(uint32_t lba, uint8_t* dst);
|
||||
/**
|
||||
* Read multiple 512 byte blocks from an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be read.
|
||||
* \param[in] nb Number of blocks to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlocks(uint32_t lba, uint8_t* dst, size_t nb);
|
||||
/**
|
||||
* Read a card's CID register. The CID contains card identification
|
||||
* information such as Manufacturer ID, Product name, Product serial
|
||||
* number and Manufacturing date.
|
||||
*
|
||||
* \param[out] cid pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCID(void* cid);
|
||||
/**
|
||||
* Read a card's CSD register. The CSD contains Card-Specific Data that
|
||||
* provides information regarding access to the card's contents.
|
||||
*
|
||||
* \param[out] csd pointer to area for returned data.
|
||||
*
|
||||
* \return true for success or false for failure.
|
||||
*/
|
||||
bool readCSD(void* csd);
|
||||
/** Read one data block in a multiple block read sequence
|
||||
*
|
||||
* \param[out] dst Pointer to the location for the data to be read.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readData(uint8_t *dst);
|
||||
/** Read OCR register.
|
||||
*
|
||||
* \param[out] ocr Value of OCR register.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool readOCR(uint32_t* ocr);
|
||||
/** Start a read multiple blocks sequence.
|
||||
*
|
||||
* \param[in] lba Address of first block in sequence.
|
||||
*
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple block reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStart(uint32_t lba);
|
||||
/** Start a read multiple blocks sequence.
|
||||
*
|
||||
* \param[in] lba Address of first block in sequence.
|
||||
* \param[in] count Maximum block count.
|
||||
* \note This function is used with readData() and readStop() for optimized
|
||||
* multiple block reads. SPI chipSelect must be low for the entire sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStart(uint32_t lba, uint32_t count);
|
||||
/** End a read multiple blocks sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readStop();
|
||||
/** \return success if sync successful. Not for user apps. */
|
||||
bool syncBlocks();
|
||||
/** Return the card type: SD V1, SD V2 or SDHC
|
||||
* \return 0 - SD V1, 1 - SD V2, or 3 - SDHC.
|
||||
*/
|
||||
uint8_t type();
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlock(uint32_t lba, const uint8_t* src);
|
||||
/**
|
||||
* Write multiple 512 byte blocks to an SD card.
|
||||
*
|
||||
* \param[in] lba Logical block to be written.
|
||||
* \param[in] nb Number of blocks to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlocks(uint32_t lba, const uint8_t* src, size_t nb);
|
||||
/** Write one data block in a multiple block write sequence.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeData(const uint8_t* src);
|
||||
/** Start a write multiple blocks sequence.
|
||||
*
|
||||
* \param[in] lba Address of first block in sequence.
|
||||
*
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple block writes.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t lba);
|
||||
/** Start a write multiple blocks sequence.
|
||||
*
|
||||
* \param[in] lba Address of first block in sequence.
|
||||
* \param[in] count Maximum block count.
|
||||
* \note This function is used with writeData() and writeStop()
|
||||
* for optimized multiple block writes.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStart(uint32_t lba, uint32_t count);
|
||||
|
||||
/** End a write multiple blocks sequence.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeStop();
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdioCardEX
|
||||
* \brief Extended SD I/O block driver.
|
||||
*/
|
||||
class SdioCardEX : public SdioCard {
|
||||
public:
|
||||
/** Initialize the SD card
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool begin() {
|
||||
m_curState = IDLE_STATE;
|
||||
return SdioCard::begin();
|
||||
}
|
||||
/** Erase a range of blocks.
|
||||
*
|
||||
* \param[in] firstBlock The address of the first block in the range.
|
||||
* \param[in] lastBlock The address of the last block in the range.
|
||||
*
|
||||
* \note This function requests the SD card to do a flash erase for a
|
||||
* range of blocks. The data on the card after an erase operation is
|
||||
* either 0 or 1, depends on the card vendor. The card must support
|
||||
* single block erase.
|
||||
*
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
return syncBlocks() && SdioCard::erase(firstBlock, lastBlock);
|
||||
}
|
||||
/**
|
||||
* Read a 512 byte block from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlock(uint32_t block, uint8_t* dst);
|
||||
/** End multi-block transfer and go to idle state.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool syncBlocks();
|
||||
/**
|
||||
* Writes a 512 byte block to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlock(uint32_t block, const uint8_t* src);
|
||||
/**
|
||||
* Read multiple 512 byte blocks from an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be read.
|
||||
* \param[in] nb Number of blocks to be read.
|
||||
* \param[out] dst Pointer to the location that will receive the data.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool readBlocks(uint32_t block, uint8_t* dst, size_t nb);
|
||||
/**
|
||||
* Write multiple 512 byte blocks to an SD card.
|
||||
*
|
||||
* \param[in] block Logical block to be written.
|
||||
* \param[in] nb Number of blocks to be written.
|
||||
* \param[in] src Pointer to the location of the data to be written.
|
||||
* \return The value true is returned for success and
|
||||
* the value false is returned for failure.
|
||||
*/
|
||||
bool writeBlocks(uint32_t block, const uint8_t* src, size_t nb);
|
||||
|
||||
private:
|
||||
static const uint32_t IDLE_STATE = 0;
|
||||
static const uint32_t READ_STATE = 1;
|
||||
static const uint32_t WRITE_STATE = 2;
|
||||
uint32_t m_curLba;
|
||||
uint32_t m_limitLba;
|
||||
uint8_t m_curState;
|
||||
};
|
||||
#endif // SdioCard_h
|
108
hardware/sd_card_formatter/src/SdFat/SdCard/SdioCardEX.cpp
Normal file
108
hardware/sd_card_formatter/src/SdFat/SdCard/SdioCardEX.cpp
Normal file
|
@ -0,0 +1,108 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdioCard.h"
|
||||
|
||||
// limit of K66 due to errata KINETIS_K_0N65N.
|
||||
const uint32_t MAX_SDHC_COUNT = 0XFFFF;
|
||||
|
||||
// Max RU is 1024 blocks.
|
||||
const uint32_t RU_MASK = 0X03FF;
|
||||
|
||||
bool SdioCardEX::readBlock(uint32_t lba, uint8_t* dst) {
|
||||
if (m_curState != READ_STATE || lba != m_curLba) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
m_limitLba = (lba + MAX_SDHC_COUNT) & ~RU_MASK;
|
||||
if (!SdioCard::readStart(lba, m_limitLba - lba)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba = lba;
|
||||
m_curState = READ_STATE;
|
||||
}
|
||||
if (!SdioCard::readData(dst)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba++;
|
||||
if (m_curLba >= m_limitLba) {
|
||||
m_curState = IDLE_STATE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::readBlocks(uint32_t lba, uint8_t* dst, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!readBlock(lba + i, dst + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::syncBlocks() {
|
||||
if (m_curState == READ_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdioCard::readStop()) {
|
||||
return false;
|
||||
}
|
||||
} else if (m_curState == WRITE_STATE) {
|
||||
m_curState = IDLE_STATE;
|
||||
if (!SdioCard::writeStop()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::writeBlock(uint32_t lba, const uint8_t* src) {
|
||||
if (m_curState != WRITE_STATE || m_curLba != lba) {
|
||||
if (!syncBlocks()) {
|
||||
return false;
|
||||
}
|
||||
m_limitLba = (lba + MAX_SDHC_COUNT) & ~RU_MASK;
|
||||
if (!SdioCard::writeStart(lba , m_limitLba - lba)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba = lba;
|
||||
m_curState = WRITE_STATE;
|
||||
}
|
||||
if (!SdioCard::writeData(src)) {
|
||||
return false;
|
||||
}
|
||||
m_curLba++;
|
||||
if (m_curLba >= m_limitLba) {
|
||||
m_curState = IDLE_STATE;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCardEX::writeBlocks(uint32_t lba, const uint8_t* src, size_t nb) {
|
||||
for (size_t i = 0; i < nb; i++) {
|
||||
if (!writeBlock(lba + i, src + i*512UL)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
800
hardware/sd_card_formatter/src/SdFat/SdCard/SdioTeensy.cpp
Normal file
800
hardware/sd_card_formatter/src/SdFat/SdCard/SdioTeensy.cpp
Normal file
|
@ -0,0 +1,800 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
||||
#include "SdioCard.h"
|
||||
//==============================================================================
|
||||
#define SDHC_PROCTL_DTW_4BIT 0x01
|
||||
const uint32_t FIFO_WML = 16;
|
||||
const uint32_t CMD8_RETRIES = 10;
|
||||
const uint32_t BUSY_TIMEOUT_MICROS = 500000;
|
||||
//==============================================================================
|
||||
const uint32_t SDHC_IRQSTATEN_MASK =
|
||||
SDHC_IRQSTATEN_DMAESEN | SDHC_IRQSTATEN_AC12ESEN |
|
||||
SDHC_IRQSTATEN_DEBESEN | SDHC_IRQSTATEN_DCESEN |
|
||||
SDHC_IRQSTATEN_DTOESEN | SDHC_IRQSTATEN_CIESEN |
|
||||
SDHC_IRQSTATEN_CEBESEN | SDHC_IRQSTATEN_CCESEN |
|
||||
SDHC_IRQSTATEN_CTOESEN | SDHC_IRQSTATEN_DINTSEN |
|
||||
SDHC_IRQSTATEN_TCSEN | SDHC_IRQSTATEN_CCSEN;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_CMD_ERROR =
|
||||
SDHC_IRQSTAT_CIE | SDHC_IRQSTAT_CEBE |
|
||||
SDHC_IRQSTAT_CCE | SDHC_IRQSTAT_CTOE;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_DATA_ERROR =
|
||||
SDHC_IRQSTAT_AC12E | SDHC_IRQSTAT_DEBE |
|
||||
SDHC_IRQSTAT_DCE | SDHC_IRQSTAT_DTOE;
|
||||
|
||||
const uint32_t SDHC_IRQSTAT_ERROR =
|
||||
SDHC_IRQSTAT_DMAE | SDHC_IRQSTAT_CMD_ERROR |
|
||||
SDHC_IRQSTAT_DATA_ERROR;
|
||||
|
||||
const uint32_t SDHC_IRQSIGEN_MASK =
|
||||
SDHC_IRQSIGEN_DMAEIEN | SDHC_IRQSIGEN_AC12EIEN |
|
||||
SDHC_IRQSIGEN_DEBEIEN | SDHC_IRQSIGEN_DCEIEN |
|
||||
SDHC_IRQSIGEN_DTOEIEN | SDHC_IRQSIGEN_CIEIEN |
|
||||
SDHC_IRQSIGEN_CEBEIEN | SDHC_IRQSIGEN_CCEIEN |
|
||||
SDHC_IRQSIGEN_CTOEIEN | SDHC_IRQSIGEN_TCIEN;
|
||||
//=============================================================================
|
||||
const uint32_t CMD_RESP_NONE = SDHC_XFERTYP_RSPTYP(0);
|
||||
|
||||
const uint32_t CMD_RESP_R1 = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
|
||||
SDHC_XFERTYP_RSPTYP(2);
|
||||
|
||||
const uint32_t CMD_RESP_R1b = SDHC_XFERTYP_CICEN | SDHC_XFERTYP_CCCEN |
|
||||
SDHC_XFERTYP_RSPTYP(3);
|
||||
|
||||
const uint32_t CMD_RESP_R2 = SDHC_XFERTYP_CCCEN | SDHC_XFERTYP_RSPTYP(1);
|
||||
|
||||
const uint32_t CMD_RESP_R3 = SDHC_XFERTYP_RSPTYP(2);
|
||||
|
||||
const uint32_t CMD_RESP_R6 = CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD_RESP_R7 = CMD_RESP_R1;
|
||||
|
||||
const uint32_t DATA_READ = SDHC_XFERTYP_DTDSEL | SDHC_XFERTYP_DPSEL;
|
||||
|
||||
const uint32_t DATA_READ_DMA = DATA_READ | SDHC_XFERTYP_DMAEN;
|
||||
|
||||
const uint32_t DATA_READ_MULTI_DMA = DATA_READ_DMA | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
|
||||
|
||||
const uint32_t DATA_READ_MULTI_PGM = DATA_READ | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_BCEN | SDHC_XFERTYP_AC12EN;
|
||||
|
||||
const uint32_t DATA_WRITE_DMA = SDHC_XFERTYP_DPSEL | SDHC_XFERTYP_DMAEN;
|
||||
|
||||
const uint32_t DATA_WRITE_MULTI_DMA = DATA_WRITE_DMA | SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_AC12EN | SDHC_XFERTYP_BCEN;
|
||||
|
||||
const uint32_t DATA_WRITE_MULTI_PGM = SDHC_XFERTYP_DPSEL |
|
||||
SDHC_XFERTYP_MSBSEL |
|
||||
SDHC_XFERTYP_BCEN | SDHC_XFERTYP_AC12EN;
|
||||
|
||||
const uint32_t ACMD6_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD6) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t ACMD41_XFERTYP = SDHC_XFERTYP_CMDINX(ACMD41) | CMD_RESP_R3;
|
||||
|
||||
const uint32_t CMD0_XFERTYP = SDHC_XFERTYP_CMDINX(CMD0) | CMD_RESP_NONE;
|
||||
|
||||
const uint32_t CMD2_XFERTYP = SDHC_XFERTYP_CMDINX(CMD2) | CMD_RESP_R2;
|
||||
|
||||
const uint32_t CMD3_XFERTYP = SDHC_XFERTYP_CMDINX(CMD3) | CMD_RESP_R6;
|
||||
|
||||
const uint32_t CMD6_XFERTYP = SDHC_XFERTYP_CMDINX(CMD6) | CMD_RESP_R1 |
|
||||
DATA_READ_DMA;
|
||||
|
||||
const uint32_t CMD7_XFERTYP = SDHC_XFERTYP_CMDINX(CMD7) | CMD_RESP_R1b;
|
||||
|
||||
const uint32_t CMD8_XFERTYP = SDHC_XFERTYP_CMDINX(CMD8) | CMD_RESP_R7;
|
||||
|
||||
const uint32_t CMD9_XFERTYP = SDHC_XFERTYP_CMDINX(CMD9) | CMD_RESP_R2;
|
||||
|
||||
const uint32_t CMD10_XFERTYP = SDHC_XFERTYP_CMDINX(CMD10) | CMD_RESP_R2;
|
||||
|
||||
const uint32_t CMD12_XFERTYP = SDHC_XFERTYP_CMDINX(CMD12) | CMD_RESP_R1b |
|
||||
SDHC_XFERTYP_CMDTYP(3);
|
||||
|
||||
const uint32_t CMD13_XFERTYP = SDHC_XFERTYP_CMDINX(CMD13) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD17_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD17) | CMD_RESP_R1 |
|
||||
DATA_READ_DMA;
|
||||
|
||||
const uint32_t CMD18_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
|
||||
DATA_READ_MULTI_DMA;
|
||||
|
||||
const uint32_t CMD18_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD18) | CMD_RESP_R1 |
|
||||
DATA_READ_MULTI_PGM;
|
||||
|
||||
const uint32_t CMD24_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD24) | CMD_RESP_R1 |
|
||||
DATA_WRITE_DMA;
|
||||
|
||||
const uint32_t CMD25_DMA_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
|
||||
DATA_WRITE_MULTI_DMA;
|
||||
|
||||
const uint32_t CMD25_PGM_XFERTYP = SDHC_XFERTYP_CMDINX(CMD25) | CMD_RESP_R1 |
|
||||
DATA_WRITE_MULTI_PGM;
|
||||
|
||||
const uint32_t CMD32_XFERTYP = SDHC_XFERTYP_CMDINX(CMD32) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD33_XFERTYP = SDHC_XFERTYP_CMDINX(CMD33) | CMD_RESP_R1;
|
||||
|
||||
const uint32_t CMD38_XFERTYP = SDHC_XFERTYP_CMDINX(CMD38) | CMD_RESP_R1b;
|
||||
|
||||
const uint32_t CMD55_XFERTYP = SDHC_XFERTYP_CMDINX(CMD55) | CMD_RESP_R1;
|
||||
|
||||
//=============================================================================
|
||||
static bool cardCommand(uint32_t xfertyp, uint32_t arg);
|
||||
static void enableGPIO(bool enable);
|
||||
static void enableDmaIrs();
|
||||
static void initSDHC();
|
||||
static bool isBusyCMD13();
|
||||
static bool isBusyCommandComplete();
|
||||
static bool isBusyCommandInhibit();
|
||||
static bool readReg16(uint32_t xfertyp, void* data);
|
||||
static void setSdclk(uint32_t kHzMax);
|
||||
static bool yieldTimeout(bool (*fcn)());
|
||||
static bool waitDmaStatus();
|
||||
static bool waitTimeout(bool (*fcn)());
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool (*m_busyFcn)() = 0;
|
||||
static bool m_initDone = false;
|
||||
static bool m_version2;
|
||||
static bool m_highCapacity;
|
||||
static uint8_t m_errorCode = SD_CARD_ERROR_INIT_NOT_CALLED;
|
||||
static uint32_t m_errorLine = 0;
|
||||
static uint32_t m_rca;
|
||||
static volatile bool m_dmaBusy = false;
|
||||
static volatile uint32_t m_irqstat;
|
||||
static uint32_t m_sdClkKhz = 0;
|
||||
static uint32_t m_ocr;
|
||||
static cid_t m_cid;
|
||||
static csd_t m_csd;
|
||||
//=============================================================================
|
||||
#define USE_DEBUG_MODE 0
|
||||
#if USE_DEBUG_MODE
|
||||
#define DBG_IRQSTAT() if (SDHC_IRQSTAT) {Serial.print(__LINE__);\
|
||||
Serial.print(" IRQSTAT "); Serial.println(SDHC_IRQSTAT, HEX);}
|
||||
|
||||
static void printRegs(uint32_t line) {
|
||||
Serial.print(line);
|
||||
Serial.print(" PRSSTAT ");
|
||||
Serial.print(SDHC_PRSSTAT, HEX);
|
||||
Serial.print(" PROCTL ");
|
||||
Serial.print(SDHC_PROCTL, HEX);
|
||||
Serial.print(" IRQSTAT ");
|
||||
Serial.print(SDHC_IRQSTAT, HEX);
|
||||
Serial.print(" m_irqstat ");
|
||||
Serial.println(m_irqstat, HEX);
|
||||
}
|
||||
#else // USE_DEBUG_MODE
|
||||
#define DBG_IRQSTAT()
|
||||
#endif // USE_DEBUG_MODE
|
||||
//=============================================================================
|
||||
// Error function and macro.
|
||||
#define sdError(code) setSdErrorCode(code, __LINE__)
|
||||
inline bool setSdErrorCode(uint8_t code, uint32_t line) {
|
||||
m_errorCode = code;
|
||||
m_errorLine = line;
|
||||
return false; // setSdErrorCode
|
||||
}
|
||||
//=============================================================================
|
||||
// ISR
|
||||
void sdhc_isr() {
|
||||
SDHC_IRQSIGEN = 0;
|
||||
m_irqstat = SDHC_IRQSTAT;
|
||||
SDHC_IRQSTAT = m_irqstat;
|
||||
m_dmaBusy = false;
|
||||
}
|
||||
//=============================================================================
|
||||
// Static functions.
|
||||
static bool cardAcmd(uint32_t rca, uint32_t xfertyp, uint32_t arg) {
|
||||
return cardCommand(CMD55_XFERTYP, rca) && cardCommand (xfertyp, arg);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool cardCommand(uint32_t xfertyp, uint32_t arg) {
|
||||
DBG_IRQSTAT();
|
||||
if (waitTimeout(isBusyCommandInhibit)) {
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
SDHC_CMDARG = arg;
|
||||
SDHC_XFERTYP = xfertyp;
|
||||
if (waitTimeout(isBusyCommandComplete)) {
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
m_irqstat = SDHC_IRQSTAT;
|
||||
SDHC_IRQSTAT = m_irqstat;
|
||||
|
||||
return (m_irqstat & SDHC_IRQSTAT_CC) &&
|
||||
!(m_irqstat & SDHC_IRQSTAT_CMD_ERROR);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool cardCMD6(uint32_t arg, uint8_t* status) {
|
||||
// CMD6 returns 64 bytes.
|
||||
if (waitTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)status;
|
||||
SDHC_CMDARG = arg;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(1) | SDHC_BLKATTR_BLKSIZE(64);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
SDHC_XFERTYP = CMD6_XFERTYP;
|
||||
|
||||
if (!waitDmaStatus()) {
|
||||
return sdError(SD_CARD_ERROR_CMD6);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static void enableGPIO(bool enable) {
|
||||
const uint32_t PORT_CLK = PORT_PCR_MUX(4) | PORT_PCR_DSE;
|
||||
const uint32_t PORT_CMD_DATA = PORT_CLK | PORT_PCR_PS | PORT_PCR_PE;
|
||||
|
||||
PORTE_PCR0 = enable ? PORT_CMD_DATA : 0; // SDHC_D1
|
||||
PORTE_PCR1 = enable ? PORT_CMD_DATA : 0; // SDHC_D0
|
||||
PORTE_PCR2 = enable ? PORT_CLK : 0; // SDHC_CLK
|
||||
PORTE_PCR3 = enable ? PORT_CMD_DATA : 0; // SDHC_CMD
|
||||
PORTE_PCR4 = enable ? PORT_CMD_DATA : 0; // SDHC_D3
|
||||
PORTE_PCR5 = enable ? PORT_CMD_DATA : 0; // SDHC_D2
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static void enableDmaIrs() {
|
||||
m_dmaBusy = true;
|
||||
m_irqstat = 0;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static void initSDHC() {
|
||||
#ifdef HAS_KINETIS_MPU
|
||||
// Allow SDHC Bus Master access.
|
||||
MPU_RGDAAC0 |= 0x0C000000;
|
||||
#endif
|
||||
// Enable SDHC clock.
|
||||
SIM_SCGC3 |= SIM_SCGC3_SDHC;
|
||||
|
||||
// Disable GPIO clock.
|
||||
enableGPIO(false);
|
||||
|
||||
// Reset SDHC. Use default Water Mark Level of 16.
|
||||
SDHC_SYSCTL = SDHC_SYSCTL_RSTA;
|
||||
while (SDHC_SYSCTL & SDHC_SYSCTL_RSTA) {
|
||||
}
|
||||
// Set initial SCK rate.
|
||||
setSdclk(400);
|
||||
|
||||
enableGPIO(true);
|
||||
|
||||
// Enable desired IRQSTAT bits.
|
||||
SDHC_IRQSTATEN = SDHC_IRQSTATEN_MASK;
|
||||
|
||||
NVIC_SET_PRIORITY(IRQ_SDHC, 6*16);
|
||||
NVIC_ENABLE_IRQ(IRQ_SDHC);
|
||||
|
||||
// Send 80 clocks to card.
|
||||
SDHC_SYSCTL |= SDHC_SYSCTL_INITA;
|
||||
while (SDHC_SYSCTL & SDHC_SYSCTL_INITA) {
|
||||
}
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyCMD13() {
|
||||
if (!cardCommand(CMD13_XFERTYP, m_rca)) {
|
||||
// Caller will timeout.
|
||||
return true;
|
||||
}
|
||||
return !(SDHC_CMDRSP0 & CARD_STATUS_READY_FOR_DATA);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyCommandComplete() {
|
||||
return !(SDHC_IRQSTAT &(SDHC_IRQSTAT_CC | SDHC_IRQSTAT_CMD_ERROR));
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyCommandInhibit() {
|
||||
return SDHC_PRSSTAT & SDHC_PRSSTAT_CIHB;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyDMA() {
|
||||
return m_dmaBusy;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyFifoRead() {
|
||||
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BREN);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyFifoWrite() {
|
||||
return !(SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool isBusyTransferComplete() {
|
||||
return !(SDHC_IRQSTAT & (SDHC_IRQSTAT_TC | SDHC_IRQSTAT_ERROR));
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool rdWrBlocks(uint32_t xfertyp,
|
||||
uint32_t lba, uint8_t* buf, size_t n) {
|
||||
if ((3 & (uint32_t)buf) || n == 0) {
|
||||
return sdError(SD_CARD_ERROR_DMA);
|
||||
}
|
||||
if (yieldTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
enableDmaIrs();
|
||||
SDHC_DSADDR = (uint32_t)buf;
|
||||
SDHC_CMDARG = m_highCapacity ? lba : 512*lba;
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(n) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
SDHC_IRQSIGEN = SDHC_IRQSIGEN_MASK;
|
||||
SDHC_XFERTYP = xfertyp;
|
||||
|
||||
return waitDmaStatus();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Read 16 byte CID or CSD register.
|
||||
static bool readReg16(uint32_t xfertyp, void* data) {
|
||||
uint8_t* d = reinterpret_cast<uint8_t*>(data);
|
||||
if (!cardCommand(xfertyp, m_rca)) {
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
uint32_t sr[] = {SDHC_CMDRSP0, SDHC_CMDRSP1, SDHC_CMDRSP2, SDHC_CMDRSP3};
|
||||
for (int i = 0; i < 15; i++) {
|
||||
d[14 - i] = sr[i/4] >> 8*(i%4);
|
||||
}
|
||||
d[15] = 0;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static void setSdclk(uint32_t kHzMax) {
|
||||
const uint32_t DVS_LIMIT = 0X10;
|
||||
const uint32_t SDCLKFS_LIMIT = 0X100;
|
||||
uint32_t dvs = 1;
|
||||
uint32_t sdclkfs = 1;
|
||||
uint32_t maxSdclk = 1000*kHzMax;
|
||||
|
||||
while ((F_CPU/(sdclkfs*DVS_LIMIT) > maxSdclk) && (sdclkfs < SDCLKFS_LIMIT)) {
|
||||
sdclkfs <<= 1;
|
||||
}
|
||||
while ((F_CPU/(sdclkfs*dvs) > maxSdclk) && (dvs < DVS_LIMIT)) {
|
||||
dvs++;
|
||||
}
|
||||
m_sdClkKhz = F_CPU/(1000*sdclkfs*dvs);
|
||||
sdclkfs >>= 1;
|
||||
dvs--;
|
||||
|
||||
// Disable SDHC clock.
|
||||
SDHC_SYSCTL &= ~SDHC_SYSCTL_SDCLKEN;
|
||||
|
||||
// Change dividers.
|
||||
uint32_t sysctl = SDHC_SYSCTL & ~(SDHC_SYSCTL_DTOCV_MASK
|
||||
| SDHC_SYSCTL_DVS_MASK | SDHC_SYSCTL_SDCLKFS_MASK);
|
||||
|
||||
SDHC_SYSCTL = sysctl | SDHC_SYSCTL_DTOCV(0x0E) | SDHC_SYSCTL_DVS(dvs)
|
||||
| SDHC_SYSCTL_SDCLKFS(sdclkfs);
|
||||
|
||||
// Wait until the SDHC clock is stable.
|
||||
while (!(SDHC_PRSSTAT & SDHC_PRSSTAT_SDSTB)) {
|
||||
}
|
||||
// Enable the SDHC clock.
|
||||
SDHC_SYSCTL |= SDHC_SYSCTL_SDCLKEN;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool transferStop() {
|
||||
DBG_IRQSTAT();
|
||||
|
||||
if (!cardCommand(CMD12_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD12);
|
||||
}
|
||||
if (yieldTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
// Save registers before reset DAT lines.
|
||||
uint32_t irqsststen = SDHC_IRQSTATEN;
|
||||
uint32_t proctl = SDHC_PROCTL & ~SDHC_PROCTL_SABGREQ;
|
||||
|
||||
// Do reset to clear CDIHB. Should be a better way!
|
||||
SDHC_SYSCTL |= SDHC_SYSCTL_RSTD;
|
||||
|
||||
// Restore registers.
|
||||
SDHC_IRQSTATEN = irqsststen;
|
||||
SDHC_PROCTL = proctl;
|
||||
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Return true if timeout occurs.
|
||||
static bool yieldTimeout(bool (*fcn)()) {
|
||||
m_busyFcn = fcn;
|
||||
uint32_t m = micros();
|
||||
while (fcn()) {
|
||||
if ((micros() - m) > BUSY_TIMEOUT_MICROS) {
|
||||
m_busyFcn = 0;
|
||||
return true;
|
||||
}
|
||||
yield();
|
||||
}
|
||||
m_busyFcn = 0;
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool waitDmaStatus() {
|
||||
if (yieldTimeout(isBusyDMA)) {
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// Return true if timeout occurs.
|
||||
static bool waitTimeout(bool (*fcn)()) {
|
||||
uint32_t m = micros();
|
||||
while (fcn()) {
|
||||
if ((micros() - m) > BUSY_TIMEOUT_MICROS) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // Caller will set errorCode.
|
||||
}
|
||||
//=============================================================================
|
||||
bool SdioCard::begin() {
|
||||
uint32_t kHzSdClk;
|
||||
uint32_t arg;
|
||||
m_initDone = false;
|
||||
m_errorCode = SD_CARD_ERROR_NONE;
|
||||
m_highCapacity = false;
|
||||
m_version2 = false;
|
||||
|
||||
// initialize controller.
|
||||
initSDHC();
|
||||
|
||||
if (!cardCommand(CMD0_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD0);
|
||||
}
|
||||
// Try several times for case of reset delay.
|
||||
for (uint32_t i = 0; i < CMD8_RETRIES; i++) {
|
||||
if (cardCommand(CMD8_XFERTYP, 0X1AA)) {
|
||||
if (SDHC_CMDRSP0 != 0X1AA) {
|
||||
return sdError(SD_CARD_ERROR_CMD8);
|
||||
}
|
||||
m_version2 = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
arg = m_version2 ? 0X40300000 : 0x00300000;
|
||||
uint32_t m = micros();
|
||||
do {
|
||||
if (!cardAcmd(0, ACMD41_XFERTYP, arg) ||
|
||||
((micros() - m) > BUSY_TIMEOUT_MICROS)) {
|
||||
return sdError(SD_CARD_ERROR_ACMD41);
|
||||
}
|
||||
} while ((SDHC_CMDRSP0 & 0x80000000) == 0);
|
||||
|
||||
m_ocr = SDHC_CMDRSP0;
|
||||
if (SDHC_CMDRSP0 & 0x40000000) {
|
||||
// Is high capacity.
|
||||
m_highCapacity = true;
|
||||
}
|
||||
if (!cardCommand(CMD2_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD2);
|
||||
}
|
||||
if (!cardCommand(CMD3_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD3);
|
||||
}
|
||||
m_rca = SDHC_CMDRSP0 & 0xFFFF0000;
|
||||
|
||||
if (!readReg16(CMD9_XFERTYP, &m_csd)) {
|
||||
return sdError(SD_CARD_ERROR_CMD9);
|
||||
}
|
||||
if (!readReg16(CMD10_XFERTYP, &m_cid)) {
|
||||
return sdError(SD_CARD_ERROR_CMD10);
|
||||
}
|
||||
if (!cardCommand(CMD7_XFERTYP, m_rca)) {
|
||||
return sdError(SD_CARD_ERROR_CMD7);
|
||||
}
|
||||
// Set card to bus width four.
|
||||
if (!cardAcmd(m_rca, ACMD6_XFERTYP, 2)) {
|
||||
return sdError(SD_CARD_ERROR_ACMD6);
|
||||
}
|
||||
// Set SDHC to bus width four.
|
||||
SDHC_PROCTL &= ~SDHC_PROCTL_DTW_MASK;
|
||||
SDHC_PROCTL |= SDHC_PROCTL_DTW(SDHC_PROCTL_DTW_4BIT);
|
||||
|
||||
SDHC_WML = SDHC_WML_RDWML(FIFO_WML) | SDHC_WML_WRWML(FIFO_WML);
|
||||
|
||||
// Determine if High Speed mode is supported and set frequency.
|
||||
uint8_t status[64];
|
||||
if (cardCMD6(0X00FFFFFF, status) && (2 & status[13]) &&
|
||||
cardCMD6(0X80FFFFF1, status) && (status[16] & 0XF) == 1) {
|
||||
kHzSdClk = 50000;
|
||||
} else {
|
||||
kHzSdClk = 25000;
|
||||
}
|
||||
// disable GPIO
|
||||
enableGPIO(false);
|
||||
|
||||
// Set the SDHC SCK frequency.
|
||||
setSdclk(kHzSdClk);
|
||||
|
||||
// enable GPIO
|
||||
enableGPIO(true);
|
||||
m_initDone = true;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t SdioCard::cardCapacity() {
|
||||
return sdCardCapacity(&m_csd);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::erase(uint32_t firstBlock, uint32_t lastBlock) {
|
||||
// check for single block erase
|
||||
if (!m_csd.v1.erase_blk_en) {
|
||||
// erase size mask
|
||||
uint8_t m = (m_csd.v1.sector_size_high << 1) | m_csd.v1.sector_size_low;
|
||||
if ((firstBlock & m) != 0 || ((lastBlock + 1) & m) != 0) {
|
||||
// error card can't erase specified area
|
||||
return sdError(SD_CARD_ERROR_ERASE_SINGLE_BLOCK);
|
||||
}
|
||||
}
|
||||
if (!m_highCapacity) {
|
||||
firstBlock <<= 9;
|
||||
lastBlock <<= 9;
|
||||
}
|
||||
if (!cardCommand(CMD32_XFERTYP, firstBlock)) {
|
||||
return sdError(SD_CARD_ERROR_CMD32);
|
||||
}
|
||||
if (!cardCommand(CMD33_XFERTYP, lastBlock)) {
|
||||
return sdError(SD_CARD_ERROR_CMD33);
|
||||
}
|
||||
if (!cardCommand(CMD38_XFERTYP, 0)) {
|
||||
return sdError(SD_CARD_ERROR_CMD38);
|
||||
}
|
||||
if (waitTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_ERASE_TIMEOUT);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t SdioCard::errorCode() {
|
||||
return m_errorCode;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorData() {
|
||||
return m_irqstat;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t SdioCard::errorLine() {
|
||||
return m_errorLine;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::isBusy() {
|
||||
return m_busyFcn ? m_busyFcn() : m_initDone && isBusyCMD13();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint32_t SdioCard::kHzSdClk() {
|
||||
return m_sdClkKhz;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readBlock(uint32_t lba, uint8_t* buf) {
|
||||
uint8_t aligned[512];
|
||||
|
||||
uint8_t* ptr = (uint32_t)buf & 3 ? aligned : buf;
|
||||
|
||||
if (!rdWrBlocks(CMD17_DMA_XFERTYP, lba, ptr, 1)) {
|
||||
return sdError(SD_CARD_ERROR_CMD18);
|
||||
}
|
||||
if (ptr != buf) {
|
||||
memcpy(buf, aligned, 512);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readBlocks(uint32_t lba, uint8_t* buf, size_t n) {
|
||||
if ((uint32_t)buf & 3) {
|
||||
for (size_t i = 0; i < n; i++, lba++, buf += 512) {
|
||||
if (!readBlock(lba, buf)) {
|
||||
return false; // readBlock will set errorCode.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!rdWrBlocks(CMD18_DMA_XFERTYP, lba, buf, n)) {
|
||||
return sdError(SD_CARD_ERROR_CMD18);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readCID(void* cid) {
|
||||
memcpy(cid, &m_cid, 16);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readCSD(void* csd) {
|
||||
memcpy(csd, &m_csd, 16);
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readData(uint8_t *dst) {
|
||||
DBG_IRQSTAT();
|
||||
uint32_t *p32 = reinterpret_cast<uint32_t*>(dst);
|
||||
|
||||
if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_RTA)) {
|
||||
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
|
||||
if ((SDHC_BLKATTR & 0XFFFF0000) == 0X10000) {
|
||||
// Don't stop at block gap if last block. Allows auto CMD12.
|
||||
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
|
||||
} else {
|
||||
noInterrupts();
|
||||
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
|
||||
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
|
||||
interrupts();
|
||||
}
|
||||
}
|
||||
if (waitTimeout(isBusyFifoRead)) {
|
||||
return sdError(SD_CARD_ERROR_READ_FIFO);
|
||||
}
|
||||
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
|
||||
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BREN)) {
|
||||
}
|
||||
for (uint32_t i = 0; i < FIFO_WML; i++) {
|
||||
p32[i] = SDHC_DATPORT;
|
||||
}
|
||||
p32 += FIFO_WML;
|
||||
}
|
||||
if (waitTimeout(isBusyTransferComplete)) {
|
||||
return sdError(SD_CARD_ERROR_READ_TIMEOUT);
|
||||
}
|
||||
m_irqstat = SDHC_IRQSTAT;
|
||||
SDHC_IRQSTAT = m_irqstat;
|
||||
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readOCR(uint32_t* ocr) {
|
||||
*ocr = m_ocr;
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readStart(uint32_t lba) {
|
||||
// K66/K65 Errata - SDHC: Does not support Infinite Block Transfer Mode.
|
||||
return sdError(SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// SDHC will do Auto CMD12 after count blocks.
|
||||
bool SdioCard::readStart(uint32_t lba, uint32_t count) {
|
||||
DBG_IRQSTAT();
|
||||
if (count > 0XFFFF) {
|
||||
return sdError(SD_CARD_ERROR_READ_START);
|
||||
}
|
||||
if (yieldTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
if (count > 1) {
|
||||
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
|
||||
}
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(count) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
if (!cardCommand(CMD18_PGM_XFERTYP, m_highCapacity ? lba : 512*lba)) {
|
||||
return sdError(SD_CARD_ERROR_CMD18);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::readStop() {
|
||||
return transferStop();
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::syncBlocks() {
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
uint8_t SdioCard::type() {
|
||||
return m_version2 ? m_highCapacity ?
|
||||
SD_CARD_TYPE_SDHC : SD_CARD_TYPE_SD2 : SD_CARD_TYPE_SD1;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::writeBlock(uint32_t lba, const uint8_t* buf) {
|
||||
uint8_t *ptr;
|
||||
uint8_t aligned[512];
|
||||
if (3 & (uint32_t)buf) {
|
||||
ptr = aligned;
|
||||
memcpy(aligned, buf, 512);
|
||||
} else {
|
||||
ptr = const_cast<uint8_t*>(buf);
|
||||
}
|
||||
if (!rdWrBlocks(CMD24_DMA_XFERTYP, lba, ptr, 1)) {
|
||||
return sdError(SD_CARD_ERROR_CMD24);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::writeBlocks(uint32_t lba, const uint8_t* buf, size_t n) {
|
||||
uint8_t* ptr = const_cast<uint8_t*>(buf);
|
||||
if (3 & (uint32_t)ptr) {
|
||||
for (size_t i = 0; i < n; i++, lba++, ptr += 512) {
|
||||
if (!writeBlock(lba, ptr)) {
|
||||
return false; // writeBlock will set errorCode.
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (!rdWrBlocks(CMD25_DMA_XFERTYP, lba, ptr, n)) {
|
||||
return sdError(SD_CARD_ERROR_CMD25);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::writeData(const uint8_t* src) {
|
||||
DBG_IRQSTAT();
|
||||
const uint32_t* p32 = reinterpret_cast<const uint32_t*>(src);
|
||||
|
||||
if (!(SDHC_PRSSTAT & SDHC_PRSSTAT_WTA)) {
|
||||
SDHC_PROCTL &= ~SDHC_PROCTL_SABGREQ;
|
||||
// Don't stop at block gap if last block. Allows auto CMD12.
|
||||
if ((SDHC_BLKATTR & 0XFFFF0000) == 0X10000) {
|
||||
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
|
||||
} else {
|
||||
SDHC_PROCTL |= SDHC_PROCTL_CREQ;
|
||||
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
|
||||
}
|
||||
}
|
||||
if (waitTimeout(isBusyFifoWrite)) {
|
||||
return sdError(SD_CARD_ERROR_WRITE_FIFO);
|
||||
}
|
||||
for (uint32_t iw = 0 ; iw < 512/(4*FIFO_WML); iw++) {
|
||||
while (0 == (SDHC_PRSSTAT & SDHC_PRSSTAT_BWEN)) {
|
||||
}
|
||||
for (uint32_t i = 0; i < FIFO_WML; i++) {
|
||||
SDHC_DATPORT = p32[i];
|
||||
}
|
||||
p32 += FIFO_WML;
|
||||
}
|
||||
if (waitTimeout(isBusyTransferComplete)) {
|
||||
return sdError(SD_CARD_ERROR_WRITE_TIMEOUT);
|
||||
}
|
||||
m_irqstat = SDHC_IRQSTAT;
|
||||
SDHC_IRQSTAT = m_irqstat;
|
||||
return (m_irqstat & SDHC_IRQSTAT_TC) && !(m_irqstat & SDHC_IRQSTAT_ERROR);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::writeStart(uint32_t lba) {
|
||||
// K66/K65 Errata - SDHC: Does not support Infinite Block Transfer Mode.
|
||||
return sdError(SD_CARD_ERROR_FUNCTION_NOT_SUPPORTED);
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
// SDHC will do Auto CMD12 after count blocks.
|
||||
bool SdioCard::writeStart(uint32_t lba, uint32_t count) {
|
||||
if (count > 0XFFFF) {
|
||||
return sdError(SD_CARD_ERROR_WRITE_START);
|
||||
}
|
||||
DBG_IRQSTAT();
|
||||
if (yieldTimeout(isBusyCMD13)) {
|
||||
return sdError(SD_CARD_ERROR_CMD13);
|
||||
}
|
||||
if (count > 1) {
|
||||
SDHC_PROCTL |= SDHC_PROCTL_SABGREQ;
|
||||
}
|
||||
SDHC_BLKATTR = SDHC_BLKATTR_BLKCNT(count) | SDHC_BLKATTR_BLKSIZE(512);
|
||||
|
||||
if (!cardCommand(CMD25_PGM_XFERTYP, m_highCapacity ? lba : 512*lba)) {
|
||||
return sdError(SD_CARD_ERROR_CMD25);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
//-----------------------------------------------------------------------------
|
||||
bool SdioCard::writeStop() {
|
||||
return transferStop();
|
||||
}
|
||||
#endif // defined(__MK64FX512__) || defined(__MK66FX1M0__)
|
512
hardware/sd_card_formatter/src/SdFat/SdFat.h
Normal file
512
hardware/sd_card_formatter/src/SdFat/SdFat.h
Normal file
|
@ -0,0 +1,512 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdFat_h
|
||||
#define SdFat_h
|
||||
/**
|
||||
* \file
|
||||
* \brief SdFat class
|
||||
*/
|
||||
#include "SysCall.h"
|
||||
#include "BlockDriver.h"
|
||||
#include "FatLib/FatLib.h"
|
||||
#include "SdCard/SdioCard.h"
|
||||
#if INCLUDE_SDIOS
|
||||
#include "sdios.h"
|
||||
#endif // INCLUDE_SDIOS
|
||||
//------------------------------------------------------------------------------
|
||||
/** SdFat version 1.1.2 */
|
||||
#define SD_FAT_VERSION 10102
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdBaseFile
|
||||
* \brief Class for backward compatibility.
|
||||
*/
|
||||
class SdBaseFile : public FatFile {
|
||||
public:
|
||||
SdBaseFile() {}
|
||||
/** Create a file object and open it in the current working directory.
|
||||
*
|
||||
* \param[in] path A path for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a
|
||||
* bitwise-inclusive OR of open flags. see
|
||||
* FatFile::open(FatFile*, const char*, oflag_t).
|
||||
*/
|
||||
SdBaseFile(const char* path, oflag_t oflag) : FatFile(path, oflag) {}
|
||||
};
|
||||
//-----------------------------------------------------------------------------
|
||||
#if ENABLE_ARDUINO_FEATURES
|
||||
/**
|
||||
* \class SdFile
|
||||
* \brief Class for backward compatibility.
|
||||
*/
|
||||
class SdFile : public PrintFile {
|
||||
public:
|
||||
SdFile() {}
|
||||
/** Create a file object and open it in the current working directory.
|
||||
*
|
||||
* \param[in] path A path for a file to be opened.
|
||||
*
|
||||
* \param[in] oflag Values for \a oflag are constructed by a
|
||||
* bitwise-inclusive OR of open flags. see
|
||||
* FatFile::open(FatFile*, const char*, oflag_t).
|
||||
*/
|
||||
SdFile(const char* path, oflag_t oflag) : PrintFile(path, oflag) {}
|
||||
};
|
||||
#endif // #if ENABLE_ARDUINO_FEATURES
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdFileSystem
|
||||
* \brief Virtual base class for %SdFat library.
|
||||
*/
|
||||
template<class SdDriverClass>
|
||||
class SdFileSystem : public FatFileSystem {
|
||||
public:
|
||||
/** Initialize file system.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin() {
|
||||
return FatFileSystem::begin(&m_card);
|
||||
}
|
||||
/** \return Pointer to SD card object */
|
||||
SdDriverClass *card() {
|
||||
m_card.syncBlocks();
|
||||
return &m_card;
|
||||
}
|
||||
/** %Print any SD error code to Serial and halt. */
|
||||
void errorHalt() {
|
||||
errorHalt(&Serial);
|
||||
}
|
||||
/** %Print any SD error code and halt.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
*/
|
||||
void errorHalt(Print* pr) {
|
||||
errorPrint(pr);
|
||||
SysCall::halt();
|
||||
}
|
||||
/** %Print msg, any SD error code and halt.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorHalt(char const* msg) {
|
||||
errorHalt(&Serial, msg);
|
||||
}
|
||||
/** %Print msg, any SD error code, and halt.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorHalt(Print* pr, char const* msg) {
|
||||
errorPrint(pr, msg);
|
||||
SysCall::halt();
|
||||
}
|
||||
/** %Print any SD error code to Serial */
|
||||
void errorPrint() {
|
||||
errorPrint(&Serial);
|
||||
}
|
||||
/** %Print any SD error code.
|
||||
* \param[in] pr Print device.
|
||||
*/
|
||||
void errorPrint(Print* pr) {
|
||||
if (!cardErrorCode()) {
|
||||
return;
|
||||
}
|
||||
pr->print(F("SD errorCode: 0X"));
|
||||
pr->print(cardErrorCode(), HEX);
|
||||
pr->print(F(",0X"));
|
||||
pr->println(cardErrorData(), HEX);
|
||||
}
|
||||
/** %Print msg, any SD error code.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorPrint(const char* msg) {
|
||||
errorPrint(&Serial, msg);
|
||||
}
|
||||
/** %Print msg, any SD error code.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorPrint(Print* pr, char const* msg) {
|
||||
pr->print(F("error: "));
|
||||
pr->println(msg);
|
||||
errorPrint(pr);
|
||||
}
|
||||
/** %Print any SD error code and halt. */
|
||||
void initErrorHalt() {
|
||||
initErrorHalt(&Serial);
|
||||
}
|
||||
/** %Print error details and halt after begin fails.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
*/
|
||||
void initErrorHalt(Print* pr) {
|
||||
initErrorPrint(pr);
|
||||
SysCall::halt();
|
||||
}
|
||||
/**Print message, error details, and halt after begin() fails.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorHalt(char const *msg) {
|
||||
initErrorHalt(&Serial, msg);
|
||||
}
|
||||
/**Print message, error details, and halt after begin() fails.
|
||||
* \param[in] pr Print device.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorHalt(Print* pr, char const *msg) {
|
||||
pr->println(msg);
|
||||
initErrorHalt(pr);
|
||||
}
|
||||
|
||||
/** Print error details after begin() fails. */
|
||||
void initErrorPrint() {
|
||||
initErrorPrint(&Serial);
|
||||
}
|
||||
/** Print error details after begin() fails.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
*/
|
||||
void initErrorPrint(Print* pr) {
|
||||
if (cardErrorCode()) {
|
||||
pr->println(F("Can't access SD card. Do not reformat."));
|
||||
if (cardErrorCode() == SD_CARD_ERROR_CMD0) {
|
||||
pr->println(F("No card, wrong chip select pin, or SPI problem?"));
|
||||
}
|
||||
errorPrint(pr);
|
||||
} else if (vol()->fatType() == 0) {
|
||||
pr->println(F("Invalid format, reformat SD."));
|
||||
} else if (!vwd()->isOpen()) {
|
||||
pr->println(F("Can't open root directory."));
|
||||
} else {
|
||||
pr->println(F("No error found."));
|
||||
}
|
||||
}
|
||||
/**Print message and error details and halt after begin() fails.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorPrint(char const *msg) {
|
||||
initErrorPrint(&Serial, msg);
|
||||
}
|
||||
/**Print message and error details and halt after begin() fails.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorPrint(Print* pr, char const *msg) {
|
||||
pr->println(msg);
|
||||
initErrorPrint(pr);
|
||||
}
|
||||
#if defined(ARDUINO) || defined(DOXYGEN)
|
||||
/** %Print msg, any SD error code, and halt.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorHalt(const __FlashStringHelper* msg) {
|
||||
errorHalt(&Serial, msg);
|
||||
}
|
||||
/** %Print msg, any SD error code, and halt.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorHalt(Print* pr, const __FlashStringHelper* msg) {
|
||||
errorPrint(pr, msg);
|
||||
SysCall::halt();
|
||||
}
|
||||
|
||||
/** %Print msg, any SD error code.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorPrint(const __FlashStringHelper* msg) {
|
||||
errorPrint(&Serial, msg);
|
||||
}
|
||||
/** %Print msg, any SD error code.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void errorPrint(Print* pr, const __FlashStringHelper* msg) {
|
||||
pr->print(F("error: "));
|
||||
pr->println(msg);
|
||||
errorPrint(pr);
|
||||
}
|
||||
/**Print message, error details, and halt after begin() fails.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorHalt(const __FlashStringHelper* msg) {
|
||||
initErrorHalt(&Serial, msg);
|
||||
}
|
||||
/**Print message, error details, and halt after begin() fails.
|
||||
* \param[in] pr Print device for message.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorHalt(Print* pr, const __FlashStringHelper* msg) {
|
||||
pr->println(msg);
|
||||
initErrorHalt(pr);
|
||||
}
|
||||
/**Print message and error details and halt after begin() fails.
|
||||
*
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorPrint(const __FlashStringHelper* msg) {
|
||||
initErrorPrint(&Serial, msg);
|
||||
}
|
||||
/**Print message and error details and halt after begin() fails.
|
||||
*
|
||||
* \param[in] pr Print destination.
|
||||
* \param[in] msg Message to print.
|
||||
*/
|
||||
void initErrorPrint(Print* pr, const __FlashStringHelper* msg) {
|
||||
pr->println(msg);
|
||||
initErrorPrint(pr);
|
||||
}
|
||||
#endif // defined(ARDUINO) || defined(DOXYGEN)
|
||||
/** \return The card error code */
|
||||
uint8_t cardErrorCode() {
|
||||
return m_card.errorCode();
|
||||
}
|
||||
/** \return the card error data */
|
||||
uint32_t cardErrorData() {
|
||||
return m_card.errorData();
|
||||
}
|
||||
|
||||
protected:
|
||||
SdDriverClass m_card;
|
||||
};
|
||||
//==============================================================================
|
||||
/**
|
||||
* \class SdFat
|
||||
* \brief Main file system class for %SdFat library.
|
||||
*/
|
||||
class SdFat : public SdFileSystem<SdSpiCard> {
|
||||
public:
|
||||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN)
|
||||
SdFat() {
|
||||
m_spi.setPort(nullptr);
|
||||
}
|
||||
/** Constructor with SPI port selection.
|
||||
* \param[in] spiPort SPI port number.
|
||||
*/
|
||||
explicit SdFat(SPIClass* spiPort) {
|
||||
m_spi.setPort(spiPort);
|
||||
}
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
/** Initialize SD card and file system.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
* \param[in] spiSettings SPI speed, mode, and bit order.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(uint8_t csPin = SS, SPISettings spiSettings = SPI_FULL_SPEED) {
|
||||
return m_card.begin(&m_spi, csPin, spiSettings) &&
|
||||
SdFileSystem::begin();
|
||||
}
|
||||
/** Initialize SD card for diagnostic use only.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
* \param[in] settings SPI speed, mode, and bit order.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool cardBegin(uint8_t csPin = SS, SPISettings settings = SPI_FULL_SPEED) {
|
||||
return m_card.begin(&m_spi, csPin, settings);
|
||||
}
|
||||
/** Initialize file system for diagnostic use only.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool fsBegin() {
|
||||
return FatFileSystem::begin(card());
|
||||
}
|
||||
|
||||
private:
|
||||
SdFatSpiDriver m_spi;
|
||||
};
|
||||
//==============================================================================
|
||||
#if ENABLE_SDIO_CLASS || defined(DOXYGEN)
|
||||
/**
|
||||
* \class SdFatSdio
|
||||
* \brief SdFat class using SDIO.
|
||||
*/
|
||||
class SdFatSdio : public SdFileSystem<SdioCard> {
|
||||
public:
|
||||
/** Initialize SD card and file system.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin() {
|
||||
return m_card.begin() && SdFileSystem::begin();
|
||||
}
|
||||
/** Initialize SD card for diagnostic use only.
|
||||
*
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool cardBegin() {
|
||||
return m_card.begin();
|
||||
}
|
||||
/** Initialize file system for diagnostic use only.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool fsBegin() {
|
||||
return SdFileSystem::begin();
|
||||
}
|
||||
};
|
||||
#if ENABLE_SDIOEX_CLASS || defined(DOXYGEN)
|
||||
//-----------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdFatSdioEX
|
||||
* \brief SdFat class using SDIO.
|
||||
*/
|
||||
class SdFatSdioEX : public SdFileSystem<SdioCardEX> {
|
||||
public:
|
||||
/** Initialize SD card and file system.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin() {
|
||||
return m_card.begin() && SdFileSystem::begin();
|
||||
}
|
||||
/** \return Pointer to SD card object */
|
||||
SdioCardEX* card() {
|
||||
return &m_card;
|
||||
}
|
||||
/** Initialize SD card for diagnostic use only.
|
||||
*
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool cardBegin() {
|
||||
return m_card.begin();
|
||||
}
|
||||
/** Initialize file system for diagnostic use only.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool fsBegin() {
|
||||
return SdFileSystem::begin();
|
||||
}
|
||||
};
|
||||
#endif // ENABLE_SDIOEX_CLASS || defined(DOXYGEN)
|
||||
#endif // ENABLE_SDIO_CLASS || defined(DOXYGEN)
|
||||
//=============================================================================
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
/**
|
||||
* \class SdFatSoftSpi
|
||||
* \brief SdFat class using software SPI.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
|
||||
class SdFatSoftSpi : public SdFileSystem<SdSpiCard> {
|
||||
public:
|
||||
/** Initialize SD card and file system.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
* \param[in] spiSettings ignored for software SPI..
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(uint8_t csPin = SS, SPISettings spiSettings = SPI_FULL_SPEED) {
|
||||
return m_card.begin(&m_spi, csPin, spiSettings) &&
|
||||
SdFileSystem::begin();
|
||||
}
|
||||
private:
|
||||
SdSpiSoftDriver<MisoPin, MosiPin, SckPin> m_spi;
|
||||
};
|
||||
#endif // #if ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
//==============================================================================
|
||||
#if ENABLE_EXTENDED_TRANSFER_CLASS || defined(DOXYGEN)
|
||||
/**
|
||||
* \class SdFatEX
|
||||
* \brief SdFat class with extended SD I/O.
|
||||
*/
|
||||
class SdFatEX : public SdFileSystem<SdSpiCardEX> {
|
||||
public:
|
||||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN)
|
||||
SdFatEX() {
|
||||
m_spi.setPort(nullptr);
|
||||
}
|
||||
/** Constructor with SPI port selection.
|
||||
* \param[in] spiPort SPI port number.
|
||||
*/
|
||||
explicit SdFatEX(SPIClass* spiPort) {
|
||||
m_spi.setPort(spiPort);
|
||||
}
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
/** Initialize SD card and file system.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
* \param[in] spiSettings SPI speed, mode, and bit order.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(uint8_t csPin = SS, SPISettings spiSettings = SPI_FULL_SPEED) {
|
||||
return m_card.begin(&m_spi, csPin, spiSettings) &&
|
||||
SdFileSystem::begin();
|
||||
}
|
||||
|
||||
private:
|
||||
SdFatSpiDriver m_spi;
|
||||
};
|
||||
//==============================================================================
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
/**
|
||||
* \class SdFatSoftSpiEX
|
||||
* \brief SdFat class using software SPI and extended SD I/O.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
|
||||
class SdFatSoftSpiEX : public SdFileSystem<SdSpiCardEX> {
|
||||
public:
|
||||
/** Initialize SD card and file system.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
* \param[in] spiSettings ignored for software SPI.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(uint8_t csPin = SS, SPISettings spiSettings = SPI_FULL_SPEED) {
|
||||
return m_card.begin(&m_spi, csPin, spiSettings) &&
|
||||
SdFileSystem::begin();
|
||||
}
|
||||
private:
|
||||
SdSpiSoftDriver<MisoPin, MosiPin, SckPin> m_spi;
|
||||
};
|
||||
#endif // #if ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
#endif // ENABLE_EXTENDED_TRANSFER_CLASS || defined(DOXYGEN)
|
||||
//=============================================================================
|
||||
/**
|
||||
* \class Sd2Card
|
||||
* \brief Raw access to SD and SDHC card using default SPI library.
|
||||
*/
|
||||
class Sd2Card : public SdSpiCard {
|
||||
public:
|
||||
/** Initialize the SD card.
|
||||
* \param[in] csPin SD chip select pin.
|
||||
* \param[in] settings SPI speed, mode, and bit order.
|
||||
* \return true for success else false.
|
||||
*/
|
||||
bool begin(uint8_t csPin = SS, SPISettings settings = SD_SCK_MHZ(50)) {
|
||||
return SdSpiCard::begin(&m_spi, csPin, settings);
|
||||
}
|
||||
private:
|
||||
SdFatSpiDriver m_spi;
|
||||
};
|
||||
#endif // SdFat_h
|
231
hardware/sd_card_formatter/src/SdFat/SdFatConfig.h
Normal file
231
hardware/sd_card_formatter/src/SdFat/SdFatConfig.h
Normal file
|
@ -0,0 +1,231 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief configuration definitions
|
||||
*/
|
||||
#ifndef SdFatConfig_h
|
||||
#define SdFatConfig_h
|
||||
#include <Arduino.h>
|
||||
#include <stdint.h>
|
||||
#ifdef __AVR__
|
||||
#include <avr/io.h>
|
||||
#endif // __AVR__
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set INCLUDE_SDIOS nonzero to include sdios.h in SdFat.h.
|
||||
* sdios.h provides C++ style IO Streams.
|
||||
*/
|
||||
#define INCLUDE_SDIOS 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_LONG_FILE_NAMES nonzero to use long file names (LFN).
|
||||
* Long File Name are limited to a maximum length of 255 characters.
|
||||
*
|
||||
* This implementation allows 7-bit characters in the range
|
||||
* 0X20 to 0X7E except the following characters are not allowed:
|
||||
*
|
||||
* < (less than)
|
||||
* > (greater than)
|
||||
* : (colon)
|
||||
* " (double quote)
|
||||
* / (forward slash)
|
||||
* \ (backslash)
|
||||
* | (vertical bar or pipe)
|
||||
* ? (question mark)
|
||||
* * (asterisk)
|
||||
*
|
||||
*/
|
||||
#define USE_LONG_FILE_NAMES 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* If the symbol ENABLE_EXTENDED_TRANSFER_CLASS is nonzero, the class SdFatEX
|
||||
* will be defined. If the symbol ENABLE_SOFTWARE_SPI_CLASS is also nonzero,
|
||||
* the class SdFatSoftSpiEX will be defined.
|
||||
*
|
||||
* These classes used extended multi-block SD I/O for better performance.
|
||||
* the SPI bus may not be shared with other devices in this mode.
|
||||
*/
|
||||
#define ENABLE_EXTENDED_TRANSFER_CLASS 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* If the symbol USE_STANDARD_SPI_LIBRARY is zero, an optimized custom SPI
|
||||
* driver is used if it exists. If the symbol USE_STANDARD_SPI_LIBRARY is
|
||||
* one, the standard Arduino SPI.h library is used with SPI. If the symbol
|
||||
* USE_STANDARD_SPI_LIBRARY is two, the SPI port can be selected with the
|
||||
* constructors SdFat(SPIClass* spiPort) and SdFatEX(SPIClass* spiPort).
|
||||
*/
|
||||
#define USE_STANDARD_SPI_LIBRARY 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* If the symbol ENABLE_SOFTWARE_SPI_CLASS is nonzero, the class SdFatSoftSpi
|
||||
* will be defined. If ENABLE_EXTENDED_TRANSFER_CLASS is also nonzero,
|
||||
* the class SdFatSoftSpiEX will be defined.
|
||||
*/
|
||||
#define ENABLE_SOFTWARE_SPI_CLASS 1
|
||||
//------------------------------------------------------------------------------
|
||||
/** If the symbol USE_FCNTL_H is nonzero, open flags for access modes O_RDONLY,
|
||||
* O_WRONLY, O_RDWR and the open modifiers O_APPEND, O_CREAT, O_EXCL, O_SYNC
|
||||
* will be defined by including the system file fcntl.h.
|
||||
*/
|
||||
#if defined(__AVR__)
|
||||
// AVR fcntl.h does not define open flags.
|
||||
#define USE_FCNTL_H 0
|
||||
#elif defined(PLATFORM_ID)
|
||||
// Particle boards - use fcntl.h.
|
||||
#define USE_FCNTL_H 1
|
||||
#elif defined(__arm__)
|
||||
// ARM gcc defines open flags.
|
||||
#define USE_FCNTL_H 1
|
||||
#elif defined(ESP32)
|
||||
#define USE_FCNTL_H 1
|
||||
#else // defined(__AVR__)
|
||||
#define USE_FCNTL_H 0
|
||||
#endif // defined(__AVR__)
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* If CHECK_FLASH_PROGRAMMING is zero, overlap of single sector flash
|
||||
* programming and other operations will be allowed for faster write
|
||||
* performance.
|
||||
*
|
||||
* Some cards will not sleep in low power mode unless CHECK_FLASH_PROGRAMMING
|
||||
* is non-zero.
|
||||
*/
|
||||
#define CHECK_FLASH_PROGRAMMING 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set MAINTAIN_FREE_CLUSTER_COUNT nonzero to keep the count of free clusters
|
||||
* updated. This will increase the speed of the freeClusterCount() call
|
||||
* after the first call. Extra flash will be required.
|
||||
*/
|
||||
#define MAINTAIN_FREE_CLUSTER_COUNT 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* To enable SD card CRC checking set USE_SD_CRC nonzero.
|
||||
*
|
||||
* Set USE_SD_CRC to 1 to use a smaller CRC-CCITT function. This function
|
||||
* is slower for AVR but may be fast for ARM and other processors.
|
||||
*
|
||||
* Set USE_SD_CRC to 2 to used a larger table driven CRC-CCITT function. This
|
||||
* function is faster for AVR but may be slower for ARM and other processors.
|
||||
*/
|
||||
#define USE_SD_CRC 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Handle Watchdog Timer for WiFi modules.
|
||||
*
|
||||
* Yield will be called before accessing the SPI bus if it has been more
|
||||
* than WDT_YIELD_TIME_MICROS microseconds since the last yield call by SdFat.
|
||||
*/
|
||||
#if defined(PLATFORM_ID) || defined(ESP8266)
|
||||
// If Particle device or ESP8266 call yield.
|
||||
#define WDT_YIELD_TIME_MICROS 100000
|
||||
#else
|
||||
#define WDT_YIELD_TIME_MICROS 0
|
||||
#endif
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set FAT12_SUPPORT nonzero to enable use of FAT12 volumes.
|
||||
* FAT12 has not been well tested and requires additional flash.
|
||||
*/
|
||||
#define FAT12_SUPPORT 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set DESTRUCTOR_CLOSES_FILE nonzero to close a file in its destructor.
|
||||
*
|
||||
* Causes use of lots of heap in ARM.
|
||||
*/
|
||||
#define DESTRUCTOR_CLOSES_FILE 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Call flush for endl if ENDL_CALLS_FLUSH is nonzero
|
||||
*
|
||||
* The standard for iostreams is to call flush. This is very costly for
|
||||
* SdFat. Each call to flush causes 2048 bytes of I/O to the SD.
|
||||
*
|
||||
* SdFat has a single 512 byte buffer for SD I/O so it must write the current
|
||||
* data block to the SD, read the directory block from the SD, update the
|
||||
* directory entry, write the directory block to the SD and read the data
|
||||
* block back into the buffer.
|
||||
*
|
||||
* The SD flash memory controller is not designed for this many rewrites
|
||||
* so performance may be reduced by more than a factor of 100.
|
||||
*
|
||||
* If ENDL_CALLS_FLUSH is zero, you must call flush and/or close to force
|
||||
* all data to be written to the SD.
|
||||
*/
|
||||
#define ENDL_CALLS_FLUSH 0
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_SEPARATE_FAT_CACHE nonzero to use a second 512 byte cache
|
||||
* for FAT table entries. This improves performance for large writes
|
||||
* that are not a multiple of 512 bytes.
|
||||
*/
|
||||
#ifdef __arm__
|
||||
#define USE_SEPARATE_FAT_CACHE 1
|
||||
#else // __arm__
|
||||
#define USE_SEPARATE_FAT_CACHE 0
|
||||
#endif // __arm__
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Set USE_MULTI_BLOCK_IO nonzero to use multi-block SD read/write.
|
||||
*
|
||||
* Don't use mult-block read/write on small AVR boards.
|
||||
*/
|
||||
#if defined(RAMEND) && RAMEND < 3000
|
||||
#define USE_MULTI_BLOCK_IO 0
|
||||
#else // RAMEND
|
||||
#define USE_MULTI_BLOCK_IO 1
|
||||
#endif // RAMEND
|
||||
//-----------------------------------------------------------------------------
|
||||
/** Enable SDIO driver if available. */
|
||||
#define ENABLE_SDIO_CLASS 1
|
||||
#define ENABLE_SDIOEX_CLASS 1
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Determine the default SPI configuration.
|
||||
*/
|
||||
#if defined(__STM32F1__) || defined(__STM32F4__) || defined(PLATFORM_ID)
|
||||
// has multiple SPI ports
|
||||
#define SD_HAS_CUSTOM_SPI 2
|
||||
#elif defined(__AVR__)\
|
||||
|| defined(__SAM3X8E__) || defined(__SAM3X8H__)\
|
||||
|| (defined(__arm__) && defined(CORE_TEENSY))\
|
||||
|| defined(ESP8266)
|
||||
#define SD_HAS_CUSTOM_SPI 1
|
||||
#else // SD_HAS_CUSTOM_SPI
|
||||
// Use standard SPI library.
|
||||
#define SD_HAS_CUSTOM_SPI 0
|
||||
#endif // SD_HAS_CUSTOM_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* Check if API to select HW SPI port is needed.
|
||||
*/
|
||||
#if USE_STANDARD_SPI_LIBRARY > 1 || SD_HAS_CUSTOM_SPI > 1
|
||||
#define IMPLEMENT_SPI_PORT_SELECTION 1
|
||||
#else // IMPLEMENT_SPI_PORT_SELECTION
|
||||
#define IMPLEMENT_SPI_PORT_SELECTION 0
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
#endif // SdFatConfig_h
|
386
hardware/sd_card_formatter/src/SdFat/SpiDriver/DigitalPin.h
Normal file
386
hardware/sd_card_formatter/src/SdFat/SpiDriver/DigitalPin.h
Normal file
|
@ -0,0 +1,386 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief Fast Digital Pin functions
|
||||
*
|
||||
* @defgroup digitalPin Fast Pin I/O
|
||||
* @details Fast Digital I/O functions and template class.
|
||||
* @{
|
||||
*/
|
||||
#ifndef DigitalPin_h
|
||||
#define DigitalPin_h
|
||||
#if defined(__AVR__) || defined(DOXYGEN)
|
||||
#include <avr/io.h>
|
||||
/** GpioPinMap type */
|
||||
struct GpioPinMap_t {
|
||||
volatile uint8_t* pin; /**< address of PIN for this pin */
|
||||
volatile uint8_t* ddr; /**< address of DDR for this pin */
|
||||
volatile uint8_t* port; /**< address of PORT for this pin */
|
||||
uint8_t mask; /**< bit mask for this pin */
|
||||
};
|
||||
|
||||
/** Initializer macro. */
|
||||
#define GPIO_PIN(reg, bit) {&PIN##reg, &DDR##reg, &PORT##reg, 1 << bit}
|
||||
|
||||
// Include pin map for current board.
|
||||
#include "boards/GpioPinMap.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** generate bad pin number error */
|
||||
void badPinNumber(void)
|
||||
__attribute__((error("Pin number is too large or not a constant")));
|
||||
//------------------------------------------------------------------------------
|
||||
/** Check for valid pin number
|
||||
* @param[in] pin Number of pin to be checked.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void badPinCheck(uint8_t pin) {
|
||||
if (!__builtin_constant_p(pin) || pin >= NUM_DIGITAL_PINS) {
|
||||
badPinNumber();
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** DDR register address
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return register address
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
volatile uint8_t* ddrReg(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
return GpioPinMap[pin].ddr;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Bit mask for pin
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return mask
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
uint8_t pinMask(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
return GpioPinMap[pin].mask;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** PIN register address
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return register address
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
volatile uint8_t* pinReg(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
return GpioPinMap[pin].pin;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** PORT register address
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return register address
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
volatile uint8_t* portReg(uint8_t pin) {
|
||||
badPinCheck(pin);
|
||||
return GpioPinMap[pin].port;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Fast write helper.
|
||||
* @param[in] address I/O register address
|
||||
* @param[in] mask bit mask for pin
|
||||
* @param[in] level value for bit
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastBitWriteSafe(volatile uint8_t* address, uint8_t mask, bool level) {
|
||||
uint8_t s;
|
||||
if (address > reinterpret_cast<uint8_t*>(0X3F)) {
|
||||
s = SREG;
|
||||
cli();
|
||||
}
|
||||
if (level) {
|
||||
*address |= mask;
|
||||
} else {
|
||||
*address &= ~mask;
|
||||
}
|
||||
if (address > reinterpret_cast<uint8_t*>(0X3F)) {
|
||||
SREG = s;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Read pin value.
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
return *pinReg(pin) & pinMask(pin);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Toggle a pin.
|
||||
* @param[in] pin Arduino pin number
|
||||
*
|
||||
* If the pin is in output mode toggle the pin level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalToggle(uint8_t pin) {
|
||||
if (pinReg(pin) > reinterpret_cast<uint8_t*>(0X3F)) {
|
||||
// must write bit to high address port
|
||||
*pinReg(pin) = pinMask(pin);
|
||||
} else {
|
||||
// will compile to sbi and PIN register will not be read.
|
||||
*pinReg(pin) |= pinMask(pin);
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value.
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool level) {
|
||||
fastBitWriteSafe(portReg(pin), pinMask(pin), level);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Write the DDR register.
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDdrWrite(uint8_t pin, bool level) {
|
||||
fastBitWriteSafe(ddrReg(pin), pinMask(pin), level);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin mode.
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] mode INPUT, OUTPUT, or INPUT_PULLUP.
|
||||
*
|
||||
* The internal pullup resistors will be enabled if mode is INPUT_PULLUP
|
||||
* and disabled if the mode is INPUT.
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastPinMode(uint8_t pin, uint8_t mode) {
|
||||
fastDdrWrite(pin, mode == OUTPUT);
|
||||
if (mode != OUTPUT) {
|
||||
fastDigitalWrite(pin, mode == INPUT_PULLUP);
|
||||
}
|
||||
}
|
||||
#else // defined(__AVR__)
|
||||
#if defined(CORE_TEENSY)
|
||||
//------------------------------------------------------------------------------
|
||||
/** read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
return *portInputRegister(pin);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool value) {
|
||||
if (value) {
|
||||
*portSetRegister(pin) = 1;
|
||||
} else {
|
||||
*portClearRegister(pin) = 1;
|
||||
}
|
||||
}
|
||||
#elif defined(__SAM3X8E__) || defined(__SAM3X8H__)
|
||||
//------------------------------------------------------------------------------
|
||||
/** read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] level value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, bool value) {
|
||||
if (value) {
|
||||
g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
|
||||
} else {
|
||||
g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
|
||||
}
|
||||
}
|
||||
#elif defined(ESP8266)
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] val value to write
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
void fastDigitalWrite(uint8_t pin, uint8_t val) {
|
||||
if (pin < 16) {
|
||||
if (val) {
|
||||
GPOS = (1 << pin);
|
||||
} else {
|
||||
GPOC = (1 << pin);
|
||||
}
|
||||
} else if (pin == 16) {
|
||||
if (val) {
|
||||
GP16O |= 1;
|
||||
} else {
|
||||
GP16O &= ~1;
|
||||
}
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Read pin value
|
||||
* @param[in] pin Arduino pin number
|
||||
* @return value read
|
||||
*/
|
||||
static inline __attribute__((always_inline))
|
||||
bool fastDigitalRead(uint8_t pin) {
|
||||
if (pin < 16) {
|
||||
return GPIP(pin);
|
||||
} else if (pin == 16) {
|
||||
return GP16I & 0x01;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else // CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
inline void fastDigitalWrite(uint8_t pin, bool value) {
|
||||
digitalWrite(pin, value);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline bool fastDigitalRead(uint8_t pin) {
|
||||
return digitalRead(pin);
|
||||
}
|
||||
#endif // CORE_TEENSY
|
||||
//------------------------------------------------------------------------------
|
||||
inline void fastDigitalToggle(uint8_t pin) {
|
||||
fastDigitalWrite(pin, !fastDigitalRead(pin));
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void fastPinMode(uint8_t pin, uint8_t mode) {
|
||||
pinMode(pin, mode);
|
||||
}
|
||||
#endif // __AVR__
|
||||
//------------------------------------------------------------------------------
|
||||
/** set pin configuration
|
||||
* @param[in] pin Arduino pin number
|
||||
* @param[in] mode mode INPUT or OUTPUT.
|
||||
* @param[in] level If mode is output, set level high/low.
|
||||
* If mode is input, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
#define fastPinConfig(pin, mode, level)\
|
||||
{fastPinMode(pin, mode); fastDigitalWrite(pin, level);}
|
||||
//==============================================================================
|
||||
/**
|
||||
* @class DigitalPin
|
||||
* @brief Fast digital port I/O
|
||||
*/
|
||||
template<uint8_t PinNumber>
|
||||
class DigitalPin {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Constructor */
|
||||
DigitalPin() {}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Asignment operator.
|
||||
* @param[in] value If true set the pin's level high else set the
|
||||
* pin's level low.
|
||||
*
|
||||
* @return This DigitalPin instance.
|
||||
*/
|
||||
inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
|
||||
write(value);
|
||||
return *this;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Parenthesis operator.
|
||||
* @return Pin's level
|
||||
*/
|
||||
inline operator bool () const __attribute__((always_inline)) {
|
||||
return read();
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Set pin configuration.
|
||||
* @param[in] mode: INPUT or OUTPUT.
|
||||
* @param[in] level If mode is OUTPUT, set level high/low.
|
||||
* If mode is INPUT, enable or disable the pin's 20K pullup.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void config(uint8_t mode, bool level) {
|
||||
fastPinConfig(PinNumber, mode, level);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level high if output mode or enable 20K pullup if input mode.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void high() {write(true);}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin level low if output mode or disable 20K pullup if input mode.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void low() {write(false);}
|
||||
//----------------------------------------------------------------------------
|
||||
/**
|
||||
* Set pin mode.
|
||||
* @param[in] mode: INPUT, OUTPUT, or INPUT_PULLUP.
|
||||
*
|
||||
* The internal pullup resistors will be enabled if mode is INPUT_PULLUP
|
||||
* and disabled if the mode is INPUT.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void mode(uint8_t mode) {
|
||||
fastPinMode(PinNumber, mode);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** @return Pin's level. */
|
||||
inline __attribute__((always_inline))
|
||||
bool read() const {
|
||||
return fastDigitalRead(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Toggle a pin.
|
||||
*
|
||||
* If the pin is in output mode toggle the pin's level.
|
||||
* If the pin is in input mode toggle the state of the 20K pullup.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void toggle() {
|
||||
fastDigitalToggle(PinNumber);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Write the pin's level.
|
||||
* @param[in] value If true set the pin's level high else set the
|
||||
* pin's level low.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void write(bool value) {
|
||||
fastDigitalWrite(PinNumber, value);
|
||||
}
|
||||
};
|
||||
#endif // DigitalPin_h
|
||||
/** @} */
|
|
@ -0,0 +1,79 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SdSpiBaseDriver_h
|
||||
#define SdSpiBaseDriver_h
|
||||
/**
|
||||
* \class SdSpiBaseDriver
|
||||
* \brief SPI base driver.
|
||||
*/
|
||||
class SdSpiBaseDriver {
|
||||
public:
|
||||
/** Set SPI options for access to SD/SDHC cards.
|
||||
*
|
||||
*/
|
||||
virtual void activate() = 0;
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] chipSelectPin SD card chip select pin.
|
||||
*/
|
||||
virtual void begin(uint8_t chipSelectPin) = 0;
|
||||
/**
|
||||
* End SPI transaction.
|
||||
*/
|
||||
virtual void deactivate() = 0;
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
virtual uint8_t receive() = 0;
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
virtual uint8_t receive(uint8_t* buf, size_t n) = 0;
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] data Byte to send
|
||||
*/
|
||||
virtual void send(uint8_t data) = 0;
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
virtual void send(const uint8_t* buf, size_t n) = 0;
|
||||
/** Set CS low. */
|
||||
virtual void select() = 0;
|
||||
/** Save SPI settings.
|
||||
* \param[in] spiSettings SPI speed, mode, and bit order.
|
||||
*/
|
||||
virtual void setSpiSettings(SPISettings spiSettings) = 0;
|
||||
/** Set CS high. */
|
||||
virtual void unselect() = 0;
|
||||
};
|
||||
#endif // SdSpiBaseDriver_h
|
438
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiDriver.h
Normal file
438
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiDriver.h
Normal file
|
@ -0,0 +1,438 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* \file
|
||||
* \brief SpiDriver classes
|
||||
*/
|
||||
#ifndef SdSpiDriver_h
|
||||
#define SdSpiDriver_h
|
||||
#include <Arduino.h>
|
||||
#include "SPI.h"
|
||||
#include "SdSpiBaseDriver.h"
|
||||
#include "../SdFatConfig.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** SDCARD_SPI is defined if board has built-in SD card socket */
|
||||
#ifndef SDCARD_SPI
|
||||
#define SDCARD_SPI SPI
|
||||
#endif // SDCARD_SPI
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdSpiLibDriver
|
||||
* \brief SdSpiLibDriver - use standard SPI library.
|
||||
*/
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS
|
||||
class SdSpiLibDriver : public SdSpiBaseDriver {
|
||||
#else // ENABLE_SOFTWARE_SPI_CLASS
|
||||
class SdSpiLibDriver {
|
||||
#endif // ENABLE_SOFTWARE_SPI_CLASS
|
||||
public:
|
||||
#if IMPLEMENT_SPI_PORT_SELECTION
|
||||
/** Activate SPI hardware. */
|
||||
void activate() {
|
||||
m_spi->beginTransaction(m_spiSettings);
|
||||
}
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate() {
|
||||
m_spi->endTransaction();
|
||||
}
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
*/
|
||||
void begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
digitalWrite(csPin, HIGH);
|
||||
pinMode(csPin, OUTPUT);
|
||||
m_spi->begin();
|
||||
}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t receive() {
|
||||
return m_spi->transfer( 0XFF);
|
||||
}
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t receive(uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
buf[i] = m_spi->transfer(0XFF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] data Byte to send
|
||||
*/
|
||||
void send(uint8_t data) {
|
||||
m_spi->transfer(data);
|
||||
}
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void send(const uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
m_spi->transfer(buf[i]);
|
||||
}
|
||||
}
|
||||
#else // IMPLEMENT_SPI_PORT_SELECTION
|
||||
/** Activate SPI hardware. */
|
||||
void activate() {
|
||||
SDCARD_SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate() {
|
||||
SDCARD_SPI.endTransaction();
|
||||
}
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
*/
|
||||
void begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
digitalWrite(csPin, HIGH);
|
||||
pinMode(csPin, OUTPUT);
|
||||
SDCARD_SPI.begin();
|
||||
}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t receive() {
|
||||
return SDCARD_SPI.transfer( 0XFF);
|
||||
}
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t receive(uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
buf[i] = SDCARD_SPI.transfer(0XFF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] data Byte to send
|
||||
*/
|
||||
void send(uint8_t data) {
|
||||
SDCARD_SPI.transfer(data);
|
||||
}
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void send(const uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
SDCARD_SPI.transfer(buf[i]);
|
||||
}
|
||||
}
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
/** Set CS low. */
|
||||
void select() {
|
||||
digitalWrite(m_csPin, LOW);
|
||||
}
|
||||
/** Save SPISettings.
|
||||
*
|
||||
* \param[in] spiSettings SPI speed, mode, and byte order.
|
||||
*/
|
||||
void setSpiSettings(SPISettings spiSettings) {
|
||||
m_spiSettings = spiSettings;
|
||||
}
|
||||
/** Set CS high. */
|
||||
void unselect() {
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
}
|
||||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN)
|
||||
/** Set SPI port.
|
||||
* \param[in] spiPort Hardware SPI port.
|
||||
*/
|
||||
void setPort(SPIClass* spiPort) {
|
||||
m_spi = spiPort ? spiPort : &SDCARD_SPI;
|
||||
}
|
||||
private:
|
||||
SPIClass* m_spi;
|
||||
#else // IMPLEMENT_SPI_PORT_SELECTION
|
||||
private:
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
SPISettings m_spiSettings;
|
||||
uint8_t m_csPin;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SdSpiAltDriver
|
||||
* \brief Optimized SPI class for access to SD and SDHC flash memory cards.
|
||||
*/
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS
|
||||
class SdSpiAltDriver : public SdSpiBaseDriver {
|
||||
#else // ENABLE_SOFTWARE_SPI_CLASS
|
||||
class SdSpiAltDriver {
|
||||
#endif // ENABLE_SOFTWARE_SPI_CLASS
|
||||
public:
|
||||
/** Activate SPI hardware. */
|
||||
void activate();
|
||||
/** Deactivate SPI hardware. */
|
||||
void deactivate();
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
*/
|
||||
void begin(uint8_t csPin);
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t receive();
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t receive(uint8_t* buf, size_t n);
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] data Byte to send
|
||||
*/
|
||||
void send(uint8_t data);
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void send(const uint8_t* buf, size_t n);
|
||||
/** Set CS low. */
|
||||
void select() {
|
||||
digitalWrite(m_csPin, LOW);
|
||||
}
|
||||
/** Save SPISettings.
|
||||
*
|
||||
* \param[in] spiSettings SPI speed, mode, and byte order.
|
||||
*/
|
||||
void setSpiSettings(SPISettings spiSettings) {
|
||||
m_spiSettings = spiSettings;
|
||||
}
|
||||
/** Set CS high. */
|
||||
void unselect() {
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
}
|
||||
#if IMPLEMENT_SPI_PORT_SELECTION || defined(DOXYGEN)
|
||||
/** Set SPI port number.
|
||||
* \param[in] spiPort Hardware SPI port.
|
||||
*/
|
||||
void setPort(SPIClass* spiPort) {
|
||||
m_spi = spiPort ? spiPort : &SDCARD_SPI;
|
||||
}
|
||||
private:
|
||||
SPIClass* m_spi;
|
||||
#else // IMPLEMENT_SPI_PORT_SELECTION
|
||||
private:
|
||||
#endif // IMPLEMENT_SPI_PORT_SELECTION
|
||||
SPISettings m_spiSettings;
|
||||
uint8_t m_csPin;
|
||||
};
|
||||
//------------------------------------------------------------------------------
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
#ifdef ARDUINO
|
||||
#include "SoftSPI.h"
|
||||
#elif defined(PLATFORM_ID) // Only defined if a Particle device
|
||||
#include "SoftSPIParticle.h"
|
||||
#endif // ARDUINO
|
||||
/**
|
||||
* \class SdSpiSoftDriver
|
||||
* \brief Software SPI class for access to SD and SDHC flash memory cards.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
|
||||
class SdSpiSoftDriver : public SdSpiBaseDriver {
|
||||
public:
|
||||
/** Dummy activate SPI hardware for software SPI */
|
||||
void activate() {}
|
||||
/** Dummy deactivate SPI hardware for software SPI */
|
||||
void deactivate() {}
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] csPin SD card chip select pin.
|
||||
*/
|
||||
void begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
m_spi.begin();
|
||||
}
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t receive() {
|
||||
return m_spi.receive();
|
||||
}
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t receive(uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
buf[i] = receive();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] data Byte to send
|
||||
*/
|
||||
void send(uint8_t data) {
|
||||
m_spi.send(data);
|
||||
}
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void send(const uint8_t* buf , size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
send(buf[i]);
|
||||
}
|
||||
}
|
||||
/** Set CS low. */
|
||||
void select() {
|
||||
digitalWrite(m_csPin, LOW);
|
||||
}
|
||||
/** Save SPISettings.
|
||||
*
|
||||
* \param[in] spiSettings SPI speed, mode, and byte order.
|
||||
*/
|
||||
void setSpiSettings(SPISettings spiSettings) {
|
||||
(void)spiSettings;
|
||||
}
|
||||
/** Set CS high. */
|
||||
void unselect() {
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
}
|
||||
|
||||
private:
|
||||
uint8_t m_csPin;
|
||||
SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
|
||||
};
|
||||
#endif // ENABLE_SOFTWARE_SPI_CLASS || defined(DOXYGEN)
|
||||
//------------------------------------------------------------------------------
|
||||
// Choose SPI driver for SdFat and SdFatEX classes.
|
||||
#if USE_STANDARD_SPI_LIBRARY || !SD_HAS_CUSTOM_SPI
|
||||
/** SdFat uses Arduino library SPI. */
|
||||
typedef SdSpiLibDriver SdFatSpiDriver;
|
||||
#else // USE_STANDARD_SPI_LIBRARY || !SD_HAS_CUSTOM_SPI
|
||||
/** SdFat uses custom fast SPI. */
|
||||
typedef SdSpiAltDriver SdFatSpiDriver;
|
||||
#endif // USE_STANDARD_SPI_LIBRARY || !SD_HAS_CUSTOM_SPI
|
||||
|
||||
/** typedef for for SdSpiCard class. */
|
||||
#if ENABLE_SOFTWARE_SPI_CLASS
|
||||
// Need virtual driver.
|
||||
typedef SdSpiBaseDriver SdSpiDriver;
|
||||
#else // ENABLE_SOFTWARE_SPI_CLASS
|
||||
// Don't need virtual driver.
|
||||
typedef SdFatSpiDriver SdSpiDriver;
|
||||
#endif // ENABLE_SOFTWARE_SPI_CLASS
|
||||
//==============================================================================
|
||||
// Use of in-line for AVR to save flash.
|
||||
#ifdef __AVR__
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiAltDriver::begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
SPI.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiAltDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiAltDriver::deactivate() {
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline uint8_t SdSpiAltDriver::receive() {
|
||||
SPDR = 0XFF;
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
return SPDR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
if (n-- == 0) {
|
||||
return 0;
|
||||
}
|
||||
SPDR = 0XFF;
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
uint8_t b = SPDR;
|
||||
SPDR = 0XFF;
|
||||
buf[i] = b;
|
||||
}
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
buf[n] = SPDR;
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiAltDriver::send(uint8_t data) {
|
||||
SPDR = data;
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
inline void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
if (n == 0) {
|
||||
return;
|
||||
}
|
||||
SPDR = buf[0];
|
||||
if (n > 1) {
|
||||
uint8_t b = buf[1];
|
||||
size_t i = 2;
|
||||
while (1) {
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
SPDR = b;
|
||||
if (i == n) {
|
||||
break;
|
||||
}
|
||||
b = buf[i++];
|
||||
}
|
||||
}
|
||||
while (!(SPSR & (1 << SPIF))) {}
|
||||
}
|
||||
#endif // __AVR__
|
||||
#endif // SdSpiDriver_h
|
104
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiESP8266.cpp
Normal file
104
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiESP8266.cpp
Normal file
|
@ -0,0 +1,104 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(ESP8266)
|
||||
#include "SdSpiDriver.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] chipSelectPin SD card chip select pin.
|
||||
*/
|
||||
void SdSpiAltDriver::begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
SPI.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set SPI options for access to SD/SDHC cards.
|
||||
*
|
||||
*/
|
||||
void SdSpiAltDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::deactivate() {
|
||||
// Note: endTransaction is an empty function on ESP8266.
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
return SPI.transfer(0XFF);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
// Adjust to 32-bit alignment.
|
||||
while ((reinterpret_cast<uintptr_t>(buf) & 0X3) && n) {
|
||||
*buf++ = SPI.transfer(0xff);
|
||||
n--;
|
||||
}
|
||||
// Do multiple of four byte transfers.
|
||||
size_t n4 = 4*(n/4);
|
||||
SPI.transferBytes(0, buf, n4);
|
||||
|
||||
// Transfer up to three remaining bytes.
|
||||
for (buf += n4, n -= n4; n; n--) {
|
||||
*buf++ = SPI.transfer(0xff);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] b Byte to send
|
||||
*/
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
SPI.transfer(b);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
// Adjust to 32-bit alignment.
|
||||
while ((reinterpret_cast<uintptr_t>(buf) & 0X3) && n) {
|
||||
SPI.transfer(*buf++);
|
||||
n--;
|
||||
}
|
||||
SPI.transferBytes(const_cast<uint8_t*>(buf), 0, n);
|
||||
}
|
||||
#endif // defined(ESP8266)
|
102
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiParticle.cpp
Normal file
102
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiParticle.cpp
Normal file
|
@ -0,0 +1,102 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(PLATFORM_ID)
|
||||
#include "SdSpiDriver.h"
|
||||
static volatile bool SPI_DMA_TransferCompleted = false;
|
||||
//-----------------------------------------------------------------------------
|
||||
static void SD_SPI_DMA_TransferComplete_Callback(void) {
|
||||
SPI_DMA_TransferCompleted = true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set SPI options for access to SD/SDHC cards.
|
||||
*
|
||||
* \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock.
|
||||
*/
|
||||
void SdSpiAltDriver::activate() {
|
||||
m_spi->beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] chipSelectPin SD card chip select pin.
|
||||
*/
|
||||
void SdSpiAltDriver::begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
m_spi->begin();
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* End SPI transaction.
|
||||
*/
|
||||
void SdSpiAltDriver::deactivate() {
|
||||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
SPI_DMA_TransferCompleted = false;
|
||||
m_spi->transfer(nullptr, buf, n, SD_SPI_DMA_TransferComplete_Callback);
|
||||
while (!SPI_DMA_TransferCompleted) {}
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] b Byte to send
|
||||
*/
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
m_spi->transfer(b);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
SPI_DMA_TransferCompleted = false;
|
||||
|
||||
m_spi->transfer(const_cast<uint8_t*>(buf), nullptr, n,
|
||||
SD_SPI_DMA_TransferComplete_Callback);
|
||||
|
||||
while (!SPI_DMA_TransferCompleted) {}
|
||||
}
|
||||
#endif // defined(PLATFORM_ID)
|
218
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiSAM3X.cpp
Normal file
218
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiSAM3X.cpp
Normal file
|
@ -0,0 +1,218 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdSpiDriver.h"
|
||||
#if defined(__SAM3X8E__) || defined(__SAM3X8H__)
|
||||
/** Use SAM3X DMAC if nonzero */
|
||||
#define USE_SAM3X_DMAC 1
|
||||
/** Use extra Bus Matrix arbitration fix if nonzero */
|
||||
#define USE_SAM3X_BUS_MATRIX_FIX 0
|
||||
/** Time in ms for DMA receive timeout */
|
||||
#define SAM3X_DMA_TIMEOUT 100
|
||||
/** chip select register number */
|
||||
#define SPI_CHIP_SEL 3
|
||||
/** DMAC receive channel */
|
||||
#define SPI_DMAC_RX_CH 1
|
||||
/** DMAC transmit channel */
|
||||
#define SPI_DMAC_TX_CH 0
|
||||
/** DMAC Channel HW Interface Number for SPI TX. */
|
||||
#define SPI_TX_IDX 1
|
||||
/** DMAC Channel HW Interface Number for SPI RX. */
|
||||
#define SPI_RX_IDX 2
|
||||
//------------------------------------------------------------------------------
|
||||
/** Disable DMA Controller. */
|
||||
static void dmac_disable() {
|
||||
DMAC->DMAC_EN &= (~DMAC_EN_ENABLE);
|
||||
}
|
||||
/** Enable DMA Controller. */
|
||||
static void dmac_enable() {
|
||||
DMAC->DMAC_EN = DMAC_EN_ENABLE;
|
||||
}
|
||||
/** Disable DMA Channel. */
|
||||
static void dmac_channel_disable(uint32_t ul_num) {
|
||||
DMAC->DMAC_CHDR = DMAC_CHDR_DIS0 << ul_num;
|
||||
}
|
||||
/** Enable DMA Channel. */
|
||||
static void dmac_channel_enable(uint32_t ul_num) {
|
||||
DMAC->DMAC_CHER = DMAC_CHER_ENA0 << ul_num;
|
||||
}
|
||||
/** Poll for transfer complete. */
|
||||
static bool dmac_channel_transfer_done(uint32_t ul_num) {
|
||||
return (DMAC->DMAC_CHSR & (DMAC_CHSR_ENA0 << ul_num)) ? false : true;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
SPI.begin();
|
||||
#if USE_SAM3X_DMAC
|
||||
pmc_enable_periph_clk(ID_DMAC);
|
||||
dmac_disable();
|
||||
DMAC->DMAC_GCFG = DMAC_GCFG_ARB_CFG_FIXED;
|
||||
dmac_enable();
|
||||
#if USE_SAM3X_BUS_MATRIX_FIX
|
||||
MATRIX->MATRIX_WPMR = 0x4d415400;
|
||||
MATRIX->MATRIX_MCFG[1] = 1;
|
||||
MATRIX->MATRIX_MCFG[2] = 1;
|
||||
MATRIX->MATRIX_SCFG[0] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[1] = 0x01000010;
|
||||
MATRIX->MATRIX_SCFG[7] = 0x01000010;
|
||||
#endif // USE_SAM3X_BUS_MATRIX_FIX
|
||||
#endif // USE_SAM3X_DMAC
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// start RX DMA
|
||||
static void spiDmaRX(uint8_t* dst, uint16_t count) {
|
||||
dmac_channel_disable(SPI_DMAC_RX_CH);
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_SADDR = (uint32_t)&SPI0->SPI_RDR;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DADDR = (uint32_t)dst;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_DSCR = 0;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLA = count |
|
||||
DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR |
|
||||
DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_PER2MEM_DMA_FC |
|
||||
DMAC_CTRLB_SRC_INCR_FIXED | DMAC_CTRLB_DST_INCR_INCREMENTING;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_RX_CH].DMAC_CFG = DMAC_CFG_SRC_PER(SPI_RX_IDX) |
|
||||
DMAC_CFG_SRC_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ASAP_CFG;
|
||||
dmac_channel_enable(SPI_DMAC_RX_CH);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// start TX DMA
|
||||
static void spiDmaTX(const uint8_t* src, uint16_t count) {
|
||||
static uint8_t ff = 0XFF;
|
||||
uint32_t src_incr = DMAC_CTRLB_SRC_INCR_INCREMENTING;
|
||||
if (!src) {
|
||||
src = &ff;
|
||||
src_incr = DMAC_CTRLB_SRC_INCR_FIXED;
|
||||
}
|
||||
dmac_channel_disable(SPI_DMAC_TX_CH);
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_SADDR = (uint32_t)src;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DADDR = (uint32_t)&SPI0->SPI_TDR;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_DSCR = 0;
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLA = count |
|
||||
DMAC_CTRLA_SRC_WIDTH_BYTE | DMAC_CTRLA_DST_WIDTH_BYTE;
|
||||
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CTRLB = DMAC_CTRLB_SRC_DSCR |
|
||||
DMAC_CTRLB_DST_DSCR | DMAC_CTRLB_FC_MEM2PER_DMA_FC |
|
||||
src_incr | DMAC_CTRLB_DST_INCR_FIXED;
|
||||
|
||||
DMAC->DMAC_CH_NUM[SPI_DMAC_TX_CH].DMAC_CFG = DMAC_CFG_DST_PER(SPI_TX_IDX) |
|
||||
DMAC_CFG_DST_H2SEL | DMAC_CFG_SOD | DMAC_CFG_FIFOCFG_ALAP_CFG;
|
||||
|
||||
dmac_channel_enable(SPI_DMAC_TX_CH);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// initialize SPI controller
|
||||
void SdSpiAltDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
|
||||
Spi* pSpi = SPI0;
|
||||
// Save the divisor
|
||||
uint32_t scbr = pSpi->SPI_CSR[SPI_CHIP_SEL] & 0XFF00;
|
||||
// Disable SPI
|
||||
pSpi->SPI_CR = SPI_CR_SPIDIS;
|
||||
// reset SPI
|
||||
pSpi->SPI_CR = SPI_CR_SWRST;
|
||||
// no mode fault detection, set master mode
|
||||
pSpi->SPI_MR = SPI_PCS(SPI_CHIP_SEL) | SPI_MR_MODFDIS | SPI_MR_MSTR;
|
||||
// mode 0, 8-bit,
|
||||
pSpi->SPI_CSR[SPI_CHIP_SEL] = scbr | SPI_CSR_CSAAT | SPI_CSR_NCPHA;
|
||||
// enable SPI
|
||||
pSpi->SPI_CR |= SPI_CR_SPIEN;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::deactivate() {
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
static inline uint8_t spiTransfer(uint8_t b) {
|
||||
Spi* pSpi = SPI0;
|
||||
|
||||
pSpi->SPI_TDR = b;
|
||||
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {}
|
||||
b = pSpi->SPI_RDR;
|
||||
return b;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive a byte */
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
return spiTransfer(0XFF);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive multiple bytes */
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
Spi* pSpi = SPI0;
|
||||
int rtn = 0;
|
||||
#if USE_SAM3X_DMAC
|
||||
// clear overrun error
|
||||
pSpi->SPI_SR;
|
||||
|
||||
spiDmaRX(buf, n);
|
||||
spiDmaTX(0, n);
|
||||
|
||||
uint32_t m = millis();
|
||||
while (!dmac_channel_transfer_done(SPI_DMAC_RX_CH)) {
|
||||
if ((millis() - m) > SAM3X_DMA_TIMEOUT) {
|
||||
dmac_channel_disable(SPI_DMAC_RX_CH);
|
||||
dmac_channel_disable(SPI_DMAC_TX_CH);
|
||||
rtn = 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (pSpi->SPI_SR & SPI_SR_OVRES) {
|
||||
rtn |= 1;
|
||||
}
|
||||
#else // USE_SAM3X_DMAC
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pSpi->SPI_TDR = 0XFF;
|
||||
while ((pSpi->SPI_SR & SPI_SR_RDRF) == 0) {}
|
||||
buf[i] = pSpi->SPI_RDR;
|
||||
}
|
||||
#endif // USE_SAM3X_DMAC
|
||||
return rtn;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send a byte */
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
spiTransfer(b);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
Spi* pSpi = SPI0;
|
||||
#if USE_SAM3X_DMAC
|
||||
spiDmaTX(buf, n);
|
||||
while (!dmac_channel_transfer_done(SPI_DMAC_TX_CH)) {}
|
||||
#else // #if USE_SAM3X_DMAC
|
||||
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {}
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
pSpi->SPI_TDR = buf[i];
|
||||
while ((pSpi->SPI_SR & SPI_SR_TDRE) == 0) {}
|
||||
}
|
||||
#endif // #if USE_SAM3X_DMAC
|
||||
while ((pSpi->SPI_SR & SPI_SR_TXEMPTY) == 0) {}
|
||||
// leave RDR empty
|
||||
pSpi->SPI_RDR;
|
||||
}
|
||||
#endif // defined(__SAM3X8E__) || defined(__SAM3X8H__)
|
105
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiSTM32.cpp
Normal file
105
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiSTM32.cpp
Normal file
|
@ -0,0 +1,105 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#if defined(__STM32F1__) || defined(__STM32F4__)
|
||||
#include "SdSpiDriver.h"
|
||||
#if defined(__STM32F1__)
|
||||
#define USE_STM32_DMA 1
|
||||
#elif defined(__STM32F4__)
|
||||
#define USE_STM32_DMA 1
|
||||
#else // defined(__STM32F1__)
|
||||
#error Unknown STM32 type
|
||||
#endif // defined(__STM32F1__)
|
||||
//------------------------------------------------------------------------------
|
||||
/** Set SPI options for access to SD/SDHC cards.
|
||||
*
|
||||
* \param[in] divisor SCK clock divider relative to the APB1 or APB2 clock.
|
||||
*/
|
||||
void SdSpiAltDriver::activate() {
|
||||
m_spi->beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Initialize the SPI bus.
|
||||
*
|
||||
* \param[in] chipSelectPin SD card chip select pin.
|
||||
*/
|
||||
void SdSpiAltDriver::begin(uint8_t csPin) {
|
||||
m_csPin = csPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
m_spi->begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* End SPI transaction.
|
||||
*/
|
||||
void SdSpiAltDriver::deactivate() {
|
||||
m_spi->endTransaction();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
return m_spi->transfer(0XFF);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
#if USE_STM32_DMA
|
||||
return m_spi->dmaTransfer(nullptr, buf, n);
|
||||
#else // USE_STM32_DMA
|
||||
m_spi->read(buf, n);
|
||||
return 0;
|
||||
#endif // USE_STM32_DMA
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] b Byte to send
|
||||
*/
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
m_spi->transfer(b);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
#if USE_STM32_DMA
|
||||
m_spi->dmaTransfer(const_cast<uint8*>(buf), nullptr, n);
|
||||
#else // USE_STM32_DMA
|
||||
m_spi->write(const_cast<uint8*>(buf), n);
|
||||
#endif // USE_STM32_DMA
|
||||
}
|
||||
#endif // defined(__STM32F1__) || defined(__STM32F4__)
|
233
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiTeensy3.cpp
Normal file
233
hardware/sd_card_formatter/src/SdFat/SpiDriver/SdSpiTeensy3.cpp
Normal file
|
@ -0,0 +1,233 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "SdSpiDriver.h"
|
||||
#if defined(__arm__) && defined(CORE_TEENSY)
|
||||
// SPI definitions
|
||||
// #include "kinetis.h"
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::activate() {
|
||||
SPI.beginTransaction(m_spiSettings);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::begin(uint8_t chipSelectPin) {
|
||||
m_csPin = chipSelectPin;
|
||||
pinMode(m_csPin, OUTPUT);
|
||||
digitalWrite(m_csPin, HIGH);
|
||||
SPI.begin();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
void SdSpiAltDriver::deactivate() {
|
||||
SPI.endTransaction();
|
||||
}
|
||||
//==============================================================================
|
||||
#ifdef KINETISK
|
||||
|
||||
// use 16-bit frame if SPI_USE_8BIT_FRAME is zero
|
||||
#define SPI_USE_8BIT_FRAME 0
|
||||
// Limit initial fifo to three entries to avoid fifo overrun
|
||||
#define SPI_INITIAL_FIFO_DEPTH 3
|
||||
// define some symbols that are not in mk20dx128.h
|
||||
#ifndef SPI_SR_RXCTR
|
||||
#define SPI_SR_RXCTR 0XF0
|
||||
#endif // SPI_SR_RXCTR
|
||||
#ifndef SPI_PUSHR_CONT
|
||||
#define SPI_PUSHR_CONT 0X80000000
|
||||
#endif // SPI_PUSHR_CONT
|
||||
#ifndef SPI_PUSHR_CTAS
|
||||
#define SPI_PUSHR_CTAS(n) (((n) & 7) << 28)
|
||||
#endif // SPI_PUSHR_CTAS
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive a byte */
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
SPI0_MCR |= SPI_MCR_CLR_RXF;
|
||||
SPI0_SR = SPI_SR_TCF;
|
||||
SPI0_PUSHR = 0xFF;
|
||||
while (!(SPI0_SR & SPI_SR_TCF)) {}
|
||||
return SPI0_POPR;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI receive multiple bytes */
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
// clear any data in RX FIFO
|
||||
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
|
||||
#if SPI_USE_8BIT_FRAME
|
||||
// initial number of bytes to push into TX FIFO
|
||||
int nf = n < SPI_INITIAL_FIFO_DEPTH ? n : SPI_INITIAL_FIFO_DEPTH;
|
||||
for (int i = 0; i < nf; i++) {
|
||||
SPI0_PUSHR = 0XFF;
|
||||
}
|
||||
// limit for pushing dummy data into TX FIFO
|
||||
uint8_t* limit = buf + n - nf;
|
||||
while (buf < limit) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_PUSHR = 0XFF;
|
||||
*buf++ = SPI0_POPR;
|
||||
}
|
||||
// limit for rest of RX data
|
||||
limit += nf;
|
||||
while (buf < limit) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
*buf++ = SPI0_POPR;
|
||||
}
|
||||
#else // SPI_USE_8BIT_FRAME
|
||||
// use 16 bit frame to avoid TD delay between frames
|
||||
// get one byte if n is odd
|
||||
if (n & 1) {
|
||||
*buf++ = receive();
|
||||
n--;
|
||||
}
|
||||
// initial number of words to push into TX FIFO
|
||||
int nf = n/2 < SPI_INITIAL_FIFO_DEPTH ? n/2 : SPI_INITIAL_FIFO_DEPTH;
|
||||
for (int i = 0; i < nf; i++) {
|
||||
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF;
|
||||
}
|
||||
uint8_t* limit = buf + n - 2*nf;
|
||||
while (buf < limit) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | 0XFFFF;
|
||||
uint16_t w = SPI0_POPR;
|
||||
*buf++ = w >> 8;
|
||||
*buf++ = w & 0XFF;
|
||||
}
|
||||
// limit for rest of RX data
|
||||
limit += 2*nf;
|
||||
while (buf < limit) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
uint16_t w = SPI0_POPR;
|
||||
*buf++ = w >> 8;
|
||||
*buf++ = w & 0XFF;
|
||||
}
|
||||
#endif // SPI_USE_8BIT_FRAME
|
||||
return 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send a byte */
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
SPI0_MCR |= SPI_MCR_CLR_RXF;
|
||||
SPI0_SR = SPI_SR_TCF;
|
||||
SPI0_PUSHR = b;
|
||||
while (!(SPI0_SR & SPI_SR_TCF)) {}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/** SPI send multiple bytes */
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
// clear any data in RX FIFO
|
||||
SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
|
||||
#if SPI_USE_8BIT_FRAME
|
||||
// initial number of bytes to push into TX FIFO
|
||||
int nf = n < SPI_INITIAL_FIFO_DEPTH ? n : SPI_INITIAL_FIFO_DEPTH;
|
||||
// limit for pushing data into TX fifo
|
||||
const uint8_t* limit = buf + n;
|
||||
for (int i = 0; i < nf; i++) {
|
||||
SPI0_PUSHR = *buf++;
|
||||
}
|
||||
// write data to TX FIFO
|
||||
while (buf < limit) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_PUSHR = *buf++;
|
||||
SPI0_POPR;
|
||||
}
|
||||
// wait for data to be sent
|
||||
while (nf) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_POPR;
|
||||
nf--;
|
||||
}
|
||||
#else // SPI_USE_8BIT_FRAME
|
||||
// use 16 bit frame to avoid TD delay between frames
|
||||
// send one byte if n is odd
|
||||
if (n & 1) {
|
||||
send(*buf++);
|
||||
n--;
|
||||
}
|
||||
// initial number of words to push into TX FIFO
|
||||
int nf = n/2 < SPI_INITIAL_FIFO_DEPTH ? n/2 : SPI_INITIAL_FIFO_DEPTH;
|
||||
// limit for pushing data into TX fifo
|
||||
const uint8_t* limit = buf + n;
|
||||
for (int i = 0; i < nf; i++) {
|
||||
uint16_t w = (*buf++) << 8;
|
||||
w |= *buf++;
|
||||
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w;
|
||||
}
|
||||
// write data to TX FIFO
|
||||
while (buf < limit) {
|
||||
uint16_t w = *buf++ << 8;
|
||||
w |= *buf++;
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_PUSHR = SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1) | w;
|
||||
SPI0_POPR;
|
||||
}
|
||||
// wait for data to be sent
|
||||
while (nf) {
|
||||
while (!(SPI0_SR & SPI_SR_RXCTR)) {}
|
||||
SPI0_POPR;
|
||||
nf--;
|
||||
}
|
||||
#endif // SPI_USE_8BIT_FRAME
|
||||
}
|
||||
#else // KINETISK
|
||||
//==============================================================================
|
||||
// Use standard SPI library if not KINETISK
|
||||
//------------------------------------------------------------------------------
|
||||
/** Receive a byte.
|
||||
*
|
||||
* \return The byte.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive() {
|
||||
return SPI.transfer(0XFF);
|
||||
}
|
||||
/** Receive multiple bytes.
|
||||
*
|
||||
* \param[out] buf Buffer to receive the data.
|
||||
* \param[in] n Number of bytes to receive.
|
||||
*
|
||||
* \return Zero for no error or nonzero error code.
|
||||
*/
|
||||
uint8_t SdSpiAltDriver::receive(uint8_t* buf, size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
buf[i] = SPI.transfer(0XFF);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
/** Send a byte.
|
||||
*
|
||||
* \param[in] b Byte to send
|
||||
*/
|
||||
void SdSpiAltDriver::send(uint8_t b) {
|
||||
SPI.transfer(b);
|
||||
}
|
||||
/** Send multiple bytes.
|
||||
*
|
||||
* \param[in] buf Buffer for data to be sent.
|
||||
* \param[in] n Number of bytes to send.
|
||||
*/
|
||||
void SdSpiAltDriver::send(const uint8_t* buf , size_t n) {
|
||||
for (size_t i = 0; i < n; i++) {
|
||||
SPI.transfer(buf[i]);
|
||||
}
|
||||
}
|
||||
#endif // KINETISK
|
||||
#endif // defined(__arm__) && defined(CORE_TEENSY)
|
167
hardware/sd_card_formatter/src/SdFat/SpiDriver/SoftSPI.h
Normal file
167
hardware/sd_card_formatter/src/SdFat/SpiDriver/SoftSPI.h
Normal file
|
@ -0,0 +1,167 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
/**
|
||||
* @file
|
||||
* @brief Software SPI.
|
||||
*
|
||||
* @defgroup softSPI Software SPI
|
||||
* @details Software SPI Template Class.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef SoftSPI_h
|
||||
#define SoftSPI_h
|
||||
#include "DigitalPin.h"
|
||||
//------------------------------------------------------------------------------
|
||||
/** Nop for timing. */
|
||||
#define nop asm volatile ("nop\n\t")
|
||||
//------------------------------------------------------------------------------
|
||||
/** Pin Mode for MISO is input.*/
|
||||
#define MISO_MODE INPUT
|
||||
/** Pullups disabled for MISO are disabled. */
|
||||
#define MISO_LEVEL false
|
||||
/** Pin Mode for MOSI is output.*/
|
||||
#define MOSI_MODE OUTPUT
|
||||
/** Pin Mode for SCK is output. */
|
||||
#define SCK_MODE OUTPUT
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* @class SoftSPI
|
||||
* @brief Fast software SPI.
|
||||
*/
|
||||
template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
|
||||
class SoftSPI {
|
||||
public:
|
||||
//----------------------------------------------------------------------------
|
||||
/** Initialize SoftSPI pins. */
|
||||
void begin() {
|
||||
fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
|
||||
fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
|
||||
fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI receive byte.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint8_t receive() {
|
||||
uint8_t data = 0;
|
||||
receiveBit(7, &data);
|
||||
receiveBit(6, &data);
|
||||
receiveBit(5, &data);
|
||||
receiveBit(4, &data);
|
||||
receiveBit(3, &data);
|
||||
receiveBit(2, &data);
|
||||
receiveBit(1, &data);
|
||||
receiveBit(0, &data);
|
||||
return data;
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI send byte.
|
||||
* @param[in] data Data byte to send.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
void send(uint8_t data) {
|
||||
sendBit(7, data);
|
||||
sendBit(6, data);
|
||||
sendBit(5, data);
|
||||
sendBit(4, data);
|
||||
sendBit(3, data);
|
||||
sendBit(2, data);
|
||||
sendBit(1, data);
|
||||
sendBit(0, data);
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
/** Soft SPI transfer byte.
|
||||
* @param[in] txData Data byte to send.
|
||||
* @return Data byte received.
|
||||
*/
|
||||
inline __attribute__((always_inline))
|
||||
uint8_t transfer(uint8_t txData) {
|
||||
uint8_t rxData = 0;
|
||||
transferBit(7, &rxData, txData);
|
||||
transferBit(6, &rxData, txData);
|
||||
transferBit(5, &rxData, txData);
|
||||
transferBit(4, &rxData, txData);
|
||||
transferBit(3, &rxData, txData);
|
||||
transferBit(2, &rxData, txData);
|
||||
transferBit(1, &rxData, txData);
|
||||
transferBit(0, &rxData, txData);
|
||||
return rxData;
|
||||
}
|
||||
|
||||
private:
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
|
||||
inline __attribute__((always_inline))
|
||||
bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
|
||||
inline __attribute__((always_inline))
|
||||
void receiveBit(uint8_t bit, uint8_t* data) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
nop;
|
||||
nop;
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void sendBit(uint8_t bit, uint8_t data) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
fastDigitalWrite(MosiPin, data & (1 << bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
nop;
|
||||
nop;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
inline __attribute__((always_inline))
|
||||
void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
|
||||
if (MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
|
||||
}
|
||||
fastDigitalWrite(MosiPin, txData & (1 << bit));
|
||||
fastDigitalWrite(SckPin,
|
||||
MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
|
||||
if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
|
||||
if (!MODE_CPHA(Mode)) {
|
||||
fastDigitalWrite(SckPin, MODE_CPOL(Mode));
|
||||
}
|
||||
}
|
||||
//----------------------------------------------------------------------------
|
||||
};
|
||||
#endif // SoftSPI_h
|
||||
/** @} */
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef AvrDevelopersGpioPinMap_h
|
||||
#define AvrDevelopersGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(B, 0), // D0
|
||||
GPIO_PIN(B, 1), // D1
|
||||
GPIO_PIN(B, 2), // D2
|
||||
GPIO_PIN(B, 3), // D3
|
||||
GPIO_PIN(B, 4), // D4
|
||||
GPIO_PIN(B, 5), // D5
|
||||
GPIO_PIN(B, 6), // D6
|
||||
GPIO_PIN(B, 7), // D7
|
||||
GPIO_PIN(D, 0), // D8
|
||||
GPIO_PIN(D, 1), // D9
|
||||
GPIO_PIN(D, 2), // D10
|
||||
GPIO_PIN(D, 3), // D11
|
||||
GPIO_PIN(D, 4), // D12
|
||||
GPIO_PIN(D, 5), // D13
|
||||
GPIO_PIN(D, 6), // D14
|
||||
GPIO_PIN(D, 7), // D15
|
||||
GPIO_PIN(C, 0), // D16
|
||||
GPIO_PIN(C, 1), // D17
|
||||
GPIO_PIN(C, 2), // D18
|
||||
GPIO_PIN(C, 3), // D19
|
||||
GPIO_PIN(C, 4), // D20
|
||||
GPIO_PIN(C, 5), // D21
|
||||
GPIO_PIN(C, 6), // D22
|
||||
GPIO_PIN(C, 7), // D23
|
||||
GPIO_PIN(A, 7), // D24
|
||||
GPIO_PIN(A, 6), // D25
|
||||
GPIO_PIN(A, 5), // D26
|
||||
GPIO_PIN(A, 4), // D27
|
||||
GPIO_PIN(A, 3), // D28
|
||||
GPIO_PIN(A, 2), // D29
|
||||
GPIO_PIN(A, 1), // D30
|
||||
GPIO_PIN(A, 0) // D31
|
||||
};
|
||||
#endif // AvrDevelopersGpioPinMap_h
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef BobuinoGpioPinMap_h
|
||||
#define BobuinoGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(B, 0), // D0
|
||||
GPIO_PIN(B, 1), // D1
|
||||
GPIO_PIN(B, 2), // D2
|
||||
GPIO_PIN(B, 3), // D3
|
||||
GPIO_PIN(B, 4), // D4
|
||||
GPIO_PIN(B, 5), // D5
|
||||
GPIO_PIN(B, 6), // D6
|
||||
GPIO_PIN(B, 7), // D7
|
||||
GPIO_PIN(D, 0), // D8
|
||||
GPIO_PIN(D, 1), // D9
|
||||
GPIO_PIN(D, 2), // D10
|
||||
GPIO_PIN(D, 3), // D11
|
||||
GPIO_PIN(D, 4), // D12
|
||||
GPIO_PIN(D, 5), // D13
|
||||
GPIO_PIN(D, 6), // D14
|
||||
GPIO_PIN(D, 7), // D15
|
||||
GPIO_PIN(C, 0), // D16
|
||||
GPIO_PIN(C, 1), // D17
|
||||
GPIO_PIN(C, 2), // D18
|
||||
GPIO_PIN(C, 3), // D19
|
||||
GPIO_PIN(C, 4), // D20
|
||||
GPIO_PIN(C, 5), // D21
|
||||
GPIO_PIN(C, 6), // D22
|
||||
GPIO_PIN(C, 7), // D23
|
||||
GPIO_PIN(A, 0), // D24
|
||||
GPIO_PIN(A, 1), // D25
|
||||
GPIO_PIN(A, 2), // D26
|
||||
GPIO_PIN(A, 3), // D27
|
||||
GPIO_PIN(A, 4), // D28
|
||||
GPIO_PIN(A, 5), // D29
|
||||
GPIO_PIN(A, 6), // D30
|
||||
GPIO_PIN(A, 7) // D31
|
||||
};
|
||||
#endif // BobuinoGpioPinMap_h
|
|
@ -0,0 +1,45 @@
|
|||
#ifndef GpioPinMap_h
|
||||
#define GpioPinMap_h
|
||||
#if defined(__AVR_ATmega168__)\
|
||||
||defined(__AVR_ATmega168P__)\
|
||||
||defined(__AVR_ATmega328P__)
|
||||
// 168 and 328 Arduinos
|
||||
#include "UnoGpioPinMap.h"
|
||||
#elif defined(__AVR_ATmega1280__)\
|
||||
|| defined(__AVR_ATmega2560__)
|
||||
// Mega ADK
|
||||
#include "MegaGpioPinMap.h"
|
||||
#elif defined(__AVR_ATmega32U4__)
|
||||
#ifdef CORE_TEENSY
|
||||
#include "Teensy2GpioPinMap.h"
|
||||
#else // CORE_TEENSY
|
||||
// Leonardo or Yun
|
||||
#include "LeonardoGpioPinMap.h"
|
||||
#endif // CORE_TEENSY
|
||||
#elif defined(__AVR_AT90USB646__)\
|
||||
|| defined(__AVR_AT90USB1286__)
|
||||
// Teensy++ 1.0 & 2.0
|
||||
#include "Teensy2ppGpioPinMap.h"
|
||||
#elif defined(__AVR_ATmega1284P__)\
|
||||
|| defined(__AVR_ATmega1284__)\
|
||||
|| defined(__AVR_ATmega644P__)\
|
||||
|| defined(__AVR_ATmega644__)\
|
||||
|| defined(__AVR_ATmega64__)\
|
||||
|| defined(__AVR_ATmega32__)\
|
||||
|| defined(__AVR_ATmega324__)\
|
||||
|| defined(__AVR_ATmega16__)
|
||||
#ifdef ARDUINO_1284P_AVR_DEVELOPERS
|
||||
#include "AvrDevelopersGpioPinMap.h"
|
||||
#elif defined(BOBUINO_PINOUT) || defined(ARDUINO_1284P_BOBUINO)
|
||||
#include "BobuinoGpioPinMap.h"
|
||||
#elif defined(ARDUINO_1284P_SLEEPINGBEAUTY)
|
||||
#include "SleepingBeautyGpioPinMap.h"
|
||||
#elif defined(STANDARD_PINOUT) || defined(ARDUINO_1284P_STANDARD)
|
||||
#include "Standard1284GpioPinMap.h"
|
||||
#else // ARDUINO_1284P_AVR_DEVELOPERS
|
||||
#error Undefined variant 1284, 644, 324
|
||||
#endif // ARDUINO_1284P_AVR_DEVELOPERS
|
||||
#else // 1284P, 1284, 644
|
||||
#error Unknown board type.
|
||||
#endif // end all boards
|
||||
#endif // GpioPinMap_h
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef LeonardoGpioPinMap_h
|
||||
#define LeonardoGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(D, 2), // D0
|
||||
GPIO_PIN(D, 3), // D1
|
||||
GPIO_PIN(D, 1), // D2
|
||||
GPIO_PIN(D, 0), // D3
|
||||
GPIO_PIN(D, 4), // D4
|
||||
GPIO_PIN(C, 6), // D5
|
||||
GPIO_PIN(D, 7), // D6
|
||||
GPIO_PIN(E, 6), // D7
|
||||
GPIO_PIN(B, 4), // D8
|
||||
GPIO_PIN(B, 5), // D9
|
||||
GPIO_PIN(B, 6), // D10
|
||||
GPIO_PIN(B, 7), // D11
|
||||
GPIO_PIN(D, 6), // D12
|
||||
GPIO_PIN(C, 7), // D13
|
||||
GPIO_PIN(B, 3), // D14
|
||||
GPIO_PIN(B, 1), // D15
|
||||
GPIO_PIN(B, 2), // D16
|
||||
GPIO_PIN(B, 0), // D17
|
||||
GPIO_PIN(F, 7), // D18
|
||||
GPIO_PIN(F, 6), // D19
|
||||
GPIO_PIN(F, 5), // D20
|
||||
GPIO_PIN(F, 4), // D21
|
||||
GPIO_PIN(F, 1), // D22
|
||||
GPIO_PIN(F, 0), // D23
|
||||
GPIO_PIN(D, 4), // D24
|
||||
GPIO_PIN(D, 7), // D25
|
||||
GPIO_PIN(B, 4), // D26
|
||||
GPIO_PIN(B, 5), // D27
|
||||
GPIO_PIN(B, 6), // D28
|
||||
GPIO_PIN(D, 6) // D29
|
||||
};
|
||||
#endif // LeonardoGpioPinMap_h
|
|
@ -0,0 +1,75 @@
|
|||
#ifndef MegaGpioPinMap_h
|
||||
#define MegaGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(E, 0), // D0
|
||||
GPIO_PIN(E, 1), // D1
|
||||
GPIO_PIN(E, 4), // D2
|
||||
GPIO_PIN(E, 5), // D3
|
||||
GPIO_PIN(G, 5), // D4
|
||||
GPIO_PIN(E, 3), // D5
|
||||
GPIO_PIN(H, 3), // D6
|
||||
GPIO_PIN(H, 4), // D7
|
||||
GPIO_PIN(H, 5), // D8
|
||||
GPIO_PIN(H, 6), // D9
|
||||
GPIO_PIN(B, 4), // D10
|
||||
GPIO_PIN(B, 5), // D11
|
||||
GPIO_PIN(B, 6), // D12
|
||||
GPIO_PIN(B, 7), // D13
|
||||
GPIO_PIN(J, 1), // D14
|
||||
GPIO_PIN(J, 0), // D15
|
||||
GPIO_PIN(H, 1), // D16
|
||||
GPIO_PIN(H, 0), // D17
|
||||
GPIO_PIN(D, 3), // D18
|
||||
GPIO_PIN(D, 2), // D19
|
||||
GPIO_PIN(D, 1), // D20
|
||||
GPIO_PIN(D, 0), // D21
|
||||
GPIO_PIN(A, 0), // D22
|
||||
GPIO_PIN(A, 1), // D23
|
||||
GPIO_PIN(A, 2), // D24
|
||||
GPIO_PIN(A, 3), // D25
|
||||
GPIO_PIN(A, 4), // D26
|
||||
GPIO_PIN(A, 5), // D27
|
||||
GPIO_PIN(A, 6), // D28
|
||||
GPIO_PIN(A, 7), // D29
|
||||
GPIO_PIN(C, 7), // D30
|
||||
GPIO_PIN(C, 6), // D31
|
||||
GPIO_PIN(C, 5), // D32
|
||||
GPIO_PIN(C, 4), // D33
|
||||
GPIO_PIN(C, 3), // D34
|
||||
GPIO_PIN(C, 2), // D35
|
||||
GPIO_PIN(C, 1), // D36
|
||||
GPIO_PIN(C, 0), // D37
|
||||
GPIO_PIN(D, 7), // D38
|
||||
GPIO_PIN(G, 2), // D39
|
||||
GPIO_PIN(G, 1), // D40
|
||||
GPIO_PIN(G, 0), // D41
|
||||
GPIO_PIN(L, 7), // D42
|
||||
GPIO_PIN(L, 6), // D43
|
||||
GPIO_PIN(L, 5), // D44
|
||||
GPIO_PIN(L, 4), // D45
|
||||
GPIO_PIN(L, 3), // D46
|
||||
GPIO_PIN(L, 2), // D47
|
||||
GPIO_PIN(L, 1), // D48
|
||||
GPIO_PIN(L, 0), // D49
|
||||
GPIO_PIN(B, 3), // D50
|
||||
GPIO_PIN(B, 2), // D51
|
||||
GPIO_PIN(B, 1), // D52
|
||||
GPIO_PIN(B, 0), // D53
|
||||
GPIO_PIN(F, 0), // D54
|
||||
GPIO_PIN(F, 1), // D55
|
||||
GPIO_PIN(F, 2), // D56
|
||||
GPIO_PIN(F, 3), // D57
|
||||
GPIO_PIN(F, 4), // D58
|
||||
GPIO_PIN(F, 5), // D59
|
||||
GPIO_PIN(F, 6), // D60
|
||||
GPIO_PIN(F, 7), // D61
|
||||
GPIO_PIN(K, 0), // D62
|
||||
GPIO_PIN(K, 1), // D63
|
||||
GPIO_PIN(K, 2), // D64
|
||||
GPIO_PIN(K, 3), // D65
|
||||
GPIO_PIN(K, 4), // D66
|
||||
GPIO_PIN(K, 5), // D67
|
||||
GPIO_PIN(K, 6), // D68
|
||||
GPIO_PIN(K, 7) // D69
|
||||
};
|
||||
#endif // MegaGpioPinMap_h
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef SleepingBeautyGpioPinMap_h
|
||||
#define SleepingBeautyGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(D, 0), // D0
|
||||
GPIO_PIN(D, 1), // D1
|
||||
GPIO_PIN(D, 2), // D2
|
||||
GPIO_PIN(D, 3), // D3
|
||||
GPIO_PIN(B, 0), // D4
|
||||
GPIO_PIN(B, 1), // D5
|
||||
GPIO_PIN(B, 2), // D6
|
||||
GPIO_PIN(B, 3), // D7
|
||||
GPIO_PIN(D, 6), // D8
|
||||
GPIO_PIN(D, 5), // D9
|
||||
GPIO_PIN(B, 4), // D10
|
||||
GPIO_PIN(B, 5), // D11
|
||||
GPIO_PIN(B, 6), // D12
|
||||
GPIO_PIN(B, 7), // D13
|
||||
GPIO_PIN(C, 7), // D14
|
||||
GPIO_PIN(C, 6), // D15
|
||||
GPIO_PIN(A, 5), // D16
|
||||
GPIO_PIN(A, 4), // D17
|
||||
GPIO_PIN(A, 3), // D18
|
||||
GPIO_PIN(A, 2), // D19
|
||||
GPIO_PIN(A, 1), // D20
|
||||
GPIO_PIN(A, 0), // D21
|
||||
GPIO_PIN(D, 4), // D22
|
||||
GPIO_PIN(D, 7), // D23
|
||||
GPIO_PIN(C, 2), // D24
|
||||
GPIO_PIN(C, 3), // D25
|
||||
GPIO_PIN(C, 4), // D26
|
||||
GPIO_PIN(C, 5), // D27
|
||||
GPIO_PIN(C, 1), // D28
|
||||
GPIO_PIN(C, 0), // D29
|
||||
GPIO_PIN(A, 6), // D30
|
||||
GPIO_PIN(A, 7) // D31
|
||||
};
|
||||
#endif // SleepingBeautyGpioPinMap_h
|
|
@ -0,0 +1,37 @@
|
|||
#ifndef Standard1284GpioPinMap_h
|
||||
#define Standard1284GpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(B, 0), // D0
|
||||
GPIO_PIN(B, 1), // D1
|
||||
GPIO_PIN(B, 2), // D2
|
||||
GPIO_PIN(B, 3), // D3
|
||||
GPIO_PIN(B, 4), // D4
|
||||
GPIO_PIN(B, 5), // D5
|
||||
GPIO_PIN(B, 6), // D6
|
||||
GPIO_PIN(B, 7), // D7
|
||||
GPIO_PIN(D, 0), // D8
|
||||
GPIO_PIN(D, 1), // D9
|
||||
GPIO_PIN(D, 2), // D10
|
||||
GPIO_PIN(D, 3), // D11
|
||||
GPIO_PIN(D, 4), // D12
|
||||
GPIO_PIN(D, 5), // D13
|
||||
GPIO_PIN(D, 6), // D14
|
||||
GPIO_PIN(D, 7), // D15
|
||||
GPIO_PIN(C, 0), // D16
|
||||
GPIO_PIN(C, 1), // D17
|
||||
GPIO_PIN(C, 2), // D18
|
||||
GPIO_PIN(C, 3), // D19
|
||||
GPIO_PIN(C, 4), // D20
|
||||
GPIO_PIN(C, 5), // D21
|
||||
GPIO_PIN(C, 6), // D22
|
||||
GPIO_PIN(C, 7), // D23
|
||||
GPIO_PIN(A, 0), // D24
|
||||
GPIO_PIN(A, 1), // D25
|
||||
GPIO_PIN(A, 2), // D26
|
||||
GPIO_PIN(A, 3), // D27
|
||||
GPIO_PIN(A, 4), // D28
|
||||
GPIO_PIN(A, 5), // D29
|
||||
GPIO_PIN(A, 6), // D30
|
||||
GPIO_PIN(A, 7) // D31
|
||||
};
|
||||
#endif // Standard1284GpioPinMap_h
|
|
@ -0,0 +1,30 @@
|
|||
#ifndef Teensy2GpioPinMap_h
|
||||
#define Teensy2GpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(B, 0), // D0
|
||||
GPIO_PIN(B, 1), // D1
|
||||
GPIO_PIN(B, 2), // D2
|
||||
GPIO_PIN(B, 3), // D3
|
||||
GPIO_PIN(B, 7), // D4
|
||||
GPIO_PIN(D, 0), // D5
|
||||
GPIO_PIN(D, 1), // D6
|
||||
GPIO_PIN(D, 2), // D7
|
||||
GPIO_PIN(D, 3), // D8
|
||||
GPIO_PIN(C, 6), // D9
|
||||
GPIO_PIN(C, 7), // D10
|
||||
GPIO_PIN(D, 6), // D11
|
||||
GPIO_PIN(D, 7), // D12
|
||||
GPIO_PIN(B, 4), // D13
|
||||
GPIO_PIN(B, 5), // D14
|
||||
GPIO_PIN(B, 6), // D15
|
||||
GPIO_PIN(F, 7), // D16
|
||||
GPIO_PIN(F, 6), // D17
|
||||
GPIO_PIN(F, 5), // D18
|
||||
GPIO_PIN(F, 4), // D19
|
||||
GPIO_PIN(F, 1), // D20
|
||||
GPIO_PIN(F, 0), // D21
|
||||
GPIO_PIN(D, 4), // D22
|
||||
GPIO_PIN(D, 5), // D23
|
||||
GPIO_PIN(E, 6), // D24
|
||||
};
|
||||
#endif // Teensy2GpioPinMap_h
|
|
@ -0,0 +1,51 @@
|
|||
#ifndef Teensypp2GpioPinMap_h
|
||||
#define Teensypp2GpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(D, 0), // D0
|
||||
GPIO_PIN(D, 1), // D1
|
||||
GPIO_PIN(D, 2), // D2
|
||||
GPIO_PIN(D, 3), // D3
|
||||
GPIO_PIN(D, 4), // D4
|
||||
GPIO_PIN(D, 5), // D5
|
||||
GPIO_PIN(D, 6), // D6
|
||||
GPIO_PIN(D, 7), // D7
|
||||
GPIO_PIN(E, 0), // D8
|
||||
GPIO_PIN(E, 1), // D9
|
||||
GPIO_PIN(C, 0), // D10
|
||||
GPIO_PIN(C, 1), // D11
|
||||
GPIO_PIN(C, 2), // D12
|
||||
GPIO_PIN(C, 3), // D13
|
||||
GPIO_PIN(C, 4), // D14
|
||||
GPIO_PIN(C, 5), // D15
|
||||
GPIO_PIN(C, 6), // D16
|
||||
GPIO_PIN(C, 7), // D17
|
||||
GPIO_PIN(E, 6), // D18
|
||||
GPIO_PIN(E, 7), // D19
|
||||
GPIO_PIN(B, 0), // D20
|
||||
GPIO_PIN(B, 1), // D21
|
||||
GPIO_PIN(B, 2), // D22
|
||||
GPIO_PIN(B, 3), // D23
|
||||
GPIO_PIN(B, 4), // D24
|
||||
GPIO_PIN(B, 5), // D25
|
||||
GPIO_PIN(B, 6), // D26
|
||||
GPIO_PIN(B, 7), // D27
|
||||
GPIO_PIN(A, 0), // D28
|
||||
GPIO_PIN(A, 1), // D29
|
||||
GPIO_PIN(A, 2), // D30
|
||||
GPIO_PIN(A, 3), // D31
|
||||
GPIO_PIN(A, 4), // D32
|
||||
GPIO_PIN(A, 5), // D33
|
||||
GPIO_PIN(A, 6), // D34
|
||||
GPIO_PIN(A, 7), // D35
|
||||
GPIO_PIN(E, 4), // D36
|
||||
GPIO_PIN(E, 5), // D37
|
||||
GPIO_PIN(F, 0), // D38
|
||||
GPIO_PIN(F, 1), // D39
|
||||
GPIO_PIN(F, 2), // D40
|
||||
GPIO_PIN(F, 3), // D41
|
||||
GPIO_PIN(F, 4), // D42
|
||||
GPIO_PIN(F, 5), // D43
|
||||
GPIO_PIN(F, 6), // D44
|
||||
GPIO_PIN(F, 7), // D45
|
||||
};
|
||||
#endif // Teensypp2GpioPinMap_h
|
|
@ -0,0 +1,25 @@
|
|||
#ifndef UnoGpioPinMap_h
|
||||
#define UnoGpioPinMap_h
|
||||
static const GpioPinMap_t GpioPinMap[] = {
|
||||
GPIO_PIN(D, 0), // D0
|
||||
GPIO_PIN(D, 1), // D1
|
||||
GPIO_PIN(D, 2), // D2
|
||||
GPIO_PIN(D, 3), // D3
|
||||
GPIO_PIN(D, 4), // D4
|
||||
GPIO_PIN(D, 5), // D5
|
||||
GPIO_PIN(D, 6), // D6
|
||||
GPIO_PIN(D, 7), // D7
|
||||
GPIO_PIN(B, 0), // D8
|
||||
GPIO_PIN(B, 1), // D9
|
||||
GPIO_PIN(B, 2), // D10
|
||||
GPIO_PIN(B, 3), // D11
|
||||
GPIO_PIN(B, 4), // D12
|
||||
GPIO_PIN(B, 5), // D13
|
||||
GPIO_PIN(C, 0), // D14
|
||||
GPIO_PIN(C, 1), // D15
|
||||
GPIO_PIN(C, 2), // D16
|
||||
GPIO_PIN(C, 3), // D17
|
||||
GPIO_PIN(C, 4), // D18
|
||||
GPIO_PIN(C, 5) // D19
|
||||
};
|
||||
#endif // UnoGpioPinMap_h
|
88
hardware/sd_card_formatter/src/SdFat/SysCall.h
Normal file
88
hardware/sd_card_formatter/src/SdFat/SysCall.h
Normal file
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef SysCall_h
|
||||
#define SysCall_h
|
||||
/**
|
||||
* \file
|
||||
* \brief SysCall class
|
||||
*/
|
||||
#if defined(ARDUINO)
|
||||
#include <Arduino.h>
|
||||
#include <SPI.h>
|
||||
#elif defined(PLATFORM_ID) // Only defined if a Particle device
|
||||
#include "application.h"
|
||||
#else // defined(ARDUINO)
|
||||
#error "Unknown system"
|
||||
#endif // defined(ARDUINO)
|
||||
//------------------------------------------------------------------------------
|
||||
#ifdef ESP8266
|
||||
// undefine F macro if ESP8266.
|
||||
#undef F
|
||||
#endif // ESP8266
|
||||
//------------------------------------------------------------------------------
|
||||
#ifndef F
|
||||
/** Define macro for strings stored in flash. */
|
||||
#define F(str) (str)
|
||||
#endif // F
|
||||
//------------------------------------------------------------------------------
|
||||
/** \return the time in milliseconds. */
|
||||
inline uint16_t curTimeMS() {
|
||||
return millis();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
/**
|
||||
* \class SysCall
|
||||
* \brief SysCall - Class to wrap system calls.
|
||||
*/
|
||||
class SysCall {
|
||||
public:
|
||||
/** Halt execution of this thread. */
|
||||
static void halt() {
|
||||
while (1) {
|
||||
yield();
|
||||
}
|
||||
}
|
||||
/** Yield to other threads. */
|
||||
static void yield();
|
||||
};
|
||||
|
||||
#if defined(ESP8266)
|
||||
inline void SysCall::yield() {
|
||||
// Avoid ESP8266 bug
|
||||
delay(0);
|
||||
}
|
||||
#elif defined(ARDUINO)
|
||||
inline void SysCall::yield() {
|
||||
// Use the external Arduino yield() function.
|
||||
::yield();
|
||||
}
|
||||
#elif defined(PLATFORM_ID) // Only defined if a Particle device
|
||||
inline void SysCall::yield() {
|
||||
Particle.process();
|
||||
}
|
||||
#else // ESP8266
|
||||
inline void SysCall::yield() {}
|
||||
#endif // ESP8266
|
||||
#endif // SysCall_h
|
33
hardware/sd_card_formatter/src/SdFat/sdios.h
Normal file
33
hardware/sd_card_formatter/src/SdFat/sdios.h
Normal file
|
@ -0,0 +1,33 @@
|
|||
/**
|
||||
* Copyright (c) 2011-2018 Bill Greiman
|
||||
* This file is part of the SdFat library for SD memory cards.
|
||||
*
|
||||
* MIT License
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a
|
||||
* copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation
|
||||
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
||||
* and/or sell copies of the Software, and to permit persons to whom the
|
||||
* Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included
|
||||
* in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
|
||||
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
||||
* DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef sdios_h
|
||||
#define sdios_h
|
||||
/**
|
||||
* \file
|
||||
* \brief C++ IO Streams features.
|
||||
*/
|
||||
#include "FatLib/fstream.h"
|
||||
#include "FatLib/ArduinoStream.h"
|
||||
#endif // sdios_h
|
5140
hardware/sd_card_formatter/src/guislice/GUIslice.c
Normal file
5140
hardware/sd_card_formatter/src/guislice/GUIslice.c
Normal file
File diff suppressed because it is too large
Load diff
3801
hardware/sd_card_formatter/src/guislice/GUIslice.h
Normal file
3801
hardware/sd_card_formatter/src/guislice/GUIslice.h
Normal file
File diff suppressed because it is too large
Load diff
218
hardware/sd_card_formatter/src/guislice/GUIslice_config.h
Normal file
218
hardware/sd_card_formatter/src/guislice/GUIslice_config.h
Normal file
|
@ -0,0 +1,218 @@
|
|||
#ifndef _GUISLICE_CONFIG_H_
|
||||
#define _GUISLICE_CONFIG_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (user configuration) selection by device
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
// \file GUIslice_config.h
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// =========================================================================================
|
||||
// SELECT ONE OF THE FOLLOWING EXAMPLE CONFIGURATIONS OR ADD YOUR OWN
|
||||
// - Uncomment one of the following lines
|
||||
// - These example configurations are located in the /configs folder
|
||||
// - To add your own, make a copy of an example config, rename it
|
||||
// and add it to the list here.
|
||||
// - If no line is uncommented, then the default combined configuration
|
||||
// file will be used, ie. GUIslice_config_ard.h / GUIslice_config_linux.h
|
||||
// which is selected at the bottom of this file
|
||||
// - Refer to https://github.com/ImpulseAdventure/GUIslice/wiki/Display-Config-Table
|
||||
// to help identify a suitable config for your MCU shield / display
|
||||
// - Multiple configurations can be supported using the method described here:
|
||||
// https://github.com/ImpulseAdventure/GUIslice/wiki/Arduino-Multiple-Configs
|
||||
// =========================================================================================
|
||||
|
||||
// =========================================================================================
|
||||
// IMPORTANT: Ensure you backup any custom config files before updating GUIslice!
|
||||
// The Arduino IDE deletes all files within the library when updating
|
||||
// =========================================================================================
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Add your own configs here:
|
||||
// ---------------------------------------------------------------------------------------
|
||||
//#include "../configs/my-config.h"
|
||||
|
||||
// ---------------------------------------------------------------------------------------
|
||||
// Example configs included in library /configs:
|
||||
// ---------------------------------------------------------------------------------------
|
||||
|
||||
// Arduino, ARM SAMD, Cortex M0/M4, nRF52:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/ard-shld-adafruit_18_joy.h"
|
||||
//#include "../configs/ard-shld-adafruit_28_cap.h"
|
||||
//#include "../configs/ard-shld-adafruit_28_res.h"
|
||||
//#include "../configs/ard-shld-eastrising_50_ra8875_res.h"
|
||||
//#include "../configs/ard-shld-eastrising_50_ra8875_sumo_res.h"
|
||||
//#include "../configs/ard-shld-eastrising_50_ssd1963_res.h"
|
||||
//#include "../configs/ard-shld-eastrising_70_ra8876_gv.h"
|
||||
//#include "../configs/ard-shld-elegoo_28_res.h"
|
||||
//#include "../configs/ard-shld-generic1_35_touch.h"
|
||||
//#include "../configs/ard-shld-gevino_tft.h"
|
||||
//#include "../configs/ard-shld-ili9341_16b_touch.h"
|
||||
//#include "../configs/ard-shld-mcufriend.h"
|
||||
//#include "../configs/ard-shld-mcufriend_4wire.h"
|
||||
//#include "../configs/ard-shld-mcufriend_xpt2046.h"
|
||||
//#include "../configs/ard-shld-osmart_22_68130_touch.h"
|
||||
//#include "../configs/ard-shld-waveshare_28_touch.h"
|
||||
//#include "../configs/ard-shld-waveshare_40_notouch.h"
|
||||
//#include "../configs/ard-shld-waveshare_40_xpt2046.h"
|
||||
//#include "../configs/ard-adagfx-hx8347-xpt2046.h"
|
||||
//#include "../configs/ard-adagfx-hx8357-ft6206.h"
|
||||
//#include "../configs/ard-adagfx-hx8357-notouch.h"
|
||||
//#include "../configs/ard-adagfx-hx8357-simple.h"
|
||||
//#include "../configs/ard-adagfx-hx8357-stmpe610.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-ft6206.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-input.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-notouch.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-simple.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-stmpe610.h"
|
||||
//#include "../configs/ard-adagfx-ili9341-xpt2046.h"
|
||||
//#include "../configs/ard-adagfx-pcd8544-notouch.h"
|
||||
//#include "../configs/ard-adagfx-ra8875-notouch.h"
|
||||
//#include "../configs/ard-adagfx-ra8876-notouch.h"
|
||||
//#include "../configs/ard-adagfx-ra8876-ft5206.h"
|
||||
//#include "../configs/ard-adagfx-ssd1306-notouch.h"
|
||||
//#include "../configs/ard-adagfx-st7735-notouch.h"
|
||||
//#include "../configs/due-adagfx-ili9341-ft6206.h"
|
||||
//#include "../configs/due-adagfx-ili9341-urtouch.h"
|
||||
|
||||
// ESP8266, ESP32, M5stack, TTGO:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/esp-shld-m5stack.h"
|
||||
//#include "../configs/esp-shld-ttgo_btc_ticker.h"
|
||||
//#include "../configs/esp-tftespi-default-ft6206.h"
|
||||
//#include "../configs/esp-tftespi-default-notouch.h"
|
||||
//#include "../configs/esp-tftespi-default-simple.h"
|
||||
//#include "../configs/esp-tftespi-default-stmpe610.h"
|
||||
//#include "../configs/esp-tftespi-default-xpt2046.h"
|
||||
//#include "../configs/esp-tftespi-default-xpt2046_int.h"
|
||||
|
||||
// Teensy:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/teensy-adagfx-ili9341-xpt2046.h"
|
||||
//#include "../configs/teensy-adagfx-ili9341-xpt2046-audio.h"
|
||||
//#include "../configs/teensy-adagfx-ili9341_t3-xpt2046.h"
|
||||
//#include "../configs/teensy-adagfx-ili9341_t3-xpt2046-audio.h"
|
||||
|
||||
// STM32:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/stm32-adagfx-mcufriend-notouch.h"
|
||||
//#include "../configs/stm32-adagfx-mcufriend-simple.h"
|
||||
|
||||
// Multi-device shields:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/mult-shld-adafruit_24_feather_touch.h"
|
||||
//#include "../configs/mult-shld-adafruit_35_feather_touch.h"
|
||||
|
||||
// Raspberry Pi / LINUX:
|
||||
// ------------------------------------------------------
|
||||
//#include "../configs/rpi-sdl1-default-tslib.h"
|
||||
//#include "../configs/rpi-sdl1-default-sdl.h"
|
||||
//#include "../configs/linux-sdl1-default-mouse.h"
|
||||
|
||||
|
||||
// =========================================================================================
|
||||
// DETECT DEVICE PLATFORM
|
||||
// =========================================================================================
|
||||
|
||||
// Detect device platform
|
||||
// #if defined(__linux__)
|
||||
// #define GSLC_CFG_LINUX
|
||||
// #elif defined(__AVR__) && !defined(TEENSYDUINO)
|
||||
// // Note: Teensy 2 also defines __AVR__, so differentiate with TEENSYDUINO
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ARDUINO_SAMD_ZERO)
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ESP8266) || defined(ESP32)
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(NRF52)
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ARDUINO_STM32_FEATHER) || defined(__STM32F1__)
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ARDUINO_ARCH_STM32) // ST Core from STMicroelectronics
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ARDUINO_ARCH_SAM) // Arduino Due
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(ARDUINO_ARCH_SAMD) // M0_PRO
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(__AVR__) && defined(TEENSYDUINO) // Teensy 2
|
||||
// #define GSLC_DEV_TEENSY_2
|
||||
// #define GSLC_CFG_ARD
|
||||
// #elif defined(__MKL26Z64__) // Teensy LC
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_LC
|
||||
// #elif defined(__MK20DX256__) // Teensy 3.2
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_3_2
|
||||
// #elif defined(__MK64FX512__) // Teensy 3.5
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_3_5
|
||||
// #elif defined(__MK66FX1M0__) // Teensy 3.6
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_3_6
|
||||
// #elif defined(__MK66FX1M0__) // Teensy 3.6
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_3_6
|
||||
// #elif defined(__IMXRT1062__)
|
||||
// #define GSLC_CFG_ARD
|
||||
// #define GSLC_DEV_TEENSY_4_0
|
||||
// #else
|
||||
// #warning Unknown
|
||||
// #error "Unknown device platform"
|
||||
// #endif
|
||||
|
||||
// Adafruit nRF52840 Feather
|
||||
#include "ard-adagfx-ili9341-stmpe610.h"
|
||||
// #include "ard-adagfx-ili9341-notouch.h"
|
||||
#define GSLC_CFG_ARD
|
||||
|
||||
// =========================================================================================
|
||||
// DEFAULT COMBINED CONFIGURATION FILE
|
||||
// - If no user configuration has been selected, a default config will be selected here
|
||||
// - Note that the include guard _GUISLICE_CONFIG_ARD_H_ and _GUISLICE_CONFIG_LINUX_H_
|
||||
// will prevent these from loading if any of the user configs have been loaded
|
||||
// =========================================================================================
|
||||
|
||||
#if defined(GSLC_CFG_LINUX)
|
||||
#include "GUIslice_config_linux.h"
|
||||
#elif defined(GSLC_CFG_ARD)
|
||||
#include "GUIslice_config_ard.h"
|
||||
#endif
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_CONFIG_H_
|
526
hardware/sd_card_formatter/src/guislice/GUIslice_config_ard.h
Normal file
526
hardware/sd_card_formatter/src/guislice/GUIslice_config_ard.h
Normal file
|
@ -0,0 +1,526 @@
|
|||
#ifndef _GUISLICE_CONFIG_ARD_H_
|
||||
#define _GUISLICE_CONFIG_ARD_H_
|
||||
|
||||
#warning No config selected in GUIslice_config.h - resorting to defaults.
|
||||
|
||||
// =============================================================================
|
||||
// GUIslice library (user configuration) for:
|
||||
// - Arduino
|
||||
// - Cortex-M0
|
||||
// - ESP8266 / ESP32
|
||||
// - nRF52
|
||||
// - STM32
|
||||
//
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =============================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =============================================================================
|
||||
// \file GUIslice_config_ard.h
|
||||
|
||||
// =============================================================================
|
||||
// User Configuration
|
||||
// - This file can be modified by the user to match the
|
||||
// intended target configuration
|
||||
// - Please refer to "docs/GUIslice_config_guide.xlsx" for detailed examples
|
||||
// specific to board and display combinations
|
||||
// =============================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// DISPLAY CONFIGURATION - SELECT
|
||||
// =============================================================================
|
||||
|
||||
// Specify the graphics driver library
|
||||
// - Uncomment one of the following graphics drivers DRV_DISP_*
|
||||
// applicable to the device type in use
|
||||
|
||||
// --------------------------------------------------------------
|
||||
// Arduino / ATmega / AVR / Cortex-M0 / nRF52:
|
||||
#define DRV_DISP_ADAGFX // Adafruit-GFX library
|
||||
// --------------------------------------------------------------
|
||||
// ESP8266 / ESP32 / NodeMCU:
|
||||
// #define DRV_DISP_ADAGFX // Adafruit-GFX library
|
||||
// #define DRV_DISP_TFT_ESPI // Bodmer/TFT_eSPI library
|
||||
// #define DRV_DISP_M5STACK // m5stack/M5Stack library
|
||||
// --------------------------------------------------------------
|
||||
// STM32:
|
||||
// #define DRV_DISP_ADAGFX // Adafruit-GFX library
|
||||
// #define DRV_DISP_ADAGFX_AS // Adafruit-GFX-AS library, high speed using DMA
|
||||
// --------------------------------------------------------------
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// TOUCH CONFIGURATION - SELECT
|
||||
// =============================================================================
|
||||
|
||||
// Specify the touchscreen driver
|
||||
// - Uncomment one of the following touchscreen drivers DRV_TOUCH_*
|
||||
// applicable to the controller chip in use
|
||||
|
||||
#define DRV_TOUCH_NONE // No touchscreen support & no input (GPIO / keyboard)
|
||||
// #define DRV_TOUCH_ADA_STMPE610 // Adafruit STMPE610 touch driver
|
||||
// #define DRV_TOUCH_ADA_FT6206 // Adafruit FT6206 touch driver
|
||||
// #define DRV_TOUCH_ADA_SIMPLE // Adafruit Touchscreen
|
||||
// #define DRV_TOUCH_TFT_ESPI // TFT_eSPI integrated XPT2046 touch driver
|
||||
// #define DRV_TOUCH_M5STACK // M5stack integrated button driver
|
||||
// #define DRV_TOUCH_XPT2046_PS // PaulStoffregen/XPT2046_Touchscreen
|
||||
// #define DRV_TOUCH_XPT2046_STM // Arduino_STM32/Serasidis_XPT2046_touch (XPT2046_touch.h)
|
||||
// #define DRV_TOUCH_INPUT // No touchscreen support, but input only (GPIO / keyboard)
|
||||
// #define DRV_TOUCH_HANDLER // touch handler class
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// DISPLAY CONFIGURATION - DETAILS
|
||||
// - Graphics display driver-specific additional configuration
|
||||
// =============================================================================
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(DRV_DISP_ADAGFX)
|
||||
|
||||
// The Adafruit-GFX library supports a number of displays
|
||||
// - Select a display sub-type by uncommenting one of the
|
||||
// following DRV_DISP_ADAGFX_* lines
|
||||
#define DRV_DISP_ADAGFX_ILI9341 // Adafruit ILI9341
|
||||
//#define DRV_DISP_ADAGFX_ILI9341_8BIT // Adafruit ILI9341 (8-bit interface)
|
||||
//#define DRV_DISP_ADAGFX_ST7735 // Adafruit ST7735
|
||||
//#define DRV_DISP_ADAGFX_SSD1306 // Adafruit SSD1306
|
||||
//#define DRV_DISP_ADAGFX_HX8347 // prenticedavid/HX8347D_kbv
|
||||
//#define DRV_DISP_ADAGFX_HX8357 // Adafruit HX8357
|
||||
//#define DRV_DISP_ADAGFX_PCD8544 // Adafruit PCD8544
|
||||
|
||||
// For Adafruit-GFX drivers, define pin connections
|
||||
// - Define general pins (modify these example pin assignments to match your board)
|
||||
// - Please refer to "docs/GUIslice_config_guide.xlsx" for detailed examples
|
||||
#define ADAGFX_PIN_CS 10 // Display chip select
|
||||
#define ADAGFX_PIN_DC 9 // Display SPI data/command
|
||||
#define ADAGFX_PIN_RST 0 // Display Reset (some displays could use pin 11)
|
||||
#define ADAGFX_PIN_SDCS 4 // SD card chip select
|
||||
#define ADAGFX_PIN_WR A1 // Display write pin (for parallel displays)
|
||||
#define ADAGFX_PIN_RD A0 // Display read pin (for parallel displays)
|
||||
|
||||
// Use hardware SPI interface?
|
||||
// - Set to 1 to enable hardware SPI interface, 0 to use software SPI
|
||||
// - Software SPI may support the use of custom pin selection (via ADAGFX_PIN_MOSI,
|
||||
// ADAGFX_PIN_MISO, ADAGFX_PIN_CLK). These pin definitions can be left blank in
|
||||
// hardware SPI mode.
|
||||
#define ADAGFX_SPI_HW 1
|
||||
|
||||
// Define custom SPI pin connections used in software SPI mode (ADAGFX_SPI_HW=0)
|
||||
// - These definitions can be left blank in hardware mode (ADAGFX_SPI_HW=1)
|
||||
#define ADAGFX_PIN_MOSI
|
||||
#define ADAGFX_PIN_MISO
|
||||
#define ADAGFX_PIN_CLK
|
||||
|
||||
// Set Default rotation
|
||||
// you can specify values 0,1,2,3, rotation is clockwise
|
||||
#define GSLC_ROTATE 1
|
||||
|
||||
|
||||
#elif defined(DRV_DISP_ADAGFX_AS)
|
||||
|
||||
//NOTE: this is a optimized driver for STM32 only
|
||||
|
||||
// The Adafruit-GFX-AS library supports a number of displays
|
||||
// - Select a display sub-type by uncommenting one of the
|
||||
// following DRV_DISP_ADAGFX_* lines
|
||||
#define DRV_DISP_ADAGFX_ILI9341_STM // Adafruit ILI9341 (STM32 version)
|
||||
|
||||
// For Adafruit-GFX drivers, define pin connections
|
||||
// - Define general pins (modify these example pin assignments to match your board)
|
||||
// - Please refer to "docs/GUIslice_config_guide.xlsx" for detailed examples
|
||||
|
||||
//Note: Fixed pin setting for HW SPI1
|
||||
// PA5 SCLK
|
||||
// PA6 MISO
|
||||
// PA7 MOSI
|
||||
|
||||
// USE Arduino STM32 PIN Notations
|
||||
// - Define to use Arduino STM32 PIN Notations
|
||||
// #define STM32_NOTATION
|
||||
|
||||
#if defined(STM32_NOTATION)
|
||||
// NOTE: Using Arduino STM32 pin notation
|
||||
#define ADAGFX_PIN_CS PA4 // Display chip select
|
||||
#define ADAGFX_PIN_DC PB1 // Display SPI data/command
|
||||
#define ADAGFX_PIN_RST PB0 // Display Reset (set to -1 in order to use Adafruit-GFX drivers w/o reset)
|
||||
#define ADAGFX_PIN_SDCS // SD card chip select
|
||||
#define ADAGFX_PIN_WR // Display write pin (for parallel displays)
|
||||
#define ADAGFX_PIN_RD // Display read pin (for parallel displays)
|
||||
#else
|
||||
// NOTE: Using Arduino pin notation
|
||||
#define ADAGFX_PIN_CS 10 // Display chip select
|
||||
#define ADAGFX_PIN_DC 9 // Display SPI data/command
|
||||
#define ADAGFX_PIN_RST 0 // Display Reset (some displays could use pin 11)
|
||||
#define ADAGFX_PIN_SDCS 4 // SD card chip select
|
||||
#define ADAGFX_PIN_WR A1 // Display write pin (for parallel displays)
|
||||
#define ADAGFX_PIN_RD A0 // Display read pin (for parallel displays)
|
||||
#endif
|
||||
|
||||
// Use hardware SPI interface?
|
||||
// - Set to 1 to enable hardware SPI interface, 0 to use software SPI
|
||||
// - Software SPI may support the use of custom pin selection (via ADAGFX_PIN_MOSI,
|
||||
// ADAGFX_PIN_MISO, ADAGFX_PIN_CLK). These pin definitions can be left blank in
|
||||
// hardware SPI mode.
|
||||
#define ADAGFX_SPI_HW 1
|
||||
|
||||
// Define custom SPI pin connections used in software SPI mode (ADAGFX_SPI_HW=0)
|
||||
// - These definitions can be left blank in hardware mode (ADAGFX_SPI_HW=1)
|
||||
#define ADAGFX_PIN_MOSI
|
||||
#define ADAGFX_PIN_MISO
|
||||
#define ADAGFX_PIN_CLK
|
||||
|
||||
|
||||
// Set Default rotation
|
||||
// you can specify values 0,1,2,3, rotation is clockwise
|
||||
#define GSLC_ROTATE 1
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_DISP_TFT_ESPI)
|
||||
|
||||
// NOTE: When using the TFT_eSPI library, there are additional
|
||||
// library-specific configuration files that may need
|
||||
// customization (including pin configuration), such as
|
||||
// "User_Setup_Select.h" (typically located in the
|
||||
// Arduino /libraries/TFT_eSPI folder). Please refer to
|
||||
// Bodmer's TFT_eSPI library for more details:
|
||||
// https://github.com/Bodmer/TFT_eSPI
|
||||
|
||||
// NOTE: To avoid potential SPI conflicts, it is recommended
|
||||
// that SUPPORT_TRANSACTIONS is defined in TFT_eSPI's "User Setup"
|
||||
|
||||
|
||||
// Set Default rotation
|
||||
// you can specify values 0,1,2,3, rotation is clockwise
|
||||
#define GSLC_ROTATE 1
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_DISP_M5STACK)
|
||||
|
||||
#define ADAGFX_PIN_SDCS 4 // SD card chip select
|
||||
#define TFT_LIGHT_PIN 32 // display backlight
|
||||
|
||||
// Set Default rotation
|
||||
// you can specify values 0,1,2,3, rotation is clockwise
|
||||
|
||||
// NOTE: M5stack has a fixed display. A setting of 1 should
|
||||
// match the built-in display and not need changing.
|
||||
#define GSLC_ROTATE 1
|
||||
|
||||
#else
|
||||
|
||||
#error "Unknown driver for display DRV_DISP_..."
|
||||
|
||||
#endif // DRV_DISP_*
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// TOUCH CONFIGURATION - DETAILS
|
||||
// - Touch Driver-specific additional configuration
|
||||
// =============================================================================
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#if defined(DRV_TOUCH_NONE)
|
||||
|
||||
//no touch defined
|
||||
|
||||
#elif defined(DRV_TOUCH_ADA_STMPE610)
|
||||
|
||||
// Select wiring method by setting one of the following to 1
|
||||
#define ADATOUCH_I2C_HW 0
|
||||
#define ADATOUCH_SPI_HW 1
|
||||
#define ADATOUCH_SPI_SW 0 // [TODO]
|
||||
|
||||
// For ADATOUCH_I2C_HW=1
|
||||
#define ADATOUCH_I2C_ADDR 0x41 // I2C address of touch device
|
||||
|
||||
// For ADATOUCH_SPI_HW=1
|
||||
#define ADATOUCH_PIN_CS 8 // From Adafruit 2.8" TFT touch shield
|
||||
|
||||
// Calibration values for touch display
|
||||
// - These values may need to be updated to match your display
|
||||
// - Typically used in resistive displays
|
||||
// - These values can be determined from the Adafruit touchtest example sketch
|
||||
// (check for min and max values reported from program as you touch display
|
||||
// corners)
|
||||
// - Note that X & Y directions reference the display's natural orientation
|
||||
#define ADATOUCH_X_MIN 230
|
||||
#define ADATOUCH_Y_MIN 260
|
||||
#define ADATOUCH_X_MAX 3800
|
||||
#define ADATOUCH_Y_MAX 3700
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_ADA_FT6206)
|
||||
// Define sensitivity coefficient (capacitive touch)
|
||||
#define ADATOUCH_SENSITIVITY 40
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_ADA_SIMPLE)
|
||||
|
||||
// Define 4-wire resistive touchscreen pinout
|
||||
#define ADATOUCH_PIN_YP A2 // "Y+": Must be an analog pin, use "An" notation
|
||||
#define ADATOUCH_PIN_XM A3 // "X-": Must be an analog pin, use "An" notation
|
||||
#define ADATOUCH_PIN_YM 44 // "Y-": Can be a digital pin
|
||||
#define ADATOUCH_PIN_XP 45 // "X+": Can be a digital pin
|
||||
#define ADATOUCH_RX 300 // "rxplate"
|
||||
|
||||
// Calibration values for touch display
|
||||
// - These values may need to be updated to match your display
|
||||
// - Typically used in resistive displays
|
||||
#define ADATOUCH_X_MIN 100
|
||||
#define ADATOUCH_Y_MIN 150
|
||||
#define ADATOUCH_X_MAX 900
|
||||
#define ADATOUCH_Y_MAX 900
|
||||
|
||||
// Define pressure threshold for detecting a touch
|
||||
#define ADATOUCH_PRESS_MIN 10
|
||||
#define ADATOUCH_PRESS_MAX 1000
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_TFT_ESPI)
|
||||
// The TFT_eSPI display library also includes support for XPT2046 touch controller
|
||||
// Note that TFT_eSPI's "User_Setup" should define TOUCH_CS
|
||||
#define DRV_TOUCH_IN_DISP // Use the display driver (TFT_eSPI) for touch events
|
||||
|
||||
// Define the XPT2046 touch driver calibration values
|
||||
// - The following are some example defaults, but they should be updated
|
||||
// to match your specific touch device.
|
||||
#define TFT_ESPI_TOUCH_CALIB { 321,3498,280,3593,3 }
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_M5STACK)
|
||||
// M5stack integrated button handler
|
||||
#define DRV_TOUCH_IN_DISP // Use the display driver (M5stack) for touch events
|
||||
|
||||
// NOTE: Long-press detection is only available in the latest
|
||||
// M5stack library releases. Uncomment the following
|
||||
// if the Btn wasReleasefor() API is available.
|
||||
//
|
||||
// Define duration (in ms) for a long-press button event
|
||||
//#define M5STACK_TOUCH_PRESS_LONG 300
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_XPT2046_PS)
|
||||
// PaulStoffregen/XPT2046_Touchscreen
|
||||
|
||||
// Chip select pin for touch
|
||||
#define XPT2046_CS 3
|
||||
|
||||
// Calibration values for touch display
|
||||
// - These values may need to be updated to match your display
|
||||
// - empirically found for XPT2046
|
||||
#define ADATOUCH_X_MIN 246
|
||||
#define ADATOUCH_Y_MIN 3925
|
||||
#define ADATOUCH_X_MAX 3837
|
||||
#define ADATOUCH_Y_MAX 370
|
||||
|
||||
// Define pressure threshold for detecting a touch
|
||||
#define ADATOUCH_PRESS_MIN 10
|
||||
#define ADATOUCH_PRESS_MAX 1000
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_XPT2046_STM)
|
||||
// Arduino_STM32/Serasidis_XPT2046_touch (XPT2046_touch.h)
|
||||
// NOTE: This touch library is included in the Arduino_STM32 library
|
||||
// While it still works on many non-STM32 targets, it is recommended
|
||||
// that users use DRV_TOUCH_XPT2046_PS instead.
|
||||
|
||||
// SPI2 is used. Due to some known issues of the TFT SPI driver working on SPI1
|
||||
// it was not possible to share the touch with SPI1.
|
||||
// On the Arduino STM32 these are the following pins:
|
||||
// PB13 SCLK
|
||||
// PB14 MISO
|
||||
// PB15 MOSI
|
||||
#define XPT2046_DEFINE_DPICLASS SPIClass XPT2046_spi(2); //Create an SPI instance on SPI2 port
|
||||
|
||||
// Chip select pin for touch SPI2
|
||||
#define XPT2046_CS PB12
|
||||
|
||||
// Calibration values for touch display
|
||||
// - These values may need to be updated to match your display
|
||||
// - empirically found for XPT2046
|
||||
#define ADATOUCH_X_MIN 398
|
||||
#define ADATOUCH_Y_MIN 280
|
||||
#define ADATOUCH_X_MAX 3877
|
||||
#define ADATOUCH_Y_MAX 3805
|
||||
|
||||
// Define pressure threshold for detecting a touch
|
||||
#define ADATOUCH_PRESS_MIN 10
|
||||
#define ADATOUCH_PRESS_MAX 1000
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_INPUT)
|
||||
// Include basic support for GPIO/keyboard only
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#elif defined(DRV_TOUCH_HANDLER)
|
||||
// touch handler class
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
#else
|
||||
|
||||
#error "Unknown driver for touch DRV_TOUCH_..."
|
||||
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// TODO: maybe those macros should be moved to one include file which is included by all drivers
|
||||
#define TOUCH_ROTATION_DATA 0x6350
|
||||
#define TOUCH_ROTATION_SWAPXY(rotation) ((( TOUCH_ROTATION_DATA >> ((rotation&0x03)*4) ) >> 2 ) & 0x01 )
|
||||
#define TOUCH_ROTATION_FLIPX(rotation) ((( TOUCH_ROTATION_DATA >> ((rotation&0x03)*4) ) >> 1 ) & 0x01 )
|
||||
#define TOUCH_ROTATION_FLIPY(rotation) ((( TOUCH_ROTATION_DATA >> ((rotation&0x03)*4) ) >> 0 ) & 0x01 )
|
||||
|
||||
// - Set any of the following to 1 to perform touch display
|
||||
// remapping functions, 0 to disable. Use DBG_TOUCH to determine which
|
||||
// remapping modes should be enabled for your display
|
||||
// - Please refer to the wiki for details:
|
||||
// https://github.com/ImpulseAdventure/GUIslice/wiki/Configure-Touch-Support
|
||||
#define ADATOUCH_SWAP_XY 0
|
||||
#define ADATOUCH_FLIP_X 0
|
||||
#define ADATOUCH_FLIP_Y 0
|
||||
|
||||
// Define the maximum number of touch events that are handled
|
||||
// per gslc_Update() call. Normally this can be set to 1 but certain
|
||||
// displays may require a greater value (eg. 30) in order to increase
|
||||
// responsiveness of the touch functionality.
|
||||
#define GSLC_TOUCH_MAX_EVT 1
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// COMMON CONFIGURATION
|
||||
// =============================================================================
|
||||
|
||||
// Error reporting
|
||||
// - Set DEBUG_ERR to 1 to enable error reporting via the Serial connection
|
||||
// - Enabling DEBUG_ERR increases FLASH memory consumption which may be
|
||||
// limited on the baseline Arduino (ATmega328P) devices. Therefore it
|
||||
// is recommended to disable DEBUG_ERR (set to 0) on baseline Arduino
|
||||
// once initial device operation confirmed to work in examples ex01 and ex02.
|
||||
//
|
||||
#if defined(__AVR__)
|
||||
#define DEBUG_ERR 1 // Debugging enabled by default
|
||||
#else
|
||||
// For all other devices, DEBUG_ERR is enabled by default.
|
||||
// Since this mode increases FLASH memory considerably, it may be
|
||||
// necessary to disable this feature.
|
||||
#define DEBUG_ERR 1 // Debugging enabled by default
|
||||
#endif
|
||||
|
||||
// Debug initialization message
|
||||
// - By default, GUIslice outputs a message in DEBUG_ERR mode
|
||||
// to indicate the initialization status, even during success.
|
||||
// - To disable the messages during successful initialization,
|
||||
// uncomment the following line.
|
||||
//#define INIT_MSG_DISABLE
|
||||
|
||||
|
||||
// Enable of optional features
|
||||
// - For memory constrained devices such as Arduino, it is best to
|
||||
// set the following features to 0 (to disable) unless they are
|
||||
// required.
|
||||
|
||||
#define GSLC_FEATURE_COMPOUND 0 // Compound elements (eg. XSelNum)
|
||||
#define GSLC_FEATURE_XGAUGE_RADIAL 0 // XGauge control with radial support
|
||||
#define GSLC_FEATURE_XGAUGE_RAMP 0 // XGauge control with ramp support
|
||||
#define GSLC_FEATURE_XTEXTBOX_EMBED 0 // XTextbox control with embedded color
|
||||
#define GSLC_FEATURE_INPUT 0 // Keyboard / GPIO input control
|
||||
|
||||
|
||||
// Enable support for SD card
|
||||
// - Set to 1 to enable, 0 to disable
|
||||
// - Note that the inclusion of the SD library consumes considerable
|
||||
// RAM and flash memory which could be problematic for Arduino models
|
||||
// with limited resources.
|
||||
#define GSLC_SD_EN 0
|
||||
|
||||
// Define buffer size for loading images from SD
|
||||
// - A larger buffer will be faster but at the cost of RAM
|
||||
#define GSLC_SD_BUFFPIXEL 50
|
||||
|
||||
|
||||
// Enable support for graphics clipping (DrvSetClipRect)
|
||||
// - Note that this will impact performance of drawing graphics primitives
|
||||
#define GSLC_CLIP_EN 1
|
||||
|
||||
// Enable for bitmap transparency and definition of color to use
|
||||
#define GSLC_BMP_TRANS_EN 1 // 1 = enabled, 0 = disabled
|
||||
#define GSLC_BMP_TRANS_RGB 0xFF,0x00,0xFF // RGB color (default:pink)
|
||||
|
||||
|
||||
// In "Local String" mode, memory within internal element array is
|
||||
// used for strings. This mode incurs a memory cost for all elements,
|
||||
// irrespective of whether strings are used or their length. This
|
||||
// mode may make string definition convenient but is not memory-efficient.
|
||||
// Therefore, it is not recommended for limited memory devices such as
|
||||
// Arduino.
|
||||
// - When using element local string storage (GSLC_LOCAL_STR=1),
|
||||
// GSLC_LOCAL_STR_LEN defines the fixed length buffer used for every element
|
||||
#define GSLC_LOCAL_STR 0 // 1=Use local strings (in element array), 0=External
|
||||
#define GSLC_LOCAL_STR_LEN 30 // Max string length of text elements
|
||||
|
||||
#define GSLC_USE_FLOAT 0 // 1=Use floating pt library, 0=Fixed-point lookup tables
|
||||
|
||||
|
||||
// Debug diagnostic modes
|
||||
// - Uncomment any of the following to enable specific debug modes
|
||||
//#define DBG_LOG // Enable debugging log output
|
||||
//#define DBG_TOUCH // Enable debugging of touch-presses
|
||||
//#define DBG_FRAME_RATE // Enable diagnostic frame rate reporting
|
||||
//#define DBG_DRAW_IMM // Enable immediate rendering of drawing primitives
|
||||
//#define DBG_DRIVER // Enable graphics driver debug reporting
|
||||
|
||||
|
||||
// =============================================================================
|
||||
// INTERNAL CONFIGURATION
|
||||
// - Users should not need to modify the following
|
||||
// =============================================================================
|
||||
|
||||
// Display device string is only used in LINUX drivers
|
||||
#define GSLC_DEV_TOUCH "" // No device path used
|
||||
|
||||
|
||||
// Define compatibility for non-AVR to call PROGMEM functions
|
||||
#if defined(__AVR__)
|
||||
#define GSLC_USE_PROGMEM 1
|
||||
#else
|
||||
#define GSLC_USE_PROGMEM 0
|
||||
#endif
|
||||
|
||||
|
||||
// =============================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_CONFIG_ARD_H_
|
191
hardware/sd_card_formatter/src/guislice/GUIslice_config_linux.h
Normal file
191
hardware/sd_card_formatter/src/guislice/GUIslice_config_linux.h
Normal file
|
@ -0,0 +1,191 @@
|
|||
#ifndef _GUISLICE_CONFIG_LINUX_H_
|
||||
#define _GUISLICE_CONFIG_LINUX_H_
|
||||
|
||||
#warning No config selected in GUIslice_config.h - resorting to defaults.
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (user configuration) for LINUX / Raspberry Pi / Beaglebone
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
// \file GUIslice_config_linux.h
|
||||
// \brief GUIslice library (user configuration) for LINUX / Raspberry Pi / Beaglebone
|
||||
|
||||
// =======================================================================
|
||||
// User Configuration
|
||||
// - This file can be modified by the user to match the
|
||||
// intended target configuration
|
||||
// - Please refer to "docs/GUIslice_config_guide.xlsx" for detailed examples
|
||||
// specific to board and display combinations
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
// Specify the graphics driver library
|
||||
// - Uncomment one of the following graphics drivers
|
||||
#define DRV_DISP_SDL1 // LINUX: SDL 1.2 library
|
||||
//#define DRV_DISP_SDL2 // LINUX: SDL 2.0 library
|
||||
|
||||
|
||||
|
||||
// Specify the touchscreen driver
|
||||
// - Uncomment one of the following touchscreen drivers
|
||||
//#define DRV_TOUCH_NONE // No touchscreen support
|
||||
//#define DRV_TOUCH_SDL // LINUX: Use SDL touch driver
|
||||
#define DRV_TOUCH_TSLIB // LINUX: Use tslib touch driver
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
// Enable of optional features
|
||||
// - For memory constrained devices such as Arduino, it is best to
|
||||
// set the following features to 0 (to disable) unless they are
|
||||
// required.
|
||||
|
||||
#define GSLC_FEATURE_COMPOUND 1 // Compound elements (eg. XSelNum)
|
||||
#define GSLC_FEATURE_XGAUGE_RADIAL 1 // XGauge control with radial support
|
||||
#define GSLC_FEATURE_XGAUGE_RAMP 1 // XGauge control with ramp support
|
||||
#define GSLC_FEATURE_XTEXTBOX_EMBED 0 // XTextbox control with embedded color
|
||||
#define GSLC_FEATURE_INPUT 1 // Keyboard / GPIO input control
|
||||
|
||||
// Error reporting
|
||||
// - Set DEBUG_ERR to 1 to enable error reporting via the console
|
||||
#define DEBUG_ERR 1 // Enable by default
|
||||
|
||||
// Debug initialization message
|
||||
// - By default, GUIslice outputs a message in DEBUG_ERR mode
|
||||
// to indicate the initialization status, even during success.
|
||||
// - To disable the messages during successful initialization,
|
||||
// uncomment the following line.
|
||||
//#define INIT_MSG_DISABLE
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
// Graphics display driver-specific additional configuration
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
// Define default device paths for framebuffer & touchscreen
|
||||
#define GSLC_DEV_FB "/dev/fb1"
|
||||
#define GSLC_DEV_TOUCH "/dev/input/touchscreen"
|
||||
#define GSLC_DEV_VID_DRV "fbcon"
|
||||
|
||||
// Enable SDL startup workaround? (1 to enable, 0 to disable)
|
||||
#define DRV_SDL_FIX_START 0
|
||||
|
||||
// Show SDL mouse (1 to show, 0 to hide)
|
||||
#define DRV_SDL_MOUSE_SHOW 0
|
||||
|
||||
#define GSLC_LOCAL_STR 1
|
||||
#define GSLC_USE_FLOAT 1
|
||||
|
||||
|
||||
#elif defined(DRV_DISP_SDL2)
|
||||
// Define default device paths for framebuffer & touchscreen
|
||||
// - The following assumes display driver (eg. fbtft) reads from fb1
|
||||
// - Raspberry Pi can support hardware acceleration onto fb0
|
||||
// - To use SDL2.0 with hardware acceleration with such displays,
|
||||
// use fb0 as the target and then run fbcp to mirror fb0 to fb1
|
||||
#define GSLC_DEV_FB "/dev/fb0"
|
||||
#define GSLC_DEV_TOUCH ""
|
||||
#define GSLC_DEV_VID_DRV "x11"
|
||||
|
||||
// Show SDL mouse (1 to show, 0 to hide)
|
||||
#define DRV_SDL_MOUSE_SHOW 0
|
||||
// Enable hardware acceleration
|
||||
#define DRV_SDL_RENDER_ACCEL 1
|
||||
|
||||
#define GSLC_LOCAL_STR 1
|
||||
#define GSLC_USE_FLOAT 1
|
||||
|
||||
|
||||
#endif // DRV_DISP_*
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
// Touch Driver-specific additional configuration
|
||||
#if defined(DRV_TOUCH_SDL)
|
||||
#define DRV_TOUCH_IN_DISP // Use the display driver (SDL) for touch events
|
||||
|
||||
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// NOTE: The GSLC_ROTATE feature is not yet supported in SDL mode
|
||||
// however, the following settings are provided for future use.
|
||||
|
||||
|
||||
// - Set any of the following to 1 to perform touch display
|
||||
// remapping functions, 0 to disable. Use DBG_TOUCH to determine which
|
||||
// remapping modes should be enabled for your display
|
||||
// - Please refer to the wiki for details:
|
||||
// https://github.com/ImpulseAdventure/GUIslice/wiki/Configure-Touch-Support
|
||||
#define ADATOUCH_SWAP_XY 0
|
||||
#define ADATOUCH_FLIP_X 0
|
||||
#define ADATOUCH_FLIP_Y 0
|
||||
|
||||
// Define the maximum number of touch events that are handled
|
||||
// per gslc_Update() call. Normally this can be set to 1 but certain
|
||||
// displays may require a greater value (eg. 30) in order to increase
|
||||
// responsiveness of the touch functionality.
|
||||
#define GSLC_TOUCH_MAX_EVT 1
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
// When using element local string storage (GSLC_LOCAL_STR=1),
|
||||
// this defines the fixed length buffer used for every element
|
||||
#define GSLC_LOCAL_STR_LEN 30 // Max string length of text elements
|
||||
|
||||
|
||||
// Debug modes
|
||||
// - Uncomment the following to enable specific debug modes
|
||||
//#define DBG_LOG // Enable debugging log output
|
||||
//#define DBG_TOUCH // Enable debugging of touch-presses
|
||||
//#define DBG_FRAME_RATE // Enable diagnostic frame rate reporting
|
||||
//#define DBG_DRAW_IMM // Enable immediate rendering of drawing primitives
|
||||
//#define DBG_DRIVER // Enable graphics driver debug reporting
|
||||
|
||||
// Enable for bitmap transparency and definition of color to use
|
||||
#define GSLC_BMP_TRANS_EN 1 // 1 = enabled, 0 = disabled
|
||||
#define GSLC_BMP_TRANS_RGB 0xFF,0x00,0xFF // RGB color (default:pink)
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------------------------
|
||||
|
||||
// Define compatibility for non-AVR to call PROGMEM functions
|
||||
#define GSLC_USE_PROGMEM 0
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_CONFIG_LINUX_H_
|
66
hardware/sd_card_formatter/src/guislice/GUIslice_drv.h
Normal file
66
hardware/sd_card_formatter/src/guislice/GUIslice_drv.h
Normal file
|
@ -0,0 +1,66 @@
|
|||
#ifndef _GUISLICE_DRV_H_
|
||||
#define _GUISLICE_DRV_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (generic driver layer include)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Generic Driver Layer
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
#include "GUIslice_drv_sdl.h"
|
||||
#elif defined(DRV_DISP_SDL2)
|
||||
#include "GUIslice_drv_sdl.h"
|
||||
#elif defined(DRV_DISP_ADAGFX) || defined(DRV_DISP_ADAGFX_AS)
|
||||
#include "GUIslice_drv_adagfx.h"
|
||||
#elif defined(DRV_DISP_TFT_ESPI)
|
||||
#include "GUIslice_drv_tft_espi.h"
|
||||
#elif defined(DRV_DISP_M5STACK)
|
||||
#include "GUIslice_drv_m5stack.h"
|
||||
#elif defined(DRV_DISP_UTFT)
|
||||
#include "GUIslice_drv_utft.h"
|
||||
#else
|
||||
#error "Driver needs to be specified in GUIslice_config_*.h (DRV_DISP_*)"
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_H_
|
||||
|
3059
hardware/sd_card_formatter/src/guislice/GUIslice_drv_adagfx.cpp
Normal file
3059
hardware/sd_card_formatter/src/guislice/GUIslice_drv_adagfx.cpp
Normal file
File diff suppressed because it is too large
Load diff
757
hardware/sd_card_formatter/src/guislice/GUIslice_drv_adagfx.h
Normal file
757
hardware/sd_card_formatter/src/guislice/GUIslice_drv_adagfx.h
Normal file
|
@ -0,0 +1,757 @@
|
|||
#ifndef _GUISLICE_DRV_ADAGFX_H_
|
||||
#define _GUISLICE_DRV_ADAGFX_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (driver layer for Adafruit-GFX)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_drv_adagfx.h
|
||||
/// \brief GUIslice library (driver layer for Adafruit-GFX)
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver Layer for Adafruit-GFX
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Determine characteristics for configured touch driver
|
||||
// - DRV_TOUCH_TYPE_EXTERNAL: TDrv* external touch APIs are enabled
|
||||
// - DRV_TOUCH_TYPE_RES: Resistive overlay
|
||||
// - DRV_TOUCH_TYPE_CAP: Capacitive overlay
|
||||
// - DRV_TOUCH_TYPE_ANALOG: Analog input
|
||||
#if defined(DRV_TOUCH_ADA_STMPE610)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_ADA_FT6206)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_CAP // Capacitive
|
||||
#elif defined(DRV_TOUCH_ADA_FT5206)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_CAP // Capacitive
|
||||
#elif defined(DRV_TOUCH_ADA_SIMPLE)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#define DRV_TOUCH_TYPE_ANALOG // Analog
|
||||
#elif defined(DRV_TOUCH_ADA_RA8875)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_ADA_RA8875_SUMO)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_XPT2046_STM)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_XPT2046_PS)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_URTOUCH)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
// Don't set DRV_TOUCH_TYPE_RES since URTouch provides its own calibration
|
||||
//#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_INPUT)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#elif defined(DRV_TOUCH_HANDLER)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#elif defined(DRV_TOUCH_NONE)
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// API support definitions
|
||||
// - These defines indicate whether the driver includes optimized
|
||||
// support for various APIs. If a define is set to 0, then the
|
||||
// GUIslice core emulation will be used instead.
|
||||
// - At the very minimum, the point draw routine must be available:
|
||||
// gslc_DrvDrawPoint()
|
||||
// =======================================================================
|
||||
|
||||
#define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint()
|
||||
|
||||
#define DRV_HAS_DRAW_POINTS 0 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 1 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 1 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 1 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 1 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 1 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 1 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
|
||||
#define DRV_OVERRIDE_TXT_ALIGN 0 ///< Driver provides text alignment
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Driver-specific overrides
|
||||
// - Some drivers have exceptions to the above support configuration
|
||||
// -----------------------------------------------------------------------
|
||||
#if defined(DRV_DISP_WAVESHARE_ILI9486)
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FRAME
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FILL
|
||||
#undef DRV_HAS_DRAW_TRI_FRAME
|
||||
#undef DRV_HAS_DRAW_TRI_FILL
|
||||
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 0
|
||||
#define DRV_HAS_DRAW_TRI_FILL 0
|
||||
|
||||
#elif defined(DRV_DISP_LCDGFX)
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FRAME
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FILL
|
||||
#undef DRV_HAS_DRAW_CIRCLE_FRAME
|
||||
#undef DRV_HAS_DRAW_CIRCLE_FILL
|
||||
#undef DRV_HAS_DRAW_TRI_FRAME
|
||||
#undef DRV_HAS_DRAW_TRI_FILL
|
||||
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 0
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 0
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 0
|
||||
#define DRV_HAS_DRAW_TRI_FILL 0
|
||||
|
||||
#elif defined(DRV_DISP_ADAGFX_RA8876)
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FRAME
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FILL
|
||||
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0
|
||||
|
||||
#elif defined(DRV_DISP_ADAGFX_RA8876_GV)
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FRAME
|
||||
#undef DRV_HAS_DRAW_RECT_ROUND_FILL
|
||||
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0
|
||||
|
||||
|
||||
#elif defined(DRV_DISP_ADAGFX_ILI9341)
|
||||
// BLIT support in library
|
||||
#undef DRV_HAS_DRAW_BMP_MEM
|
||||
#define DRV_HAS_DRAW_BMP_MEM 1
|
||||
#endif
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver-specific members
|
||||
// =======================================================================
|
||||
typedef struct {
|
||||
gslc_tsColor nColBkgnd; ///< Background color (if not image-based)
|
||||
|
||||
gslc_tsRect rClipRect; ///< Clipping rectangle
|
||||
|
||||
} gslc_tsDriver;
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Public APIs to GUIslice core library
|
||||
// - These functions define the renderer / driver-dependent
|
||||
// implementations for the core drawing operations within
|
||||
// GUIslice.
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Initialize the SDL library
|
||||
/// - Performs clean startup workaround (if enabled)
|
||||
/// - Configures video mode
|
||||
/// - Initializes font support
|
||||
///
|
||||
/// PRE:
|
||||
/// - The environment variables should be configured before
|
||||
/// calling gslc_DrvInit(). This can be done with gslc_DrvInitEnv()
|
||||
/// or manually in user function.
|
||||
///
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvInit(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTs(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Free up any members associated with the driver
|
||||
/// - Eg. renderers, windows, background surfaces, etc.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the display driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the touch driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native display driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the display driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native touch driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the touch driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Image/surface handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a bitmap (*.bmp) and create a new image resource.
|
||||
/// Transparency is enabled by GSLC_BMP_TRANS_EN
|
||||
/// through use of color (GSLC_BMP_TRANS_RGB).
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return Image pointer (surface/texture) or NULL if error
|
||||
///
|
||||
void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the background to use a bitmap image
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Configure the background to use a solid color
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB Color to use
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Set an element's normal-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Set an element's glow-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Release an image surface
|
||||
///
|
||||
/// \param[in] pvImg: Void ptr to image
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvImageDestruct(void* pvImg);
|
||||
|
||||
|
||||
///
|
||||
/// Set the clipping rectangle for future drawing updates
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pRect: Rectangular region to constrain edits
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Font handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Load a font from a resource and return pointer to it
|
||||
///
|
||||
/// \param[in] eFontRefType: Font reference type (GSLC_FONTREF_PTR for Arduino)
|
||||
/// \param[in] pvFontRef: Font reference pointer (Pointer to the GFXFont array)
|
||||
/// \param[in] nFontSz: Typeface size to use
|
||||
///
|
||||
/// \return Void ptr to driver-specific font if load was successful, NULL otherwise
|
||||
///
|
||||
const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz);
|
||||
|
||||
///
|
||||
/// Release all fonts defined in the GUI
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvFontsDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the extent (width and height) of a text string
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pFont: Ptr to Font structure
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[out] pnTxtX: Ptr to offset X of text
|
||||
/// \param[out] pnTxtY: Ptr to offset Y of text
|
||||
/// \param[out] pnTxtSzW: Ptr to width of text
|
||||
/// \param[out] pnTxtSzH: Ptr to height of text
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,
|
||||
int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a text string at the given coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nTxtX: X coordinate of top-left text string
|
||||
/// \param[in] nTxtY: Y coordinate of top-left text string
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: unused in ADAGFX, defaults to black
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Screen Management Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Force a page flip to occur. This generally copies active
|
||||
/// screen surface to the display.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPageFlipNow(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Graphics Primitives Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: X coordinate of point
|
||||
/// \param[in] nY: Y coordinate of point
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] asPt: Array of points to draw
|
||||
/// \param[in] nNumPt: Number of points in array
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a framed rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Draw a line
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: Line start (X coordinate)
|
||||
/// \param[in] nY0: Line start (Y coordinate)
|
||||
/// \param[in] nX1: Line finish (X coordinate)
|
||||
/// \param[in] nY1: Line finish (Y coordinate)
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Copy all of source image to destination screen at specified coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a monochrome bitmap from a memory array
|
||||
/// - Draw from the bitmap buffer using the foreground color
|
||||
/// defined in the header (unset bits are transparent)
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawMonoFromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY, const unsigned char *pBitmap,bool bProgMem);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a color 24-bit depth bitmap from a memory array
|
||||
/// - Note that users must convert images from their native
|
||||
/// format (eg. BMP, PNG, etc.) into a C array. Please
|
||||
/// refer to the following guide for details:
|
||||
/// https://github.com/ImpulseAdventure/GUIslice/wiki/Display-Images-from-FLASH
|
||||
/// - The converted file (c array) can then be included in the sketch.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: X coord for copy
|
||||
/// \param[in] nDstY: Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawBmp24FromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY,const unsigned char* pBitmap,bool bProgMem);
|
||||
|
||||
///
|
||||
/// Copy the background image to destination screen
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
void gslc_DrvDrawBkgnd(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using display driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the internal touch handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using external touch driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// Check for deprecated config option
|
||||
// - This check will be removed in future releases
|
||||
#if defined(DRV_TOUCH_XPT2046)
|
||||
#error "NOTE: DRV_TOUCH_XPT2046 has been renamed to DRV_TOUCH_XPT2046_STM. Please update your config."
|
||||
#endif
|
||||
|
||||
#if defined(DRV_TOUCH_TYPE_EXTERNAL)
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_TDrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the SDL_Event handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_TDrvGetTouch(gslc_tsGui* pGui, int16_t* pnX, int16_t* pnY, uint16_t* pnPress, gslc_teInputRawEvent* peInputEvent, int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Dynamic Screen rotation and Touch axes swap/flip functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Change rotation, automatically adapt touchscreen axes swap/flip
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3)
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Private Functions
|
||||
// - These functions are not included in the scope of APIs used by
|
||||
// the core GUIslice library. Instead, these functions are used
|
||||
// to support the operations within this driver layer.
|
||||
// =======================================================================
|
||||
|
||||
uint16_t gslc_DrvAdaptColorToRaw(gslc_tsColor nCol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_ADAGFX_H_
|
1071
hardware/sd_card_formatter/src/guislice/GUIslice_drv_m5stack.cpp
Normal file
1071
hardware/sd_card_formatter/src/guislice/GUIslice_drv_m5stack.cpp
Normal file
File diff suppressed because it is too large
Load diff
656
hardware/sd_card_formatter/src/guislice/GUIslice_drv_m5stack.h
Normal file
656
hardware/sd_card_formatter/src/guislice/GUIslice_drv_m5stack.h
Normal file
|
@ -0,0 +1,656 @@
|
|||
#ifndef _GUISLICE_DRV_M5STACK_H_
|
||||
#define _GUISLICE_DRV_M5STACK_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (driver layer for m5stack/M5Stack)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_drv_m5stack.h
|
||||
/// \brief GUIslice library (driver layer for M5stack)
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver Layer for m5stack/M5Stack
|
||||
// - https://github.com/m5stack/M5Stack
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Error Strings
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
extern const char GSLC_PMEM ERRSTR_NULL[];
|
||||
extern const char GSLC_PMEM ERRSTR_PXD_NULL[];
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// API support definitions
|
||||
// - These defines indicate whether the driver includes optimized
|
||||
// support for various APIs. If a define is set to 0, then the
|
||||
// GUIslice core emulation will be used instead.
|
||||
// - At the very minimum, the point draw routine must be available:
|
||||
// gslc_DrvDrawPoint()
|
||||
// =======================================================================
|
||||
|
||||
#define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint()
|
||||
|
||||
#define DRV_HAS_DRAW_POINTS 0 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 1 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 1 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 1 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 1 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 1 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 1 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
|
||||
#define DRV_OVERRIDE_TXT_ALIGN 1 ///< Driver provides text alignment
|
||||
|
||||
// =======================================================================
|
||||
// Driver-specific members
|
||||
// =======================================================================
|
||||
typedef struct {
|
||||
gslc_tsColor nColBkgnd; ///< Background color (if not image-based)
|
||||
|
||||
gslc_tsRect rClipRect; ///< Clipping rectangle
|
||||
|
||||
} gslc_tsDriver;
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Public APIs to GUIslice core library
|
||||
// - These functions define the renderer / driver-dependent
|
||||
// implementations for the core drawing operations within
|
||||
// GUIslice.
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Initialize the SDL library
|
||||
/// - Performs clean startup workaround (if enabled)
|
||||
/// - Configures video mode
|
||||
/// - Initializes font support
|
||||
///
|
||||
/// PRE:
|
||||
/// - The environment variables should be configured before
|
||||
/// calling gslc_DrvInit(). This can be done with gslc_DrvInitEnv()
|
||||
/// or manually in user function.
|
||||
///
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvInit(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTs(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Free up any members associated with the driver
|
||||
/// - Eg. renderers, windows, background surfaces, etc.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the display driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the touch driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native display driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the display driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native touch driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the touch driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Image/surface handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a bitmap (*.bmp) and create a new image resource.
|
||||
/// Transparency is enabled by GSLC_BMP_TRANS_EN
|
||||
/// through use of color (GSLC_BMP_TRANS_RGB).
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return Image pointer (surface/texture) or NULL if error
|
||||
///
|
||||
void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the background to use a bitmap image
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Configure the background to use a solid color
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB Color to use
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Set an element's normal-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Set an element's glow-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Release an image surface
|
||||
///
|
||||
/// \param[in] pvImg: Void ptr to image
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvImageDestruct(void* pvImg);
|
||||
|
||||
|
||||
///
|
||||
/// Set the clipping rectangle for future drawing updates
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pRect: Rectangular region to constrain edits
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Font handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Load a font from a resource and return pointer to it
|
||||
///
|
||||
/// \param[in] eFontRefType: Font reference type (GSLC_FONTREF_PTR for Arduino)
|
||||
/// \param[in] pvFontRef: Font reference pointer (Pointer to the GFXFont array)
|
||||
/// \param[in] nFontSz: Typeface size to use
|
||||
///
|
||||
/// \return Void ptr to driver-specific font if load was successful, NULL otherwise
|
||||
///
|
||||
const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz);
|
||||
|
||||
///
|
||||
/// Release all fonts defined in the GUI
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvFontsDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the extent (width and height) of a text string
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pFont: Ptr to Font structure
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[out] pnTxtX: Ptr to offset X of text
|
||||
/// \param[out] pnTxtY: Ptr to offset Y of text
|
||||
/// \param[out] pnTxtSzW: Ptr to width of text
|
||||
/// \param[out] pnTxtSzH: Ptr to height of text
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,
|
||||
int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a text string at the given coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nTxtX: X coordinate of top-left text string
|
||||
/// \param[in] nTxtY: Y coordinate of top-left text string
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: unused in m5stack, defaults to black
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
///
|
||||
/// Draw a text string in a bounding box using the specified alignment
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X coordinate of top-left of bounding box
|
||||
/// \param[in] nY0: Y coordinate of top-left of bounding box
|
||||
/// \param[in] nX1: X coordinate of bot-right of bounding box
|
||||
/// \param[in] nY1: Y coordinate of bot-right of bounding box
|
||||
/// \param[in] eTxtAlign: Alignment mode]
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: unused in m5stack, defaults to black
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxtAlign(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,int8_t eTxtAlign,
|
||||
gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Screen Management Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Force a page flip to occur. This generally copies active
|
||||
/// screen surface to the display.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPageFlipNow(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Graphics Primitives Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: X coordinate of point
|
||||
/// \param[in] nY: Y coordinate of point
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] asPt: Array of points to draw
|
||||
/// \param[in] nNumPt: Number of points in array
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a framed rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Draw a line
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: Line start (X coordinate)
|
||||
/// \param[in] nY0: Line start (Y coordinate)
|
||||
/// \param[in] nX1: Line finish (X coordinate)
|
||||
/// \param[in] nY1: Line finish (Y coordinate)
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Copy all of source image to destination screen at specified coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a monochrome bitmap from a memory array
|
||||
/// - Draw from the bitmap buffer using the foreground color
|
||||
/// defined in the header (unset bits are transparent)
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawMonoFromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY, const unsigned char *pBitmap,bool bProgMem);
|
||||
|
||||
///
|
||||
/// Draw a color 24-bit depth bitmap from a memory array
|
||||
/// - Note that users must convert images from their native
|
||||
/// format (eg. BMP, PNG, etc.) into a C array. Please
|
||||
/// refer to the following guide for details:
|
||||
/// https://github.com/ImpulseAdventure/GUIslice/wiki/Display-Images-from-FLASH
|
||||
/// - The converted file (c array) can then be included in the sketch.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: X coord for copy
|
||||
/// \param[in] nDstY: Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawBmp24FromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY,const unsigned char* pBitmap,bool bProgMem);
|
||||
|
||||
///
|
||||
/// Copy the background image to destination screen
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
void gslc_DrvDrawBkgnd(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using display driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#if defined(DRV_TOUCH_IN_DISP)
|
||||
// Use M5stack's integrated button handler
|
||||
|
||||
///
|
||||
/// Perform any touch-specific initialization
|
||||
/// - This function doesn't do anything in M5stack
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the internal button handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event (UNUSED)
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event (UNUSED)
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch) (UNUSED)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_IN_DISP
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Dynamic Screen rotation and Touch axes swap/flip functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Change rotation, automatically adapt touchscreen axes swap/flip
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3)
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Private Functions
|
||||
// - These functions are not included in the scope of APIs used by
|
||||
// the core GUIslice library. Instead, these functions are used
|
||||
// to support the operations within this driver layer.
|
||||
// =======================================================================
|
||||
|
||||
uint16_t gslc_DrvAdaptColorToRaw(gslc_tsColor nCol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_M5STACK_H_
|
1470
hardware/sd_card_formatter/src/guislice/GUIslice_drv_sdl.c
Normal file
1470
hardware/sd_card_formatter/src/guislice/GUIslice_drv_sdl.c
Normal file
File diff suppressed because it is too large
Load diff
722
hardware/sd_card_formatter/src/guislice/GUIslice_drv_sdl.h
Normal file
722
hardware/sd_card_formatter/src/guislice/GUIslice_drv_sdl.h
Normal file
|
@ -0,0 +1,722 @@
|
|||
#ifndef _GUISLICE_DRV_SDL_H_
|
||||
#define _GUISLICE_DRV_SDL_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (driver layer for SDL 1.2 & 2.0)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_drv_sdl.h
|
||||
/// \brief GUIslice library (driver layer for LINUX / SDL)
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver Layer for SDL
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
#include <SDL/SDL.h>
|
||||
#include <SDL/SDL_getenv.h>
|
||||
#include <SDL/SDL_ttf.h>
|
||||
#endif
|
||||
#if defined(DRV_DISP_SDL2)
|
||||
#include <SDL2/SDL.h>
|
||||
#include <SDL2/SDL_ttf.h>
|
||||
#endif
|
||||
|
||||
// Includes for optional tslib touch handling
|
||||
#if defined(DRV_TOUCH_TSLIB)
|
||||
#include "tslib.h"
|
||||
#endif
|
||||
|
||||
// =======================================================================
|
||||
// API support definitions
|
||||
// - These defines indicate whether the driver includes optimized
|
||||
// support for various APIs. If a define is set to 0, then the
|
||||
// GUIslice core emulation will be used instead.
|
||||
// - At the very minimum, the point draw routine must be available:
|
||||
// gslc_DrvDrawPoint()
|
||||
// =======================================================================
|
||||
|
||||
#define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint()
|
||||
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
#define DRV_HAS_DRAW_POINTS 1 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 0 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 0 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 0 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 0 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 0 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 0 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
#endif
|
||||
|
||||
#if defined(DRV_DISP_SDL2)
|
||||
#define DRV_HAS_DRAW_POINTS 1 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 0 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 0 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 0 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 0 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 0 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 0 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
#endif
|
||||
|
||||
#define DRV_OVERRIDE_TXT_ALIGN 0 ///< Driver provides text alignment
|
||||
|
||||
// =======================================================================
|
||||
// Driver-specific members
|
||||
// =======================================================================
|
||||
typedef struct {
|
||||
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
SDL_Surface* pSurfScreen; ///< Surface ptr for screen
|
||||
#endif
|
||||
|
||||
#if defined(DRV_DISP_SDL2)
|
||||
SDL_Window* pWind; ///< SDL2 Window
|
||||
SDL_Renderer* pRender; ///< SDL2 Rendering engine
|
||||
#endif
|
||||
|
||||
#if defined(DRV_TOUCH_TSLIB)
|
||||
struct tsdev* pTsDev; ///< Ptr to touchscreen device
|
||||
#endif
|
||||
|
||||
} gslc_tsDriver;
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Public APIs to GUIslice core library
|
||||
// - These functions define the renderer / driver-dependent
|
||||
// implementations for the core drawing operations within
|
||||
// GUIslice.
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Initialize the SDL library
|
||||
/// - Performs clean startup workaround (if enabled)
|
||||
/// - Configures video mode
|
||||
/// - Initializes font support
|
||||
///
|
||||
/// PRE:
|
||||
/// - The environment variables should be configured before
|
||||
/// calling gslc_DrvInit().
|
||||
///
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvInit(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Free up any members associated with the driver
|
||||
/// - Eg. renderers, windows, background surfaces, etc.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the display driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the touch driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native display driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the display driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native touch driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the touch driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Image/surface handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a bitmap (*.bmp) and create a new image resource.
|
||||
/// Transparency is enabled by GSLC_BMP_TRANS_EN
|
||||
/// through use of color (GSLC_BMP_TRANS_RGB).
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return Image pointer (surface/texture/path) or NULL if error
|
||||
///
|
||||
void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the background to use a bitmap image
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Configure the background to use a solid color
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB Color to use
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Set an element's normal-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Set an element's glow-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Release an image surface
|
||||
///
|
||||
/// \param[in] pvImg: Void ptr to image
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvImageDestruct(void* pvImg);
|
||||
|
||||
|
||||
///
|
||||
/// Set the clipping rectangle for future drawing updates
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pRect: Rectangular region to constrain edits
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Font handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a font from a resource and return pointer to it
|
||||
///
|
||||
/// \param[in] eFontRefType: Font reference type (GSLC_FONTREF_FNAME for SDL)
|
||||
/// \param[in] pvFontRef: Font reference pointer (Pointer to the font filename)
|
||||
/// \param[in] nFontSz: Typeface size to use
|
||||
///
|
||||
/// \return Void ptr to driver-specific font if load was successful, NULL otherwise
|
||||
///
|
||||
const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz);
|
||||
|
||||
///
|
||||
/// Release all fonts defined in the GUI
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvFontsDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the extent (width and height) of a text string
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pFont: Ptr to Font structure
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[out] pnTxtX: Ptr to offset X of text
|
||||
/// \param[out] pnTxtY: Ptr to offset Y of text
|
||||
/// \param[out] pnTxtSzW: Ptr to width of text
|
||||
/// \param[out] pnTxtSzH: Ptr to height of text
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,
|
||||
int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a text string at the given coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nTxtX: X coordinate of top-left text string
|
||||
/// \param[in] nTxtY: Y coordinate of top-left text string
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: unused in SDL, defaults to black
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Screen Management Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Force a page flip to occur. This generally copies active
|
||||
/// screen surface to the display.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPageFlipNow(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Graphics Primitives Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: X coordinate of point
|
||||
/// \param[in] nY: Y coordinate of point
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] asPt: Array of points to draw
|
||||
/// \param[in] nNumPt: Number of points in array
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a framed rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a line
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: Line start (X coordinate)
|
||||
/// \param[in] nY0: Line start (Y coordinate)
|
||||
/// \param[in] nX1: Line finish (X coordinate)
|
||||
/// \param[in] nY1: Line finish (Y coordinate)
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol);
|
||||
|
||||
|
||||
// TODO: Add DrvDrawFrameCircle()
|
||||
// TODO: Add DrvDrawFillCircle()
|
||||
// TODO: Add DrvDrawFrameTriangle()
|
||||
// TODO: Add DrvDrawFillTriangle()
|
||||
|
||||
|
||||
///
|
||||
/// Copy all of source image to destination screen at specified coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
// TODO: Add DrvDrawMonoFromMem()
|
||||
// TODO: Add DrvDrawBmp24FromMem()
|
||||
|
||||
|
||||
///
|
||||
/// Copy the background image to destination screen
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
void gslc_DrvDrawBkgnd(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Get the last touch event from the SDL_Event handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Dynamic Screen rotation and Touch axes swap/flip functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Change rotation, automatically adapt touchscreen axes swap/flip
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3)
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Private Functions
|
||||
// - These functions are not included in the scope of APIs used by
|
||||
// the core GUIslice library. Instead, these functions are used
|
||||
// to support the operations within this driver layer.
|
||||
// =======================================================================
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Ensure SDL initializes cleanly to workaround
|
||||
/// possible issues if previous SDL application
|
||||
/// failed to close down gracefully.
|
||||
///
|
||||
/// \param[in] sTTY: Terminal device (eg. "/dev/tty0")
|
||||
///
|
||||
/// \return true if success
|
||||
///
|
||||
bool gslc_DrvCleanStart(const char* sTTY);
|
||||
|
||||
|
||||
///
|
||||
/// Report driver debug info (before initialization)
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvReportInfoPre();
|
||||
|
||||
///
|
||||
/// Report driver debug info (after initialization)
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvReportInfoPost();
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private Conversion Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Translate a gslc_tsRect into an SDL_Rect
|
||||
///
|
||||
/// \param[in] rRect: gslc_tsRect
|
||||
///
|
||||
/// \return Converted SDL_Rect
|
||||
///
|
||||
SDL_Rect gslc_DrvAdaptRect(gslc_tsRect rRect);
|
||||
|
||||
///
|
||||
/// Translate a gslc_tsColor into an SDL_Color
|
||||
///
|
||||
/// \param[in] sCol: gslc_tsColor
|
||||
///
|
||||
/// \return Converted SDL_Color
|
||||
///
|
||||
SDL_Color gslc_DrvAdaptColor(gslc_tsColor sCol);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private Drawing Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#if defined(DRV_DISP_SDL1)
|
||||
///
|
||||
/// Lock an SDL surface so that direct pixel manipulation
|
||||
/// can be done safely. This function is called before any
|
||||
/// direct pixel updates.
|
||||
///
|
||||
/// POST:
|
||||
/// - Primary screen surface is locked
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_DrvScreenLock(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Unlock the SDL surface after pixel manipulation is
|
||||
/// complete. This function is called after all pixel updates
|
||||
/// are done.
|
||||
///
|
||||
/// POST:
|
||||
/// - Primary screen surface is unlocked
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvScreenUnlock(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Convert an RGB color triplet into the surface pixel value.
|
||||
/// This is called to produce the native pixel value required by
|
||||
/// the raw pixel manipulation routines.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB value for conversion
|
||||
///
|
||||
/// \return A pixel value for the current screen format
|
||||
///
|
||||
uint32_t gslc_DrvAdaptColorRaw(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Get the pixel at (X,Y) from the active screen
|
||||
///
|
||||
/// PRE:
|
||||
/// - Screen surface must be locked
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: Pixel X coordinate
|
||||
/// \param[in] nY: Pixel Y coordinate
|
||||
///
|
||||
/// \return Pixel color value from the coordinate or 0 if error
|
||||
///
|
||||
uint32_t gslc_DrvDrawGetPixelRaw(gslc_tsGui* pGui,int16_t nX,int16_t nY);
|
||||
|
||||
|
||||
///
|
||||
/// Set a pixel on the active screen to the given color
|
||||
///
|
||||
/// PRE:
|
||||
/// - Screen surface must be locked
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: Pixel X coordinate to set
|
||||
/// \param[in] nY: Pixel Y coordinate to set
|
||||
/// \param[in] nPixelCol: Raw color pixel value to assign
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawSetPixelRaw(gslc_tsGui* pGui,int16_t nX,int16_t nY,uint32_t nPixelCol);
|
||||
|
||||
///
|
||||
/// Copy one image region to another.
|
||||
/// - This is typically used to copy an image to the main screen surface
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: Destination X coordinate of copy
|
||||
/// \param[in] nY: Destination Y coordinate of copy
|
||||
/// \param[in] pvSrc: Void Ptr to source surface (eg. a loaded image)
|
||||
/// \param[in] pvDest: Void Ptr to destination surface (typically the screen)
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPasteSurface(gslc_tsGui* pGui,int16_t nX, int16_t nY, void* pvSrc, void* pvDest);
|
||||
|
||||
#endif // DRV_DISP_SDL1
|
||||
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Private Touchscreen Functions (if using SDL)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touchscreen Functions (if using tslib)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#if defined(DRV_TOUCH_TSLIB)
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_TDrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the tslib handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, >0 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return non-zero if an event was detected or 0 otherwise
|
||||
///
|
||||
bool gslc_TDrvGetTouch(gslc_tsGui* pGui, int16_t* pnX, int16_t* pnY, uint16_t* pnPress, gslc_teInputRawEvent* peInputEvent, int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_TSLIB
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_SDL_H_
|
2188
hardware/sd_card_formatter/src/guislice/GUIslice_drv_tft_espi.cpp
Normal file
2188
hardware/sd_card_formatter/src/guislice/GUIslice_drv_tft_espi.cpp
Normal file
File diff suppressed because it is too large
Load diff
755
hardware/sd_card_formatter/src/guislice/GUIslice_drv_tft_espi.h
Normal file
755
hardware/sd_card_formatter/src/guislice/GUIslice_drv_tft_espi.h
Normal file
|
@ -0,0 +1,755 @@
|
|||
#ifndef _GUISLICE_DRV_TFT_ESPI_H_
|
||||
#define _GUISLICE_DRV_TFT_ESPI_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (driver layer for bodmer/TFT_eSPI)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_drv_tft_espi.h
|
||||
/// \brief GUIslice library (driver layer for TFT-eSPI)
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver Layer for bodmer/TFT_eSPI
|
||||
// - https://github.com/Bodmer/TFT_eSPI
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Determine characteristics for configured touch driver
|
||||
// - DRV_TOUCH_TYPE_EXTERNAL: TDrv* external touch APIs are enabled
|
||||
// - DRV_TOUCH_TYPE_RES: Resistive overlay
|
||||
// - DRV_TOUCH_TYPE_CAP: Capacitive overlay
|
||||
// - DRV_TOUCH_TYPE_ANALOG: Analog input
|
||||
#if defined(DRV_TOUCH_ADA_STMPE610)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_ADA_FT6206)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_CAP // Capacitive
|
||||
#elif defined(DRV_TOUCH_ADA_SIMPLE)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#define DRV_TOUCH_TYPE_ANALOG // Analog
|
||||
#elif defined(DRV_TOUCH_XPT2046_STM)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_XPT2046_PS)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_TFT_ESPI)
|
||||
#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_INPUT)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#elif defined(DRV_TOUCH_HANDLER)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#elif defined(DRV_TOUCH_NONE)
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
// Additional defines
|
||||
// - Provide default if not in config file
|
||||
#if !defined(GSLC_SPIFFS_EN)
|
||||
#define GSLC_SPIFFS_EN 0
|
||||
#endif // GSLC_SPIFFS_EN
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// API support definitions
|
||||
// - These defines indicate whether the driver includes optimized
|
||||
// support for various APIs. If a define is set to 0, then the
|
||||
// GUIslice core emulation will be used instead.
|
||||
// - At the very minimum, the point draw routine must be available:
|
||||
// gslc_DrvDrawPoint()
|
||||
// =======================================================================
|
||||
|
||||
#define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint()
|
||||
|
||||
#define DRV_HAS_DRAW_POINTS 0 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 1 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 1 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 1 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 1 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 1 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 1 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
|
||||
#define DRV_OVERRIDE_TXT_ALIGN 1 ///< Driver provides text alignment
|
||||
|
||||
// =======================================================================
|
||||
// Driver-specific members
|
||||
// =======================================================================
|
||||
typedef struct {
|
||||
gslc_tsColor nColBkgnd; ///< Background color (if not image-based)
|
||||
|
||||
gslc_tsRect rClipRect; ///< Clipping rectangle
|
||||
|
||||
} gslc_tsDriver;
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Public APIs to GUIslice core library
|
||||
// - These functions define the renderer / driver-dependent
|
||||
// implementations for the core drawing operations within
|
||||
// GUIslice.
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Initialize the SDL library
|
||||
/// - Performs clean startup workaround (if enabled)
|
||||
/// - Configures video mode
|
||||
/// - Initializes font support
|
||||
///
|
||||
/// PRE:
|
||||
/// - The environment variables should be configured before
|
||||
/// calling gslc_DrvInit(). This can be done with gslc_DrvInitEnv()
|
||||
/// or manually in user function.
|
||||
///
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvInit(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTs(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Free up any members associated with the driver
|
||||
/// - Eg. renderers, windows, background surfaces, etc.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the display driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the touch driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native display driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the display driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native touch driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the touch driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Image/surface handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a bitmap (*.bmp) and create a new image resource.
|
||||
/// Transparency is enabled by GSLC_BMP_TRANS_EN
|
||||
/// through use of color (GSLC_BMP_TRANS_RGB).
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return Image pointer (surface/texture) or NULL if error
|
||||
///
|
||||
void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the background to use a bitmap image
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Configure the background to use a solid color
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB Color to use
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Set an element's normal-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Set an element's glow-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Release an image surface
|
||||
///
|
||||
/// \param[in] pvImg: Void ptr to image
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvImageDestruct(void* pvImg);
|
||||
|
||||
|
||||
///
|
||||
/// Set the clipping rectangle for future drawing updates
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pRect: Rectangular region to constrain edits
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Font handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Load a font from a resource and return pointer to it
|
||||
///
|
||||
/// \param[in] eFontRefType: Font reference type:
|
||||
/// - GSLC_FONTREF_PTR for Standard TFT_eSPI Fonts
|
||||
/// - GSLC_FONTREF_FNAME for antialiased Font in SPIFFS
|
||||
/// \param[in] pvFontRef: Font reference pointer / SPIFFS font filename without ext.
|
||||
/// \param[in] nFontSz: Typeface size to use, ignored for SPIFFS font
|
||||
///
|
||||
/// \return Void ptr to driver-specific font if load was successful, NULL otherwise
|
||||
///
|
||||
const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz);
|
||||
|
||||
///
|
||||
/// Release all fonts defined in the GUI
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvFontsDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the extent (width and height) of a text string
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pFont: Ptr to Font structure
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[out] pnTxtX: Ptr to offset X of text
|
||||
/// \param[out] pnTxtY: Ptr to offset Y of text
|
||||
/// \param[out] pnTxtSzW: Ptr to width of text
|
||||
/// \param[out] pnTxtSzH: Ptr to height of text
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,
|
||||
int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a text string at the given coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nTxtX: X coordinate of top-left text string
|
||||
/// \param[in] nTxtY: Y coordinate of top-left text string
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: Color of Background for antialias blending
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
///
|
||||
/// Draw a text string in a bounding box using the specified alignment
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X coordinate of top-left of bounding box
|
||||
/// \param[in] nY0: Y coordinate of top-left of bounding box
|
||||
/// \param[in] nX1: X coordinate of bot-right of bounding box
|
||||
/// \param[in] nY1: Y coordinate of bot-right of bounding box
|
||||
/// \param[in] eTxtAlign: Alignment mode]
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: Color of Background for antialias blending
|
||||
//
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxtAlign(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,int8_t eTxtAlign,
|
||||
gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Screen Management Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Force a page flip to occur. This generally copies active
|
||||
/// screen surface to the display.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPageFlipNow(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Graphics Primitives Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: X coordinate of point
|
||||
/// \param[in] nY: Y coordinate of point
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] asPt: Array of points to draw
|
||||
/// \param[in] nNumPt: Number of points in array
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a framed rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Draw a line
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: Line start (X coordinate)
|
||||
/// \param[in] nY0: Line start (Y coordinate)
|
||||
/// \param[in] nX1: Line finish (X coordinate)
|
||||
/// \param[in] nY1: Line finish (Y coordinate)
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Copy all of source image to destination screen at specified coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a monochrome bitmap from a memory array
|
||||
/// - Draw from the bitmap buffer using the foreground color
|
||||
/// defined in the header (unset bits are transparent)
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawMonoFromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY, const unsigned char *pBitmap,bool bProgMem);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a color 24-bit depth bitmap from a memory array
|
||||
/// - Note that users must convert images from their native
|
||||
/// format (eg. BMP, PNG, etc.) into a C array. Please
|
||||
/// refer to the following guide for details:
|
||||
/// https://github.com/ImpulseAdventure/GUIslice/wiki/Display-Images-from-FLASH
|
||||
/// - The converted file (c array) can then be included in the sketch.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: X coord for copy
|
||||
/// \param[in] nDstY: Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawBmp24FromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY,const unsigned char* pBitmap,bool bProgMem);
|
||||
|
||||
#if (GSLC_SPIFFS_EN)
|
||||
///
|
||||
/// This routine uses TFT_eFEX library to draw a BMP file stored in SPIFFS file system
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawBmpFromFile(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// This routine uses TFT_eFEX library to draw a JPEG file stored in SPIFFS file system
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawJpegFromFile(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
#endif // end GSLC_SPIFFS_EN
|
||||
|
||||
///
|
||||
/// Copy the background image to destination screen
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
void gslc_DrvDrawBkgnd(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using display driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
#if defined(DRV_TOUCH_IN_DISP)
|
||||
// Use TFT_eSPI's integrated XPT2046 touch driver
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the internal XPT2046 touch handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_IN_DISP
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using external touch driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
// Check for deprecated config option
|
||||
// - This check will be removed in future releases
|
||||
#if defined(DRV_TOUCH_XPT2046)
|
||||
#error "NOTE: DRV_TOUCH_XPT2046 has been renamed to DRV_TOUCH_XPT2046_STM. Please update your config."
|
||||
#endif
|
||||
|
||||
#if defined(DRV_TOUCH_TYPE_EXTERNAL)
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_TDrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the SDL_Event handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_TDrvGetTouch(gslc_tsGui* pGui, int16_t* pnX, int16_t* pnY, uint16_t* pnPress, gslc_teInputRawEvent* peInputEvent, int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Dynamic Screen rotation and Touch axes swap/flip functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Change rotation, automatically adapt touchscreen axes swap/flip
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3)
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Private Functions
|
||||
// - These functions are not included in the scope of APIs used by
|
||||
// the core GUIslice library. Instead, these functions are used
|
||||
// to support the operations within this driver layer.
|
||||
// =======================================================================
|
||||
|
||||
uint16_t gslc_DrvAdaptColorToRaw(gslc_tsColor nCol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_TFT_ESPI_H_
|
1361
hardware/sd_card_formatter/src/guislice/GUIslice_drv_utft.cpp
Normal file
1361
hardware/sd_card_formatter/src/guislice/GUIslice_drv_utft.cpp
Normal file
File diff suppressed because it is too large
Load diff
672
hardware/sd_card_formatter/src/guislice/GUIslice_drv_utft.h
Normal file
672
hardware/sd_card_formatter/src/guislice/GUIslice_drv_utft.h
Normal file
|
@ -0,0 +1,672 @@
|
|||
#ifndef _GUISLICE_DRV_UTFT_H_
|
||||
#define _GUISLICE_DRV_UTFT_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (driver layer for UTFT)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_drv_utft.h
|
||||
/// \brief GUIslice library (driver layer for UTFT)
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Driver Layer for UTFT
|
||||
// =======================================================================
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
|
||||
// Determine characteristics for configured touch driver
|
||||
// - DRV_TOUCH_TYPE_EXTERNAL: TDrv* external touch APIs are enabled
|
||||
// - DRV_TOUCH_TYPE_RES: Resistive overlay
|
||||
// - DRV_TOUCH_TYPE_CAP: Capacitive overlay
|
||||
// - DRV_TOUCH_TYPE_ANALOG: Analog input
|
||||
#if defined(DRV_TOUCH_URTOUCH)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
// Don't set DRV_TOUCH_TYPE_RES since URTouch provides its own calibration
|
||||
//#define DRV_TOUCH_TYPE_RES // Resistive
|
||||
#elif defined(DRV_TOUCH_INPUT)
|
||||
#define DRV_TOUCH_TYPE_EXTERNAL
|
||||
#elif defined(DRV_TOUCH_NONE)
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// API support definitions
|
||||
// - These defines indicate whether the driver includes optimized
|
||||
// support for various APIs. If a define is set to 0, then the
|
||||
// GUIslice core emulation will be used instead.
|
||||
// - At the very minimum, the point draw routine must be available:
|
||||
// gslc_DrvDrawPoint()
|
||||
// =======================================================================
|
||||
|
||||
#define DRV_HAS_DRAW_POINT 1 ///< Support gslc_DrvDrawPoint()
|
||||
|
||||
#define DRV_HAS_DRAW_POINTS 0 ///< Support gslc_DrvDrawPoints()
|
||||
#define DRV_HAS_DRAW_LINE 1 ///< Support gslc_DrvDrawLine()
|
||||
#define DRV_HAS_DRAW_RECT_FRAME 1 ///< Support gslc_DrvDrawFrameRect()
|
||||
#define DRV_HAS_DRAW_RECT_FILL 1 ///< Support gslc_DrvDrawFillRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FRAME 1 ///< Support gslc_DrvDrawFrameRoundRect()
|
||||
#define DRV_HAS_DRAW_RECT_ROUND_FILL 1 ///< Support gslc_DrvDrawFillRoundRect()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FRAME 1 ///< Support gslc_DrvDrawFrameCircle()
|
||||
#define DRV_HAS_DRAW_CIRCLE_FILL 1 ///< Support gslc_DrvDrawFillCircle()
|
||||
#define DRV_HAS_DRAW_TRI_FRAME 0 ///< Support gslc_DrvDrawFrameTriangle()
|
||||
#define DRV_HAS_DRAW_TRI_FILL 0 ///< Support gslc_DrvDrawFillTriangle()
|
||||
#define DRV_HAS_DRAW_TEXT 1 ///< Support gslc_DrvDrawTxt()
|
||||
#define DRV_HAS_DRAW_BMP_MEM 0 ///< Support gslc_DrvDrawBmp24FromMem()
|
||||
|
||||
#define DRV_OVERRIDE_TXT_ALIGN 0 ///< Driver provides text alignment
|
||||
|
||||
// =======================================================================
|
||||
// Driver-specific members
|
||||
// =======================================================================
|
||||
typedef struct {
|
||||
gslc_tsColor nColBkgnd; ///< Background color (if not image-based)
|
||||
|
||||
gslc_tsRect rClipRect; ///< Clipping rectangle
|
||||
|
||||
} gslc_tsDriver;
|
||||
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Public APIs to GUIslice core library
|
||||
// - These functions define the renderer / driver-dependent
|
||||
// implementations for the core drawing operations within
|
||||
// GUIslice.
|
||||
// =======================================================================
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Configuration Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Initialize the SDL library
|
||||
/// - Performs clean startup workaround (if enabled)
|
||||
/// - Configures video mode
|
||||
/// - Initializes font support
|
||||
///
|
||||
/// PRE:
|
||||
/// - The environment variables should be configured before
|
||||
/// calling gslc_DrvInit(). This can be done with gslc_DrvInitEnv()
|
||||
/// or manually in user function.
|
||||
///
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvInit(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTs(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Free up any members associated with the driver
|
||||
/// - Eg. renderers, windows, background surfaces, etc.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the display driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameDisp(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the touch driver name
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return String containing driver name
|
||||
///
|
||||
const char* gslc_DrvGetNameTouch(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native display driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the display driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverDisp(gslc_tsGui* pGui);
|
||||
|
||||
///
|
||||
/// Get the native touch driver instance
|
||||
/// - This can be useful to access special commands
|
||||
/// available in the selected driver.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return Void pointer to the touch driver instance.
|
||||
/// This pointer should be typecast to the particular
|
||||
/// driver being used. If no driver was created then
|
||||
/// this function will return NULL.
|
||||
///
|
||||
void* gslc_DrvGetDriverTouch(gslc_tsGui* pGui);
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Image/surface handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
///
|
||||
/// Load a bitmap (*.bmp) and create a new image resource.
|
||||
/// Transparency is enabled by GSLC_BMP_TRANS_EN
|
||||
/// through use of color (GSLC_BMP_TRANS_RGB).
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return Image pointer (surface/texture) or NULL if error
|
||||
///
|
||||
void* gslc_DrvLoadImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the background to use a bitmap image
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndImage(gslc_tsGui* pGui,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Configure the background to use a solid color
|
||||
/// - The background is used when redrawing the entire page
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nCol: RGB Color to use
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvSetBkgndColor(gslc_tsGui* pGui,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Set an element's normal-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageNorm(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
///
|
||||
/// Set an element's glow-state image
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElem: Pointer to Element to update
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetElemImageGlow(gslc_tsGui* pGui,gslc_tsElem* pElem,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Release an image surface
|
||||
///
|
||||
/// \param[in] pvImg: Void ptr to image
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvImageDestruct(void* pvImg);
|
||||
|
||||
|
||||
///
|
||||
/// Set the clipping rectangle for future drawing updates
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pRect: Rectangular region to constrain edits
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvSetClipRect(gslc_tsGui* pGui,gslc_tsRect* pRect);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Font handling Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Load a font from a resource and return pointer to it
|
||||
///
|
||||
/// \param[in] eFontRefType: Font reference type (GSLC_FONTREF_PTR for Arduino)
|
||||
/// \param[in] pvFontRef: Font reference pointer (Pointer to the GFXFont array)
|
||||
/// \param[in] nFontSz: Typeface size to use
|
||||
///
|
||||
/// \return Void ptr to driver-specific font if load was successful, NULL otherwise
|
||||
///
|
||||
const void* gslc_DrvFontAdd(gslc_teFontRefType eFontRefType,const void* pvFontRef,uint16_t nFontSz);
|
||||
|
||||
///
|
||||
/// Release all fonts defined in the GUI
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvFontsDestruct(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
///
|
||||
/// Get the extent (width and height) of a text string
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pFont: Ptr to Font structure
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[out] pnTxtX: Ptr to offset X of text
|
||||
/// \param[out] pnTxtY: Ptr to offset Y of text
|
||||
/// \param[out] pnTxtSzW: Ptr to width of text
|
||||
/// \param[out] pnTxtSzH: Ptr to height of text
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvGetTxtSize(gslc_tsGui* pGui,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,
|
||||
int16_t* pnTxtX,int16_t* pnTxtY,uint16_t* pnTxtSzW,uint16_t* pnTxtSzH);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a text string at the given coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nTxtX: X coordinate of top-left text string
|
||||
/// \param[in] nTxtY: Y coordinate of top-left text string
|
||||
/// \param[in] pFont: Ptr to Font
|
||||
/// \param[in] pStr: String to display
|
||||
/// \param[in] eTxtFlags: Flags associated with text string
|
||||
/// \param[in] colTxt: Color to draw text
|
||||
/// \param[in] colBg: unused in ADAGFX, defaults to black
|
||||
///
|
||||
/// \return true if success, false if failure
|
||||
///
|
||||
bool gslc_DrvDrawTxt(gslc_tsGui* pGui,int16_t nTxtX,int16_t nTxtY,gslc_tsFont* pFont,const char* pStr,gslc_teTxtFlags eTxtFlags,gslc_tsColor colTxt,gslc_tsColor colBg);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Screen Management Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Force a page flip to occur. This generally copies active
|
||||
/// screen surface to the display.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvPageFlipNow(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Graphics Primitives Functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX: X coordinate of point
|
||||
/// \param[in] nY: Y coordinate of point
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoint(gslc_tsGui* pGui,int16_t nX,int16_t nY,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a point
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] asPt: Array of points to draw
|
||||
/// \param[in] nNumPt: Number of points in array
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawPoints(gslc_tsGui* pGui,gslc_tsPt* asPt,uint16_t nNumPt,gslc_tsColor nCol);
|
||||
|
||||
///
|
||||
/// Draw a framed rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRect(gslc_tsGui* pGui,gslc_tsRect rRect,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to frame
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled rounded rectangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] rRect: Rectangular region to fill
|
||||
/// \param[in] nRadius: Radius for rounded corners
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillRoundRect(gslc_tsGui* pGui,gslc_tsRect rRect,int16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
|
||||
///
|
||||
/// Draw a line
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: Line start (X coordinate)
|
||||
/// \param[in] nY0: Line start (Y coordinate)
|
||||
/// \param[in] nX1: Line finish (X coordinate)
|
||||
/// \param[in] nY1: Line finish (Y coordinate)
|
||||
/// \param[in] nCol: Color RGB value to draw
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawLine(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,int16_t nX1,int16_t nY1,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled circle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nMidX: Center of circle (X coordinate)
|
||||
/// \param[in] nMidY: Center of circle (Y coordinate)
|
||||
/// \param[in] nRadius: Radius of circle
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillCircle(gslc_tsGui* pGui,int16_t nMidX,int16_t nMidY,uint16_t nRadius,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a framed triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to frame
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFrameTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a filled triangle
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nX0: X Coordinate #1
|
||||
/// \param[in] nY0: Y Coordinate #1
|
||||
/// \param[in] nX1: X Coordinate #2
|
||||
/// \param[in] nY1: Y Coordinate #2
|
||||
/// \param[in] nX2: X Coordinate #3
|
||||
/// \param[in] nY2: Y Coordinate #3
|
||||
/// \param[in] nCol: Color RGB value to fill
|
||||
///
|
||||
/// \return true if success, false if error
|
||||
///
|
||||
bool gslc_DrvDrawFillTriangle(gslc_tsGui* pGui,int16_t nX0,int16_t nY0,
|
||||
int16_t nX1,int16_t nY1,int16_t nX2,int16_t nY2,gslc_tsColor nCol);
|
||||
|
||||
|
||||
///
|
||||
/// Copy all of source image to destination screen at specified coordinate
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] sImgRef: Image reference
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
bool gslc_DrvDrawImage(gslc_tsGui* pGui,int16_t nDstX,int16_t nDstY,gslc_tsImgRef sImgRef);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a monochrome bitmap from a memory array
|
||||
/// - Draw from the bitmap buffer using the foreground color
|
||||
/// defined in the header (unset bits are transparent)
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: Destination X coord for copy
|
||||
/// \param[in] nDstY: Destination Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawMonoFromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY, const unsigned char *pBitmap,bool bProgMem);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a color 24-bit depth bitmap from a memory array
|
||||
/// - Note that users must convert images from their native
|
||||
/// format (eg. BMP, PNG, etc.) into a C array. Please
|
||||
/// refer to the following guide for details:
|
||||
/// https://github.com/ImpulseAdventure/GUIslice/wiki/Display-Images-from-FLASH
|
||||
/// - The converted file (c array) can then be included in the sketch.
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nDstX: X coord for copy
|
||||
/// \param[in] nDstY: Y coord for copy
|
||||
/// \param[in] pBitmap: Pointer to bitmap buffer
|
||||
/// \param[in] bProgMem: Bitmap is stored in Flash if true, RAM otherwise
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_DrvDrawBmp24FromMem(gslc_tsGui* pGui,int16_t nDstX, int16_t nDstY,const unsigned char* pBitmap,bool bProgMem);
|
||||
|
||||
///
|
||||
/// Copy the background image to destination screen
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
///
|
||||
/// \return true if success, false if fail
|
||||
///
|
||||
void gslc_DrvDrawBkgnd(gslc_tsGui* pGui);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using display driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the internal touch handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_DrvGetTouch(gslc_tsGui* pGui,int16_t* pnX,int16_t* pnY,uint16_t* pnPress,gslc_teInputRawEvent* peInputEvent,int16_t* pnInputVal);
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Touch Functions (if using external touch driver library)
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
|
||||
#if defined(DRV_TOUCH_TYPE_EXTERNAL)
|
||||
///
|
||||
/// Perform any touchscreen-specific initialization
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] acDev: Device path to touchscreen
|
||||
/// eg. "/dev/input/touchscreen"
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_TDrvInitTouch(gslc_tsGui* pGui,const char* acDev);
|
||||
|
||||
|
||||
///
|
||||
/// Get the last touch event from the SDL_Event handler
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[out] pnX: Ptr to X coordinate of last touch event
|
||||
/// \param[out] pnY: Ptr to Y coordinate of last touch event
|
||||
/// \param[out] pnPress: Ptr to Pressure level of last touch event (0 for none, 1 for touch)
|
||||
/// \param[out] peInputEvent Indication of event type
|
||||
/// \param[out] pnInputVal Additional data for event type
|
||||
///
|
||||
/// \return true if an event was detected or false otherwise
|
||||
///
|
||||
bool gslc_TDrvGetTouch(gslc_tsGui* pGui, int16_t* pnX, int16_t* pnY, uint16_t* pnPress, gslc_teInputRawEvent* peInputEvent, int16_t* pnInputVal);
|
||||
|
||||
#endif // DRV_TOUCH_*
|
||||
|
||||
|
||||
// -----------------------------------------------------------------------
|
||||
// Dynamic Screen rotation and Touch axes swap/flip functions
|
||||
// -----------------------------------------------------------------------
|
||||
|
||||
///
|
||||
/// Change rotation, automatically adapt touchscreen axes swap/flip
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nRotation: Screen Rotation value (0, 1, 2 or 3)
|
||||
///
|
||||
/// \return true if successful
|
||||
///
|
||||
bool gslc_DrvRotate(gslc_tsGui* pGui, uint8_t nRotation);
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// Private Functions
|
||||
// - These functions are not included in the scope of APIs used by
|
||||
// the core GUIslice library. Instead, these functions are used
|
||||
// to support the operations within this driver layer.
|
||||
// =======================================================================
|
||||
|
||||
uint16_t gslc_DrvAdaptColorToRaw(gslc_tsColor nCol);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_DRV_ADAGFX_H_
|
52
hardware/sd_card_formatter/src/guislice/GUIslice_ex.h
Normal file
52
hardware/sd_card_formatter/src/guislice/GUIslice_ex.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
#ifndef _GUISLICE_EX_H_
|
||||
#define _GUISLICE_EX_H_
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (extensions)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file GUIslice_ex.h
|
||||
|
||||
// Provide backwards compatibility until we have removed GUIslice_ex
|
||||
#include "XCheckbox.h"
|
||||
#include "XGauge.h"
|
||||
#include "XGraph.h"
|
||||
#include "XSelNum.h"
|
||||
#include "XSlider.h"
|
||||
#include "XTextbox.h"
|
||||
|
||||
// Warn users that they should update their includes
|
||||
// #warning "NOTE: Please replace `GUIslice_ex` per https://github.com/ImpulseAdventure/GUIslice/wiki/Note-_-Include-Extended-Elements"
|
||||
|
||||
|
||||
#endif // _GUISLICE_EX_H_
|
||||
|
119
hardware/sd_card_formatter/src/guislice/GUIslice_th.cpp
Normal file
119
hardware/sd_card_formatter/src/guislice/GUIslice_th.cpp
Normal file
|
@ -0,0 +1,119 @@
|
|||
// Abstract touch handler (TH) class
|
||||
// This is the abstract base class for creating specific touch handlers
|
||||
// The touch handler performs the adaption in between the GUIslice framework and any touch driver
|
||||
// The touch handler used is specified in the main program by calling gslc_InitTouchHandler(&touchHandler);
|
||||
|
||||
/// \file GUIslice_th.cpp
|
||||
|
||||
#include "GUIslice_th.h"
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Point x,y,z Class for usage in the touch handler
|
||||
|
||||
THPoint::THPoint(void) {
|
||||
x = y = z = 0;
|
||||
}
|
||||
|
||||
THPoint::THPoint(uint16_t x0, uint16_t y0, uint16_t z0) {
|
||||
x = x0;
|
||||
y = y0;
|
||||
z = z0;
|
||||
}
|
||||
|
||||
bool THPoint::operator==(THPoint p1) {
|
||||
return ((p1.x == x) && (p1.y == y) && (p1.z == z));
|
||||
}
|
||||
|
||||
bool THPoint::operator!=(THPoint p1) {
|
||||
return ((p1.x != x) || (p1.y != y) || (p1.z != z));
|
||||
}
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Abstract TouchHandler - you have to inherit this
|
||||
|
||||
void TouchHandler::setSize(uint16_t _disp_xSize, uint16_t _disp_ySize)
|
||||
{
|
||||
disp_xSize = _disp_xSize;
|
||||
disp_ySize = _disp_ySize;
|
||||
}
|
||||
|
||||
void TouchHandler::setCalibration(uint16_t _ts_xMin, uint16_t _ts_xMax, uint16_t _ts_yMin, uint16_t _ts_yMax)
|
||||
{
|
||||
ts_xMin = _ts_xMin;
|
||||
ts_xMax = _ts_xMax;
|
||||
ts_yMin = _ts_yMin;
|
||||
ts_yMax = _ts_yMax;
|
||||
}
|
||||
|
||||
void TouchHandler::setSwapFlip(bool _swapXY,bool _flipX,bool _flipY)
|
||||
{
|
||||
swapXY = _swapXY;
|
||||
flipX = _flipX;
|
||||
flipY = _flipY;
|
||||
}
|
||||
|
||||
THPoint TouchHandler::scale(THPoint pIn)
|
||||
{
|
||||
THPoint pOut;
|
||||
|
||||
pOut.x = map(pIn.x, ts_xMin,ts_xMax, 0,disp_xSize);
|
||||
pOut.y = map(pIn.y, ts_yMin,ts_yMax, 0,disp_ySize);
|
||||
pOut.z = pIn.z;
|
||||
|
||||
pOut.x = constrain(pOut.x,0,disp_xSize-1);
|
||||
pOut.y = constrain(pOut.y,0,disp_ySize-1);
|
||||
pOut.z = constrain(pOut.z,0,4095);
|
||||
|
||||
if (swapXY)
|
||||
{
|
||||
uint16_t x = pOut.x;
|
||||
pOut.x = pOut.y;
|
||||
pOut.y = x;
|
||||
}
|
||||
|
||||
if (flipX)
|
||||
pOut.x = ( (!swapXY) ? disp_xSize-1 : disp_ySize-1 ) - pOut.x;
|
||||
|
||||
if (flipY)
|
||||
pOut.y = ( (!swapXY) ? disp_ySize-1 : disp_xSize-1 ) - pOut.y;
|
||||
|
||||
//Serial.print("disp_xSize= ");Serial.println(disp_xSize);
|
||||
|
||||
return pOut;
|
||||
}
|
||||
|
||||
|
||||
// overwrite this with your code to add initialisation of the touch driver used
|
||||
void TouchHandler::begin(void) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// overwrite this with your code to return the scaled touch coordinates
|
||||
THPoint TouchHandler::getPoint(void) {
|
||||
return THPoint();
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// init and set the touch handler
|
||||
|
||||
// Pointer to touch handler used by GUIslice
|
||||
TouchHandler *pTouchHandler = NULL; // NULL => no handler is available
|
||||
|
||||
// Init and set the touch hander
|
||||
void gslc_InitTouchHandler(TouchHandler *pTH) {
|
||||
//begin
|
||||
pTH->begin();
|
||||
//set the touch handler to be used by GUIslice_drv_...
|
||||
pTouchHandler = pTH;
|
||||
}
|
||||
|
||||
// Get the touch handler
|
||||
TouchHandler* gslc_getTouchHandler(void)
|
||||
{
|
||||
return pTouchHandler;
|
||||
}
|
||||
|
71
hardware/sd_card_formatter/src/guislice/GUIslice_th.h
Normal file
71
hardware/sd_card_formatter/src/guislice/GUIslice_th.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
// Abstract touch handler (TH) class
|
||||
// This is the abstract base class for creating specific touch handlers
|
||||
// The touch handler performs the adaption in between the GUIslice framework and any touch driver
|
||||
// The touch handler used is specified in the main program by calling gslc_InitTouchHandler(&touchHandler);
|
||||
|
||||
/// \file GUIslice_th.h
|
||||
|
||||
#ifndef _GUISLICE_TH_H_
|
||||
#define _GUISLICE_TH_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Point x,y,z Class for usage in the touch handler
|
||||
|
||||
class THPoint {
|
||||
public:
|
||||
THPoint(void);
|
||||
THPoint(uint16_t x, uint16_t y, uint16_t z);
|
||||
|
||||
bool operator==(THPoint);
|
||||
bool operator!=(THPoint);
|
||||
|
||||
uint16_t x, y, z;
|
||||
};
|
||||
|
||||
|
||||
///////////////////////////////////////////////////
|
||||
// Abstract TouchHandler - you have to inherit this
|
||||
|
||||
class TouchHandler {
|
||||
public:
|
||||
//in order to create a specific touch handler you have to write your own constructor
|
||||
TouchHandler() {};
|
||||
|
||||
void setSize(uint16_t _disp_xSize, uint16_t _disp_ySize);
|
||||
void setCalibration(uint16_t ts_xMin, uint16_t ts_xMax, uint16_t ts_yMin, uint16_t ts_yMax);
|
||||
//order of operations: map, swap, constraint, flip
|
||||
void setSwapFlip(bool _swapXY,bool _flipX,bool _flipY);
|
||||
|
||||
THPoint scale(THPoint pIn);
|
||||
|
||||
//in order to create a specific touch handler you have to overwrite this methods
|
||||
virtual void begin(void);
|
||||
virtual THPoint getPoint(void);
|
||||
|
||||
private:
|
||||
//landscape perspective: x: width, y: heigth
|
||||
uint16_t disp_xSize = 320;
|
||||
uint16_t disp_ySize = 240;
|
||||
|
||||
uint16_t ts_xMin = 0;
|
||||
uint16_t ts_xMax = 4095;
|
||||
uint16_t ts_yMin = 0;
|
||||
uint16_t ts_yMax = 4095;
|
||||
|
||||
bool swapXY = false;
|
||||
bool flipX = false;
|
||||
bool flipY = false;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/////////////////////////////////
|
||||
// init and set the touch handler
|
||||
|
||||
void gslc_InitTouchHandler(TouchHandler *pTHO);
|
||||
TouchHandler* gslc_getTouchHandler(void);
|
||||
|
||||
|
||||
#endif
|
|
@ -0,0 +1,52 @@
|
|||
// touch handler (TH) for XPT2046 using the arduino built in driver <XPT2046_touch.h>
|
||||
|
||||
// The touch handler performs the adaption in between the GUIslice framework and any touch driver
|
||||
// The touch handler used is specified in the main program by calling gslc_InitTouchHandler(&touchHandler);
|
||||
|
||||
/// \file GUIslice_th_XPT2046.h
|
||||
|
||||
#ifndef _GUISLICE_TH_XPT2046_H_
|
||||
#define _GUISLICE_TH_XPT2046_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include <GUIslice_th.h>
|
||||
#include <XPT2046_touch.h>
|
||||
|
||||
class TouchHandler_XPT2046: public TouchHandler {
|
||||
public:
|
||||
// parameters:
|
||||
// spi object to be used
|
||||
// chip select pin for spi
|
||||
TouchHandler_XPT2046(SPIClass &spi, uint8_t spi_cs_pin) : spi(spi), touchDriver(XPT2046_touch(spi_cs_pin, spi)) {
|
||||
//empirical calibration values, can be updated by calling setCalibration in the user program
|
||||
setCalibration(398,3877,280,3805);
|
||||
//swapping and flipping to adopt to default GUIslice orientation
|
||||
setSwapFlip(true,false,true);
|
||||
}
|
||||
|
||||
//begin is called by gslc_InitTouchHandler
|
||||
void begin(void) {
|
||||
//init the touch driver
|
||||
touchDriver.begin();
|
||||
}
|
||||
|
||||
//this method returns the scaled point provided by the touch driver
|
||||
THPoint getPoint(void) {
|
||||
//get the coordinates from the touch driver
|
||||
TS_Point pt = touchDriver.getPoint();
|
||||
//Serial.print("pt= ");Serial.print(pt.x);Serial.print(",");Serial.print(pt.y);Serial.print(",");Serial.println(pt.z);
|
||||
|
||||
//perform scaling (this includes swapping and flipping)
|
||||
THPoint ps = scale( THPoint(pt.x,pt.y,pt.z) );
|
||||
//Serial.print("ps= ");Serial.print(ps.x);Serial.print(",");Serial.print(ps.y);Serial.print(",");Serial.println(ps.z);
|
||||
|
||||
return ps;
|
||||
};
|
||||
|
||||
SPIClass spi;
|
||||
XPT2046_touch touchDriver;
|
||||
|
||||
};
|
||||
|
||||
|
||||
#endif
|
42
hardware/sd_card_formatter/src/guislice/GUIslice_version.h
Normal file
42
hardware/sd_card_formatter/src/guislice/GUIslice_version.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
#ifndef _GUISLICE_VERSION_H_
|
||||
#define _GUISLICE_VERSION_H_
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library (version control)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
|
||||
// =======================================================================
|
||||
// Define current release (X.Y.Z) & build number
|
||||
// =======================================================================
|
||||
|
||||
#define GUISLICE_VER "0.15.0"
|
||||
|
||||
#endif // _GUISLICE_VERSION_H_
|
||||
|
219
hardware/sd_card_formatter/src/guislice/NotoMono10pt7b.h
Normal file
219
hardware/sd_card_formatter/src/guislice/NotoMono10pt7b.h
Normal file
|
@ -0,0 +1,219 @@
|
|||
const uint8_t NotoMono10pt7bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0x6D, 0x92, 0x48, 0x6F, 0xC0, 0xCF, 0x3C, 0xF3, 0xCC, 0x0C,
|
||||
0x60, 0xC6, 0x08, 0x40, 0x84, 0x7F, 0xF1, 0x8C, 0x10, 0x81, 0x08, 0x31,
|
||||
0x8F, 0xFE, 0x21, 0x02, 0x10, 0x63, 0x06, 0x30, 0x08, 0x04, 0x0F, 0xCF,
|
||||
0x6C, 0x86, 0x43, 0xA0, 0xF8, 0x0F, 0x05, 0xC2, 0x61, 0x3E, 0xF7, 0xF0,
|
||||
0x20, 0x10, 0x78, 0xCC, 0xC8, 0xCD, 0x8C, 0xD0, 0xCF, 0x0C, 0xE0, 0x7E,
|
||||
0x00, 0x7E, 0x07, 0x30, 0xF3, 0x0B, 0x31, 0xB3, 0x13, 0x33, 0x1E, 0x3E,
|
||||
0x0E, 0xE1, 0x8C, 0x31, 0x86, 0x30, 0x7C, 0x0E, 0x03, 0xE6, 0xCC, 0xD8,
|
||||
0xD3, 0x0E, 0x61, 0xC7, 0xFC, 0x79, 0xC0, 0xFF, 0xC0, 0x08, 0x43, 0x18,
|
||||
0x63, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0x61, 0x83, 0x04, 0x08, 0x40, 0x83,
|
||||
0x06, 0x18, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x18, 0x63, 0x08, 0x40, 0x08,
|
||||
0x04, 0x02, 0x1D, 0x7F, 0xF8, 0xE0, 0xD8, 0x6E, 0x22, 0x00, 0x08, 0x04,
|
||||
0x02, 0x01, 0x0F, 0xF8, 0x40, 0x20, 0x10, 0x08, 0x00, 0x6F, 0x6C, 0xFF,
|
||||
0xF0, 0xFF, 0x80, 0x03, 0x02, 0x06, 0x04, 0x0C, 0x0C, 0x18, 0x18, 0x30,
|
||||
0x30, 0x20, 0x60, 0x40, 0xC0, 0x3E, 0x3B, 0x98, 0xD8, 0x3C, 0x1E, 0x0F,
|
||||
0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x6C, 0x67, 0x71, 0xF0, 0x19, 0xF7, 0x31,
|
||||
0x8C, 0x63, 0x18, 0xC6, 0x31, 0x8C, 0x3E, 0x7B, 0x90, 0x60, 0x30, 0x18,
|
||||
0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x07, 0xFC, 0x3E, 0x7B,
|
||||
0x80, 0x60, 0x30, 0x18, 0x18, 0xF0, 0x1E, 0x01, 0x80, 0xC0, 0x60, 0x3E,
|
||||
0xF3, 0xF0, 0x03, 0x01, 0xC0, 0xF0, 0x2C, 0x1B, 0x0C, 0xC2, 0x31, 0x8C,
|
||||
0xC3, 0x3F, 0xF0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0xFF, 0x60, 0x30, 0x18,
|
||||
0x0C, 0x07, 0xF3, 0xBC, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x3E, 0xF3, 0xE0,
|
||||
0x0F, 0x8F, 0x27, 0x01, 0x80, 0xC0, 0x37, 0xCF, 0x3B, 0x03, 0xC0, 0xF0,
|
||||
0x3C, 0x0D, 0x83, 0x7B, 0x87, 0xC0, 0xFF, 0xC0, 0x30, 0x08, 0x06, 0x01,
|
||||
0x00, 0xC0, 0x20, 0x18, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x00,
|
||||
0x1E, 0x0D, 0xC6, 0x19, 0x86, 0x61, 0x8C, 0xC1, 0xE0, 0xCC, 0x61, 0xB0,
|
||||
0x3C, 0x0F, 0x03, 0x73, 0x8F, 0xC0, 0x3E, 0x1D, 0xEC, 0x1B, 0x03, 0xC0,
|
||||
0xF0, 0x3C, 0x0D, 0xCF, 0x3E, 0xC0, 0x30, 0x18, 0x06, 0x4F, 0x1F, 0x00,
|
||||
0xFF, 0x80, 0x00, 0xFF, 0x80, 0xFF, 0x80, 0x00, 0x0D, 0xED, 0x80, 0x00,
|
||||
0x81, 0xC3, 0x87, 0x0E, 0x07, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x40, 0xFF,
|
||||
0x80, 0x00, 0x00, 0x0F, 0xF8, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x1C,
|
||||
0x38, 0x70, 0xE0, 0x40, 0x00, 0x7C, 0xEE, 0x03, 0x03, 0x03, 0x06, 0x0C,
|
||||
0x18, 0x10, 0x30, 0x00, 0x10, 0x38, 0x38, 0x0F, 0x83, 0x8C, 0x20, 0x64,
|
||||
0x02, 0x47, 0xBC, 0xC9, 0x98, 0x99, 0x09, 0x90, 0x99, 0x1B, 0xD9, 0xAC,
|
||||
0xE6, 0x40, 0x06, 0x00, 0x38, 0x40, 0xFC, 0x06, 0x00, 0x60, 0x0F, 0x00,
|
||||
0x90, 0x09, 0x01, 0x98, 0x10, 0x83, 0x0C, 0x3F, 0xC3, 0xFC, 0x60, 0x66,
|
||||
0x06, 0x40, 0x2C, 0x03, 0xFF, 0x3F, 0xEC, 0x0F, 0x03, 0xC0, 0xF0, 0x6F,
|
||||
0xF3, 0xFE, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xFF, 0xBF, 0xC0, 0x0F, 0x8F,
|
||||
0xF7, 0x01, 0x80, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x06, 0x01,
|
||||
0xC0, 0x3F, 0xC3, 0xF0, 0xFC, 0x3F, 0xCC, 0x3B, 0x06, 0xC0, 0xF0, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x1B, 0x0E, 0xFF, 0x3F, 0x00, 0xFF, 0xFF,
|
||||
0xF0, 0x18, 0x0C, 0x06, 0x03, 0xFF, 0xFF, 0xC0, 0x60, 0x30, 0x18, 0x0F,
|
||||
0xFF, 0xFC, 0xFF, 0xFF, 0xF0, 0x18, 0x0C, 0x06, 0x03, 0xFF, 0xFF, 0xC0,
|
||||
0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x0F, 0x8F, 0xE7, 0x01, 0x80, 0xC0,
|
||||
0x30, 0x0C, 0x3F, 0x0F, 0xC0, 0xF0, 0x36, 0x0D, 0x83, 0x3F, 0xC7, 0xE0,
|
||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3F, 0xFF, 0xFF, 0xC0, 0xF0,
|
||||
0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x30, 0xFF, 0x38, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x38, 0xFF, 0x01, 0x80, 0xC0, 0x60,
|
||||
0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x7F, 0xF7, 0xE0,
|
||||
0xC0, 0xF0, 0x6C, 0x33, 0x18, 0xCC, 0x36, 0x0F, 0x83, 0xA0, 0xCC, 0x31,
|
||||
0x8C, 0x33, 0x0C, 0xC1, 0xB0, 0x30, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06,
|
||||
0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0F, 0xFF, 0xFC, 0xC0, 0xF0,
|
||||
0x3E, 0x1F, 0x87, 0xE1, 0xF4, 0xBD, 0x2F, 0x4B, 0xD2, 0xF5, 0x3C, 0xCF,
|
||||
0x33, 0xCC, 0xF3, 0x30, 0xC0, 0xF8, 0x3E, 0x0F, 0xC3, 0xD0, 0xF6, 0x3C,
|
||||
0xCF, 0x33, 0xC6, 0xF0, 0xBC, 0x3F, 0x07, 0xC1, 0xF0, 0x30, 0x1E, 0x1F,
|
||||
0xC6, 0x1B, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0D,
|
||||
0x86, 0x7F, 0x07, 0x80, 0xFE, 0x7F, 0xB0, 0x78, 0x3C, 0x1E, 0x0F, 0x0D,
|
||||
0xFC, 0xF8, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x00, 0x1E, 0x1F, 0xC6, 0x1B,
|
||||
0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0D, 0x86, 0x7F,
|
||||
0x07, 0x80, 0x30, 0x06, 0x01, 0xC0, 0x20, 0xFE, 0x3F, 0xCC, 0x1B, 0x06,
|
||||
0xC1, 0xB0, 0x6C, 0x33, 0xF8, 0xFC, 0x31, 0x8C, 0x33, 0x0C, 0xC1, 0xB0,
|
||||
0x30, 0x3E, 0x7F, 0xC0, 0xC0, 0xC0, 0xE0, 0x78, 0x1E, 0x07, 0x03, 0x03,
|
||||
0x03, 0xFE, 0xFC, 0xFF, 0xFF, 0xF0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0xF0, 0x3C,
|
||||
0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x87,
|
||||
0x7F, 0x8F, 0xC0, 0xC0, 0x34, 0x02, 0x60, 0x66, 0x06, 0x20, 0x43, 0x0C,
|
||||
0x30, 0xC1, 0x98, 0x19, 0x80, 0x90, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60,
|
||||
0xC0, 0x3C, 0x03, 0xC0, 0x34, 0x03, 0x46, 0x24, 0x62, 0x66, 0x26, 0x92,
|
||||
0x69, 0x66, 0x96, 0x30, 0xE3, 0x0C, 0x30, 0xC2, 0x04, 0xC0, 0xD8, 0x66,
|
||||
0x18, 0xCC, 0x12, 0x07, 0x80, 0xC0, 0x30, 0x1E, 0x04, 0x83, 0x31, 0x86,
|
||||
0x61, 0xB0, 0x30, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x0C, 0x30, 0x81, 0x98,
|
||||
0x09, 0x00, 0xF0, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60,
|
||||
0xFF, 0xFF, 0xF0, 0x18, 0x04, 0x03, 0x01, 0x80, 0xC0, 0x30, 0x18, 0x0C,
|
||||
0x02, 0x01, 0x80, 0xFF, 0xFF, 0xF0, 0xFC, 0xCC, 0xCC, 0xCC, 0xCC, 0xCC,
|
||||
0xCC, 0xCC, 0xF0, 0xC0, 0x40, 0x60, 0x20, 0x30, 0x30, 0x18, 0x18, 0x0C,
|
||||
0x0C, 0x04, 0x06, 0x02, 0x03, 0xF3, 0x33, 0x33, 0x33, 0x33, 0x33, 0x33,
|
||||
0x33, 0xF0, 0x0C, 0x03, 0x01, 0xE0, 0x48, 0x33, 0x08, 0x46, 0x19, 0x02,
|
||||
0xC0, 0xC0, 0xFF, 0xF0, 0xC6, 0x30, 0x3E, 0x3B, 0xC0, 0x60, 0x33, 0xFB,
|
||||
0x8F, 0x07, 0x83, 0xC1, 0xF3, 0xDF, 0x20, 0xC0, 0x30, 0x0C, 0x03, 0x00,
|
||||
0xDF, 0x3E, 0xEC, 0x1B, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC1, 0xBE,
|
||||
0xE9, 0xF0, 0x1F, 0x7B, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x60, 0x7B,
|
||||
0x1F, 0x01, 0x80, 0xC0, 0x60, 0x33, 0xDB, 0xBD, 0x07, 0x83, 0xC1, 0xE0,
|
||||
0xF0, 0x78, 0x34, 0x1B, 0xBC, 0xF6, 0x1F, 0x1E, 0xE4, 0x0F, 0x03, 0xFF,
|
||||
0xF0, 0x0C, 0x03, 0x00, 0x60, 0x1E, 0xE1, 0xF8, 0x0F, 0xC7, 0x31, 0x80,
|
||||
0x60, 0xFF, 0x86, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01, 0x80, 0x60, 0x18,
|
||||
0x06, 0x01, 0x80, 0x1F, 0xCC, 0xC6, 0x19, 0x86, 0x61, 0x8C, 0xC1, 0xE0,
|
||||
0xC0, 0x30, 0x0F, 0xE6, 0x1F, 0x03, 0xC0, 0xF0, 0x36, 0x38, 0xFC, 0xC0,
|
||||
0x60, 0x30, 0x18, 0x0D, 0xE7, 0xBB, 0x87, 0x83, 0xC1, 0xE0, 0xF0, 0x78,
|
||||
0x3C, 0x1E, 0x0F, 0x06, 0x18, 0x18, 0x00, 0x00, 0xF8, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0x06, 0x0C, 0x00, 0x07, 0xE0,
|
||||
0xC1, 0x83, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1, 0x83, 0x06, 0x0F, 0x77,
|
||||
0xC0, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x36, 0x33, 0x31, 0xB0, 0xF0, 0x78,
|
||||
0x36, 0x19, 0x8C, 0x66, 0x1B, 0x06, 0xF8, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0xFF, 0xBB, 0xBE, 0xFC,
|
||||
0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCF, 0x33, 0xCC, 0xF3, 0x3C, 0xCC, 0xDE,
|
||||
0x7B, 0xB8, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0xC1, 0xE0, 0xF0, 0x60,
|
||||
0x1E, 0x1D, 0xE6, 0x1B, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0x61, 0x9F,
|
||||
0xE1, 0xE0, 0xDF, 0x3E, 0xEC, 0x1B, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||
0xC1, 0xBE, 0xED, 0xF3, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0x3D, 0xBB,
|
||||
0xD0, 0x78, 0x3C, 0x1E, 0x0F, 0x07, 0x83, 0x41, 0xBB, 0xCF, 0x60, 0x30,
|
||||
0x18, 0x0C, 0x06, 0x03, 0x9F, 0xEF, 0x06, 0x0C, 0x18, 0x30, 0x60, 0xC1,
|
||||
0x83, 0x00, 0x3E, 0xE7, 0xC0, 0xC0, 0x70, 0x3C, 0x07, 0x03, 0x03, 0xEF,
|
||||
0xFC, 0x08, 0x0C, 0x06, 0x1F, 0xF1, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C,
|
||||
0x06, 0x03, 0x01, 0xD8, 0x7C, 0xC1, 0xE0, 0xF0, 0x78, 0x3C, 0x1E, 0x0F,
|
||||
0x07, 0x83, 0xC1, 0xBB, 0xCF, 0x60, 0xC0, 0xD0, 0x26, 0x19, 0x86, 0x21,
|
||||
0x0C, 0xC3, 0x30, 0x48, 0x1E, 0x07, 0x80, 0xC0, 0xC6, 0x3C, 0x63, 0xC7,
|
||||
0x34, 0xB2, 0x49, 0x24, 0x92, 0x59, 0xA5, 0x0A, 0x50, 0xA3, 0x0C, 0x20,
|
||||
0x40, 0x61, 0x98, 0x63, 0x30, 0x48, 0x1E, 0x03, 0x01, 0xE0, 0xCC, 0x33,
|
||||
0x18, 0x6C, 0x0C, 0xC0, 0xD0, 0x26, 0x19, 0x86, 0x21, 0x0C, 0xC3, 0x30,
|
||||
0x68, 0x1E, 0x03, 0x80, 0xC0, 0x30, 0x08, 0x06, 0x0B, 0x03, 0x80, 0xFF,
|
||||
0x03, 0x06, 0x04, 0x0C, 0x18, 0x30, 0x30, 0x60, 0xC0, 0xFF, 0x07, 0x1E,
|
||||
0x18, 0x18, 0x18, 0x18, 0x38, 0xE0, 0x70, 0x18, 0x18, 0x18, 0x18, 0x18,
|
||||
0x18, 0x1E, 0x07, 0xFF, 0xFF, 0xF0, 0xE0, 0x78, 0x18, 0x18, 0x18, 0x18,
|
||||
0x1C, 0x07, 0x0E, 0x18, 0x18, 0x18, 0x18, 0x18, 0x18, 0x78, 0xE0, 0x70,
|
||||
0x7F, 0xC1, 0xC0 };
|
||||
|
||||
const GFXglyph NotoMono10pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 12, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 3, 14, 12, 5, -13 }, // 0x21 '!'
|
||||
{ 7, 6, 5, 12, 3, -13 }, // 0x22 '"'
|
||||
{ 11, 12, 14, 12, 0, -13 }, // 0x23 '#'
|
||||
{ 32, 9, 16, 12, 2, -14 }, // 0x24 '$'
|
||||
{ 50, 12, 14, 12, 0, -13 }, // 0x25 '%'
|
||||
{ 71, 11, 14, 12, 1, -13 }, // 0x26 '&'
|
||||
{ 91, 2, 5, 12, 5, -13 }, // 0x27 '''
|
||||
{ 93, 6, 17, 12, 3, -13 }, // 0x28 '('
|
||||
{ 106, 6, 17, 12, 3, -13 }, // 0x29 ')'
|
||||
{ 119, 9, 9, 12, 1, -14 }, // 0x2A '*'
|
||||
{ 130, 9, 9, 12, 1, -11 }, // 0x2B '+'
|
||||
{ 141, 3, 5, 12, 4, -2 }, // 0x2C ','
|
||||
{ 143, 6, 2, 12, 3, -5 }, // 0x2D '-'
|
||||
{ 145, 3, 3, 12, 4, -2 }, // 0x2E '.'
|
||||
{ 147, 8, 14, 12, 2, -13 }, // 0x2F '/'
|
||||
{ 161, 9, 14, 12, 1, -13 }, // 0x30 '0'
|
||||
{ 177, 5, 14, 12, 3, -13 }, // 0x31 '1'
|
||||
{ 186, 9, 14, 12, 1, -13 }, // 0x32 '2'
|
||||
{ 202, 9, 14, 12, 1, -13 }, // 0x33 '3'
|
||||
{ 218, 10, 14, 12, 1, -13 }, // 0x34 '4'
|
||||
{ 236, 9, 14, 12, 1, -13 }, // 0x35 '5'
|
||||
{ 252, 10, 14, 12, 1, -13 }, // 0x36 '6'
|
||||
{ 270, 10, 14, 12, 1, -13 }, // 0x37 '7'
|
||||
{ 288, 10, 14, 12, 1, -13 }, // 0x38 '8'
|
||||
{ 306, 10, 14, 12, 1, -13 }, // 0x39 '9'
|
||||
{ 324, 3, 11, 12, 4, -10 }, // 0x3A ':'
|
||||
{ 329, 3, 14, 12, 4, -10 }, // 0x3B ';'
|
||||
{ 335, 9, 10, 12, 1, -11 }, // 0x3C '<'
|
||||
{ 347, 9, 5, 12, 1, -9 }, // 0x3D '='
|
||||
{ 353, 9, 10, 12, 1, -11 }, // 0x3E '>'
|
||||
{ 365, 8, 14, 12, 2, -13 }, // 0x3F '?'
|
||||
{ 379, 12, 16, 12, 0, -13 }, // 0x40 '@'
|
||||
{ 403, 12, 14, 12, 0, -13 }, // 0x41 'A'
|
||||
{ 424, 10, 14, 12, 1, -13 }, // 0x42 'B'
|
||||
{ 442, 10, 14, 12, 1, -13 }, // 0x43 'C'
|
||||
{ 460, 10, 14, 12, 1, -13 }, // 0x44 'D'
|
||||
{ 478, 9, 14, 12, 2, -13 }, // 0x45 'E'
|
||||
{ 494, 9, 14, 12, 2, -13 }, // 0x46 'F'
|
||||
{ 510, 10, 14, 12, 1, -13 }, // 0x47 'G'
|
||||
{ 528, 10, 14, 12, 1, -13 }, // 0x48 'H'
|
||||
{ 546, 8, 14, 12, 2, -13 }, // 0x49 'I'
|
||||
{ 560, 9, 14, 12, 1, -13 }, // 0x4A 'J'
|
||||
{ 576, 10, 14, 12, 2, -13 }, // 0x4B 'K'
|
||||
{ 594, 9, 14, 12, 2, -13 }, // 0x4C 'L'
|
||||
{ 610, 10, 14, 12, 1, -13 }, // 0x4D 'M'
|
||||
{ 628, 10, 14, 12, 1, -13 }, // 0x4E 'N'
|
||||
{ 646, 10, 14, 12, 1, -13 }, // 0x4F 'O'
|
||||
{ 664, 9, 14, 12, 2, -13 }, // 0x50 'P'
|
||||
{ 680, 10, 18, 12, 1, -13 }, // 0x51 'Q'
|
||||
{ 703, 10, 14, 12, 2, -13 }, // 0x52 'R'
|
||||
{ 721, 8, 14, 12, 2, -13 }, // 0x53 'S'
|
||||
{ 735, 10, 14, 12, 1, -13 }, // 0x54 'T'
|
||||
{ 753, 10, 14, 12, 1, -13 }, // 0x55 'U'
|
||||
{ 771, 12, 14, 12, 0, -13 }, // 0x56 'V'
|
||||
{ 792, 12, 14, 12, 0, -13 }, // 0x57 'W'
|
||||
{ 813, 10, 14, 12, 1, -13 }, // 0x58 'X'
|
||||
{ 831, 12, 14, 12, 0, -13 }, // 0x59 'Y'
|
||||
{ 852, 10, 14, 12, 1, -13 }, // 0x5A 'Z'
|
||||
{ 870, 4, 17, 12, 5, -13 }, // 0x5B '['
|
||||
{ 879, 8, 14, 12, 2, -13 }, // 0x5C '\'
|
||||
{ 893, 4, 17, 12, 3, -13 }, // 0x5D ']'
|
||||
{ 902, 10, 9, 12, 1, -13 }, // 0x5E '^'
|
||||
{ 914, 12, 1, 12, 0, 3 }, // 0x5F '_'
|
||||
{ 916, 4, 3, 12, 4, -14 }, // 0x60 '`'
|
||||
{ 918, 9, 11, 12, 1, -10 }, // 0x61 'a'
|
||||
{ 931, 10, 15, 12, 1, -14 }, // 0x62 'b'
|
||||
{ 950, 8, 11, 12, 2, -10 }, // 0x63 'c'
|
||||
{ 961, 9, 15, 12, 1, -14 }, // 0x64 'd'
|
||||
{ 978, 10, 11, 12, 1, -10 }, // 0x65 'e'
|
||||
{ 992, 10, 15, 12, 1, -14 }, // 0x66 'f'
|
||||
{ 1011, 10, 16, 12, 1, -10 }, // 0x67 'g'
|
||||
{ 1031, 9, 15, 12, 1, -14 }, // 0x68 'h'
|
||||
{ 1048, 8, 15, 12, 2, -14 }, // 0x69 'i'
|
||||
{ 1063, 7, 20, 12, 1, -14 }, // 0x6A 'j'
|
||||
{ 1081, 9, 15, 12, 2, -14 }, // 0x6B 'k'
|
||||
{ 1098, 8, 15, 12, 2, -14 }, // 0x6C 'l'
|
||||
{ 1113, 10, 11, 12, 1, -10 }, // 0x6D 'm'
|
||||
{ 1127, 9, 11, 12, 1, -10 }, // 0x6E 'n'
|
||||
{ 1140, 10, 11, 12, 1, -10 }, // 0x6F 'o'
|
||||
{ 1154, 10, 16, 12, 1, -10 }, // 0x70 'p'
|
||||
{ 1174, 9, 16, 12, 1, -10 }, // 0x71 'q'
|
||||
{ 1192, 7, 11, 12, 3, -10 }, // 0x72 'r'
|
||||
{ 1202, 8, 11, 12, 2, -10 }, // 0x73 's'
|
||||
{ 1213, 9, 14, 12, 1, -13 }, // 0x74 't'
|
||||
{ 1229, 9, 11, 12, 1, -10 }, // 0x75 'u'
|
||||
{ 1242, 10, 11, 12, 1, -10 }, // 0x76 'v'
|
||||
{ 1256, 12, 11, 12, 0, -10 }, // 0x77 'w'
|
||||
{ 1273, 10, 11, 12, 1, -10 }, // 0x78 'x'
|
||||
{ 1287, 10, 16, 12, 1, -10 }, // 0x79 'y'
|
||||
{ 1307, 8, 11, 12, 2, -10 }, // 0x7A 'z'
|
||||
{ 1318, 8, 17, 12, 2, -13 }, // 0x7B '{'
|
||||
{ 1335, 1, 20, 12, 5, -14 }, // 0x7C '|'
|
||||
{ 1338, 8, 17, 12, 2, -13 }, // 0x7D '}'
|
||||
{ 1355, 9, 3, 12, 1, -8 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont NotoMono10pt7b PROGMEM = {
|
||||
(uint8_t *)NotoMono10pt7bBitmaps,
|
||||
(GFXglyph *)NotoMono10pt7bGlyphs,
|
||||
0x20, 0x7E, 23 };
|
||||
|
||||
// Approx. 2031 bytes
|
265
hardware/sd_card_formatter/src/guislice/NotoMono12pt7b.h
Normal file
265
hardware/sd_card_formatter/src/guislice/NotoMono12pt7b.h
Normal file
|
@ -0,0 +1,265 @@
|
|||
const uint8_t NotoMono12pt7bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0xFF, 0xD2, 0x49, 0x20, 0x3F, 0xE0, 0xE7, 0xE7, 0xE7, 0xE7,
|
||||
0xC6, 0xC6, 0x0C, 0x60, 0x63, 0x03, 0x18, 0x10, 0xC0, 0x84, 0x3F, 0xFD,
|
||||
0xFF, 0xE3, 0x18, 0x18, 0xC0, 0xC6, 0x3F, 0xFD, 0xFF, 0xE1, 0x08, 0x18,
|
||||
0xC0, 0xC6, 0x06, 0x30, 0x31, 0x80, 0x0C, 0x03, 0x03, 0xF9, 0xFE, 0xEC,
|
||||
0x33, 0x0C, 0xC3, 0xB0, 0x7C, 0x0F, 0xC0, 0xF8, 0x37, 0x0C, 0xC3, 0x38,
|
||||
0xDF, 0xFE, 0x7E, 0x03, 0x00, 0xC0, 0x30, 0x38, 0x33, 0x63, 0x31, 0x99,
|
||||
0x8D, 0x8C, 0x6C, 0x63, 0xC1, 0xB6, 0x07, 0x60, 0x02, 0x00, 0x37, 0x03,
|
||||
0x6C, 0x1E, 0x31, 0xB1, 0x8D, 0x8C, 0xCC, 0x66, 0x36, 0x60, 0xE0, 0x1E,
|
||||
0x01, 0xF8, 0x18, 0x60, 0xC3, 0x06, 0x18, 0x39, 0x80, 0xDC, 0x03, 0xC0,
|
||||
0x3C, 0x03, 0xF1, 0xB9, 0xCD, 0x87, 0xCC, 0x1E, 0x60, 0x63, 0x87, 0x8F,
|
||||
0xEE, 0x3E, 0x38, 0xFF, 0xFD, 0x80, 0x06, 0x0C, 0x18, 0x30, 0x30, 0x60,
|
||||
0x60, 0xE0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xE0, 0x60, 0x60, 0x30, 0x30,
|
||||
0x18, 0x0C, 0x06, 0x60, 0x30, 0x18, 0x1C, 0x0C, 0x06, 0x06, 0x07, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x07, 0x06, 0x06, 0x0C, 0x0C, 0x18, 0x30, 0x60,
|
||||
0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x7F, 0xFF, 0xFF, 0x0F, 0x00, 0xF0,
|
||||
0x19, 0x83, 0x9C, 0x10, 0x80, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x61,
|
||||
0xFF, 0xFF, 0xF8, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x00, 0x77, 0x66, 0xCC,
|
||||
0xFF, 0xFF, 0xFF, 0x80, 0x00, 0xC0, 0x60, 0x18, 0x0C, 0x03, 0x01, 0x80,
|
||||
0x60, 0x38, 0x0C, 0x07, 0x01, 0x80, 0x60, 0x30, 0x0C, 0x06, 0x01, 0x80,
|
||||
0xC0, 0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x6E, 0x0F, 0x80, 0xF0, 0x1E,
|
||||
0x03, 0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3E, 0x0E, 0xC1, 0x9C, 0x71, 0xFC,
|
||||
0x1F, 0x00, 0x0C, 0xF7, 0xFB, 0x4C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C,
|
||||
0x30, 0xC3, 0x0C, 0x1F, 0x0F, 0xF1, 0x87, 0x00, 0x60, 0x0C, 0x01, 0x80,
|
||||
0x70, 0x0C, 0x03, 0x80, 0xE0, 0x38, 0x06, 0x01, 0x80, 0x60, 0x18, 0x07,
|
||||
0xFF, 0xFF, 0xE0, 0x3E, 0x3F, 0xC4, 0x38, 0x06, 0x01, 0x80, 0xE0, 0x70,
|
||||
0xF0, 0x3F, 0x00, 0x60, 0x0C, 0x03, 0x00, 0xC0, 0x78, 0x1B, 0xFE, 0x7E,
|
||||
0x00, 0x03, 0x80, 0x38, 0x07, 0x80, 0x58, 0x0D, 0x81, 0x98, 0x19, 0x83,
|
||||
0x18, 0x31, 0x86, 0x18, 0xC1, 0x8F, 0xFF, 0xFF, 0xF0, 0x18, 0x01, 0x80,
|
||||
0x18, 0x01, 0x80, 0x7F, 0x9F, 0xEC, 0x03, 0x00, 0xC0, 0x30, 0x0F, 0xE3,
|
||||
0xFE, 0x01, 0x80, 0x70, 0x0C, 0x03, 0x00, 0xC0, 0x78, 0x1B, 0xFC, 0x7E,
|
||||
0x00, 0x07, 0xC3, 0xF8, 0xE0, 0x38, 0x06, 0x01, 0xC0, 0x33, 0xC6, 0xFE,
|
||||
0xE0, 0xDC, 0x0F, 0x01, 0xE0, 0x3C, 0x06, 0xC1, 0xDC, 0x31, 0xFE, 0x1F,
|
||||
0x00, 0xFF, 0xFF, 0xFC, 0x03, 0x80, 0x60, 0x0C, 0x03, 0x00, 0x60, 0x18,
|
||||
0x03, 0x00, 0xE0, 0x18, 0x07, 0x00, 0xC0, 0x18, 0x06, 0x00, 0xC0, 0x38,
|
||||
0x00, 0x1F, 0x07, 0xF1, 0xC7, 0x30, 0x66, 0x0C, 0xE1, 0x8E, 0x60, 0xF8,
|
||||
0x1F, 0x0E, 0x39, 0x83, 0x60, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0xFE, 0x1F,
|
||||
0x00, 0x1F, 0x0F, 0xF1, 0x87, 0x70, 0x6C, 0x07, 0x80, 0xF0, 0x1E, 0x07,
|
||||
0x60, 0xEF, 0xEC, 0x79, 0x80, 0x70, 0x0C, 0x03, 0x80, 0xE3, 0xF8, 0x7C,
|
||||
0x00, 0xFF, 0x80, 0x00, 0x03, 0xFE, 0x77, 0x70, 0x00, 0x00, 0x00, 0x77,
|
||||
0x66, 0xCC, 0x00, 0x40, 0x70, 0x78, 0x78, 0x38, 0x38, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x01, 0xE0, 0x1C, 0x01, 0xFF, 0xFF, 0xF0, 0x00, 0x00, 0x00, 0x3F,
|
||||
0xFF, 0xFC, 0x80, 0x38, 0x07, 0x80, 0x70, 0x07, 0x00, 0x70, 0x1C, 0x1C,
|
||||
0x1C, 0x1E, 0x0E, 0x02, 0x00, 0x3F, 0x3F, 0xE4, 0x1C, 0x03, 0x00, 0xC0,
|
||||
0x30, 0x18, 0x0E, 0x06, 0x03, 0x00, 0xC0, 0x60, 0x00, 0x00, 0x01, 0xC0,
|
||||
0x70, 0x1C, 0x00, 0x07, 0xC0, 0x7F, 0xC3, 0x03, 0x18, 0x06, 0x60, 0x09,
|
||||
0x1F, 0x3C, 0xFC, 0xF6, 0x33, 0xD8, 0xCF, 0x63, 0x3D, 0x8C, 0xF6, 0x33,
|
||||
0xCF, 0xFB, 0x3C, 0xC6, 0x00, 0x18, 0x00, 0x30, 0x00, 0x7F, 0xC0, 0x7E,
|
||||
0x00, 0x03, 0x00, 0x1E, 0x00, 0x78, 0x01, 0xE0, 0x0C, 0xC0, 0x33, 0x00,
|
||||
0xCC, 0x06, 0x18, 0x18, 0x60, 0x61, 0x83, 0xFF, 0x0F, 0xFC, 0x30, 0x31,
|
||||
0x80, 0x66, 0x01, 0x98, 0x06, 0xC0, 0x0C, 0xFF, 0x8F, 0xFE, 0xC0, 0x7C,
|
||||
0x03, 0xC0, 0x3C, 0x07, 0xC0, 0xEF, 0xF8, 0xFF, 0xCC, 0x0E, 0xC0, 0x7C,
|
||||
0x03, 0xC0, 0x3C, 0x07, 0xC0, 0xEF, 0xFE, 0xFF, 0x80, 0x07, 0xE1, 0xFF,
|
||||
0x38, 0x27, 0x00, 0x60, 0x0E, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00,
|
||||
0xC0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x38, 0x01, 0xFF, 0x07, 0xE0, 0xFE,
|
||||
0x0F, 0xF8, 0xC1, 0xCC, 0x0E, 0xC0, 0x6C, 0x07, 0xC0, 0x3C, 0x03, 0xC0,
|
||||
0x3C, 0x03, 0xC0, 0x7C, 0x07, 0xC0, 0x6C, 0x0E, 0xC1, 0xCF, 0xF8, 0xFE,
|
||||
0x00, 0xFF, 0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF,
|
||||
0xF0, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xC0, 0xFF,
|
||||
0xFF, 0xFC, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF, 0xF0, 0x0C,
|
||||
0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, 0x0F, 0xC3, 0xFC,
|
||||
0xE1, 0x38, 0x06, 0x01, 0xC0, 0x30, 0x06, 0x1F, 0xC3, 0xF8, 0x0F, 0x01,
|
||||
0xF0, 0x36, 0x06, 0xC0, 0xDC, 0x19, 0xFF, 0x0F, 0xC0, 0xC0, 0x78, 0x0F,
|
||||
0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1F, 0xFF, 0xFF, 0xF8, 0x0F, 0x01,
|
||||
0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x60, 0xFF, 0xFF, 0xC6,
|
||||
0x03, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x01, 0x80,
|
||||
0xC0, 0x61, 0xFF, 0xFF, 0x80, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0,
|
||||
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x70, 0x3B,
|
||||
0xFC, 0xFE, 0x00, 0xC0, 0x78, 0x1B, 0x06, 0x61, 0x8C, 0x61, 0x9C, 0x33,
|
||||
0x06, 0xC0, 0xFC, 0x1D, 0x83, 0x18, 0x63, 0x8C, 0x31, 0x83, 0x30, 0x76,
|
||||
0x06, 0xC0, 0x60, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03,
|
||||
0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0xFF, 0xFF,
|
||||
0xC0, 0xE0, 0xFC, 0x1F, 0x83, 0xF0, 0x7E, 0x17, 0xA2, 0xF4, 0x5E, 0x8B,
|
||||
0xD1, 0x7A, 0x6F, 0x29, 0xE5, 0x3C, 0xA7, 0x94, 0xF3, 0x9E, 0x23, 0xC4,
|
||||
0x60, 0xE0, 0x7C, 0x0F, 0xC1, 0xF8, 0x3D, 0x07, 0xB0, 0xF2, 0x1E, 0x63,
|
||||
0xC4, 0x78, 0xCF, 0x09, 0xE1, 0xBC, 0x17, 0x83, 0xF0, 0x7E, 0x07, 0xC0,
|
||||
0xE0, 0x1F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0xE0, 0x6E, 0x07, 0xC0, 0x3C,
|
||||
0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, 0x07, 0xE0, 0x66, 0x06, 0x70, 0xE3,
|
||||
0xFC, 0x1F, 0x00, 0xFF, 0x1F, 0xFB, 0x07, 0x60, 0x7C, 0x07, 0x80, 0xF0,
|
||||
0x1E, 0x07, 0xC1, 0xDF, 0xF3, 0xF8, 0x60, 0x0C, 0x01, 0x80, 0x30, 0x06,
|
||||
0x00, 0xC0, 0x00, 0x1F, 0x03, 0xFC, 0x70, 0xE6, 0x06, 0xE0, 0x6E, 0x07,
|
||||
0xC0, 0x3C, 0x03, 0xC0, 0x3C, 0x03, 0xC0, 0x3E, 0x07, 0xE0, 0x76, 0x06,
|
||||
0x70, 0xE3, 0xFC, 0x1F, 0x80, 0x18, 0x00, 0xC0, 0x0E, 0x00, 0x70, 0x02,
|
||||
0xFE, 0x1F, 0xF3, 0x07, 0x60, 0xEC, 0x0D, 0x81, 0xB0, 0x76, 0x1C, 0xFF,
|
||||
0x1F, 0xC3, 0x18, 0x61, 0x8C, 0x39, 0x83, 0x30, 0x76, 0x06, 0xC0, 0x60,
|
||||
0x1F, 0x9F, 0xFE, 0x0B, 0x00, 0xC0, 0x30, 0x0E, 0x01, 0xF0, 0x1F, 0x01,
|
||||
0xE0, 0x1C, 0x03, 0x00, 0xC0, 0x38, 0x1F, 0xFE, 0x7E, 0x00, 0xFF, 0xFF,
|
||||
0xFF, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00,
|
||||
0xC0, 0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
|
||||
0x78, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0xC1, 0xDC, 0x73, 0xFE, 0x1F, 0x00,
|
||||
0xC0, 0x1D, 0x80, 0x66, 0x01, 0x98, 0x06, 0x30, 0x30, 0xC0, 0xC3, 0x03,
|
||||
0x06, 0x18, 0x18, 0x60, 0x61, 0x80, 0xCC, 0x03, 0x30, 0x0C, 0xC0, 0x1E,
|
||||
0x00, 0x78, 0x01, 0xE0, 0x03, 0x00, 0xC0, 0x0F, 0x00, 0x3C, 0x00, 0xF0,
|
||||
0x03, 0x60, 0x09, 0x8C, 0x66, 0x31, 0x99, 0xE6, 0x67, 0x99, 0x92, 0x66,
|
||||
0xC9, 0x9B, 0x36, 0x2C, 0xD0, 0xA1, 0x42, 0x87, 0x0E, 0x1C, 0x30, 0x30,
|
||||
0xE0, 0x76, 0x06, 0x70, 0xE3, 0x0C, 0x19, 0x81, 0x98, 0x0F, 0x00, 0xF0,
|
||||
0x06, 0x00, 0xF0, 0x0F, 0x01, 0x98, 0x39, 0xC3, 0x0C, 0x70, 0xE6, 0x06,
|
||||
0xE0, 0x70, 0xC0, 0x36, 0x06, 0x60, 0x63, 0x0C, 0x30, 0xC1, 0x98, 0x19,
|
||||
0x80, 0xF0, 0x0F, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06, 0x00, 0x60, 0x06,
|
||||
0x00, 0x60, 0x06, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x60, 0x0E, 0x00, 0xC0,
|
||||
0x18, 0x03, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x1C, 0x01, 0x80, 0x30, 0x07,
|
||||
0x00, 0x60, 0x0F, 0xFF, 0xFF, 0xF0, 0xFF, 0xFC, 0x30, 0xC3, 0x0C, 0x30,
|
||||
0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x3F, 0xFC, 0xC0, 0x18,
|
||||
0x06, 0x00, 0xC0, 0x30, 0x06, 0x01, 0x80, 0x70, 0x0C, 0x03, 0x80, 0x60,
|
||||
0x18, 0x03, 0x00, 0xC0, 0x18, 0x06, 0x00, 0xC0, 0xFF, 0xF0, 0xC3, 0x0C,
|
||||
0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xC3, 0x0C, 0x30, 0xFF, 0xFC,
|
||||
0x06, 0x00, 0x60, 0x0F, 0x00, 0x90, 0x19, 0x81, 0x08, 0x30, 0xC3, 0x0C,
|
||||
0x60, 0x66, 0x06, 0xC0, 0x30, 0xFF, 0xFC, 0xE3, 0x0C, 0x30, 0x3F, 0x1F,
|
||||
0xE0, 0x1C, 0x03, 0x00, 0xC7, 0xF7, 0xEF, 0x83, 0xC0, 0xF0, 0x7E, 0x1D,
|
||||
0xFF, 0x3C, 0xC0, 0xC0, 0x18, 0x03, 0x00, 0x60, 0x0C, 0x01, 0x9E, 0x3F,
|
||||
0xE7, 0x06, 0xE0, 0xF8, 0x0F, 0x01, 0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3F,
|
||||
0x06, 0xFF, 0x99, 0xE0, 0x1F, 0x8F, 0xF7, 0x03, 0x80, 0xC0, 0x30, 0x0C,
|
||||
0x03, 0x00, 0xC0, 0x38, 0x07, 0x00, 0xFF, 0x1F, 0x80, 0x00, 0x60, 0x0C,
|
||||
0x01, 0x80, 0x30, 0x06, 0x3C, 0xCF, 0xFB, 0x07, 0xE0, 0xF8, 0x0F, 0x01,
|
||||
0xE0, 0x3C, 0x07, 0x80, 0xF8, 0x3B, 0x07, 0x3F, 0xE3, 0xCC, 0x0F, 0x83,
|
||||
0xFC, 0x70, 0x66, 0x03, 0xC0, 0x3F, 0xFF, 0xFF, 0xFC, 0x00, 0xC0, 0x06,
|
||||
0x00, 0x70, 0x03, 0xFE, 0x0F, 0xC0, 0x03, 0xF0, 0x7F, 0x0E, 0x00, 0xC0,
|
||||
0x0C, 0x0F, 0xFE, 0xFF, 0xE0, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0,
|
||||
0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x0C, 0x00, 0xC0, 0x1F, 0xF9, 0xFF,
|
||||
0x1C, 0x38, 0xC0, 0xC6, 0x06, 0x30, 0x30, 0xFF, 0x03, 0xF0, 0x30, 0x01,
|
||||
0x80, 0x0C, 0x00, 0x3F, 0x83, 0xFE, 0x30, 0x1B, 0x00, 0xD8, 0x06, 0xE0,
|
||||
0x73, 0xFF, 0x0F, 0xE0, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x33, 0xCF,
|
||||
0xFB, 0x87, 0xE0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||
0xC0, 0xF0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x00, 0x00, 0x1F, 0x03, 0xC0,
|
||||
0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7F,
|
||||
0xBF, 0xF0, 0x03, 0x07, 0x03, 0x00, 0x00, 0x7F, 0x1F, 0x03, 0x03, 0x03,
|
||||
0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x07,
|
||||
0xFE, 0xFC, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7C, 0x3B, 0x1C,
|
||||
0xCE, 0x33, 0x0D, 0x83, 0xE0, 0xEC, 0x31, 0x8C, 0x63, 0x0C, 0xC1, 0xB0,
|
||||
0x70, 0x7C, 0x0F, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x0C,
|
||||
0x03, 0x00, 0xC0, 0x30, 0x0C, 0x03, 0x00, 0xC0, 0x30, 0x7F, 0xBF, 0xF0,
|
||||
0xDC, 0xEF, 0xFF, 0xE7, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63,
|
||||
0xC6, 0x3C, 0x63, 0xC6, 0x3C, 0x63, 0xC6, 0x30, 0xCF, 0x3F, 0xEE, 0x1F,
|
||||
0x83, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0,
|
||||
0xC0, 0x1F, 0x83, 0xFC, 0x70, 0xEE, 0x06, 0xC0, 0x3C, 0x03, 0xC0, 0x3C,
|
||||
0x03, 0xC0, 0x36, 0x06, 0x70, 0xE3, 0xFC, 0x1F, 0x80, 0xCF, 0x1F, 0xF3,
|
||||
0x83, 0x70, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0, 0x7C, 0x1F, 0x83,
|
||||
0x7F, 0xCC, 0xF1, 0x80, 0x30, 0x06, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x00,
|
||||
0x1E, 0x67, 0xED, 0x83, 0xF0, 0x7C, 0x07, 0x80, 0xF0, 0x1E, 0x03, 0xC0,
|
||||
0x7C, 0x1D, 0x83, 0x9F, 0xF1, 0xE6, 0x00, 0xC0, 0x18, 0x03, 0x00, 0x60,
|
||||
0x0C, 0x01, 0x80, 0xCF, 0xEF, 0xFC, 0x1C, 0x0C, 0x06, 0x03, 0x01, 0x80,
|
||||
0xC0, 0x60, 0x30, 0x18, 0x0C, 0x00, 0x3F, 0x9F, 0xFC, 0x03, 0x00, 0xE0,
|
||||
0x1F, 0x01, 0xF0, 0x0E, 0x01, 0xC0, 0x38, 0x1F, 0xFE, 0x7F, 0x00, 0x08,
|
||||
0x06, 0x01, 0x83, 0xFF, 0xFF, 0xC6, 0x01, 0x80, 0x60, 0x18, 0x06, 0x01,
|
||||
0x80, 0x60, 0x18, 0x07, 0x00, 0xFC, 0x1F, 0xC0, 0xF0, 0x3C, 0x0F, 0x03,
|
||||
0xC0, 0xF0, 0x3C, 0x0F, 0x03, 0xC0, 0xF0, 0x7E, 0x1D, 0xFF, 0x3C, 0xC0,
|
||||
0xC0, 0x36, 0x06, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C, 0x30, 0xC1, 0x98,
|
||||
0x19, 0x80, 0x98, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0xC3, 0x0F, 0x0C, 0x3C,
|
||||
0x78, 0x91, 0xE2, 0x65, 0x99, 0x92, 0x66, 0xCD, 0x8B, 0x34, 0x2C, 0xD0,
|
||||
0xA1, 0x42, 0x85, 0x0E, 0x1C, 0x10, 0x60, 0x60, 0x67, 0x0E, 0x30, 0xC1,
|
||||
0x98, 0x1F, 0x80, 0xF0, 0x06, 0x00, 0xF0, 0x1F, 0x81, 0x98, 0x30, 0xC6,
|
||||
0x06, 0xE0, 0x70, 0xC0, 0x36, 0x06, 0x60, 0x66, 0x06, 0x30, 0xC3, 0x0C,
|
||||
0x19, 0xC1, 0x98, 0x19, 0x80, 0xF8, 0x0F, 0x00, 0xF0, 0x06, 0x00, 0x60,
|
||||
0x0E, 0x00, 0xC0, 0x1C, 0x0F, 0x80, 0xF0, 0x00, 0xFF, 0xFF, 0xF0, 0x18,
|
||||
0x0E, 0x03, 0x01, 0x80, 0xC0, 0x60, 0x38, 0x0C, 0x06, 0x03, 0xFF, 0xFF,
|
||||
0xC0, 0x03, 0x83, 0xC3, 0x01, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x1C, 0x7C,
|
||||
0x3E, 0x03, 0x80, 0xC0, 0x60, 0x30, 0x18, 0x0C, 0x06, 0x03, 0x80, 0xF0,
|
||||
0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xE0, 0x78, 0x0E, 0x03, 0x01,
|
||||
0x80, 0xC0, 0x60, 0x30, 0x1C, 0x07, 0xC3, 0xE3, 0x81, 0x80, 0xC0, 0x60,
|
||||
0x30, 0x18, 0x0C, 0x0E, 0x1E, 0x0E, 0x00, 0x78, 0x7F, 0xF8, 0x78 };
|
||||
|
||||
const GFXglyph NotoMono12pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 14, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 3, 17, 14, 6, -16 }, // 0x21 '!'
|
||||
{ 8, 8, 6, 14, 3, -16 }, // 0x22 '"'
|
||||
{ 14, 13, 17, 14, 0, -16 }, // 0x23 '#'
|
||||
{ 42, 10, 20, 14, 2, -17 }, // 0x24 '$'
|
||||
{ 67, 13, 17, 14, 0, -16 }, // 0x25 '%'
|
||||
{ 95, 13, 17, 14, 1, -16 }, // 0x26 '&'
|
||||
{ 123, 3, 6, 14, 5, -16 }, // 0x27 '''
|
||||
{ 126, 8, 21, 14, 3, -16 }, // 0x28 '('
|
||||
{ 147, 8, 21, 14, 3, -16 }, // 0x29 ')'
|
||||
{ 168, 12, 11, 14, 1, -17 }, // 0x2A '*'
|
||||
{ 185, 11, 11, 14, 1, -13 }, // 0x2B '+'
|
||||
{ 201, 4, 6, 14, 4, -2 }, // 0x2C ','
|
||||
{ 204, 8, 2, 14, 3, -6 }, // 0x2D '-'
|
||||
{ 206, 3, 3, 14, 5, -2 }, // 0x2E '.'
|
||||
{ 208, 10, 17, 14, 2, -16 }, // 0x2F '/'
|
||||
{ 230, 11, 17, 14, 1, -16 }, // 0x30 '0'
|
||||
{ 254, 6, 17, 14, 3, -16 }, // 0x31 '1'
|
||||
{ 267, 11, 17, 14, 2, -16 }, // 0x32 '2'
|
||||
{ 291, 10, 17, 14, 2, -16 }, // 0x33 '3'
|
||||
{ 313, 12, 17, 14, 1, -16 }, // 0x34 '4'
|
||||
{ 339, 10, 17, 14, 2, -16 }, // 0x35 '5'
|
||||
{ 361, 11, 17, 14, 1, -16 }, // 0x36 '6'
|
||||
{ 385, 11, 17, 14, 1, -16 }, // 0x37 '7'
|
||||
{ 409, 11, 17, 14, 1, -16 }, // 0x38 '8'
|
||||
{ 433, 11, 17, 14, 1, -16 }, // 0x39 '9'
|
||||
{ 457, 3, 13, 14, 5, -12 }, // 0x3A ':'
|
||||
{ 462, 4, 16, 14, 4, -12 }, // 0x3B ';'
|
||||
{ 470, 10, 12, 14, 2, -13 }, // 0x3C '<'
|
||||
{ 485, 10, 7, 14, 2, -11 }, // 0x3D '='
|
||||
{ 494, 10, 12, 14, 2, -13 }, // 0x3E '>'
|
||||
{ 509, 10, 17, 14, 2, -16 }, // 0x3F '?'
|
||||
{ 531, 14, 19, 14, 0, -16 }, // 0x40 '@'
|
||||
{ 565, 14, 17, 14, 0, -16 }, // 0x41 'A'
|
||||
{ 595, 12, 17, 14, 1, -16 }, // 0x42 'B'
|
||||
{ 621, 12, 17, 14, 1, -16 }, // 0x43 'C'
|
||||
{ 647, 12, 17, 14, 1, -16 }, // 0x44 'D'
|
||||
{ 673, 10, 17, 14, 2, -16 }, // 0x45 'E'
|
||||
{ 695, 10, 17, 14, 2, -16 }, // 0x46 'F'
|
||||
{ 717, 11, 17, 14, 1, -16 }, // 0x47 'G'
|
||||
{ 741, 11, 17, 14, 1, -16 }, // 0x48 'H'
|
||||
{ 765, 9, 17, 14, 3, -16 }, // 0x49 'I'
|
||||
{ 785, 10, 17, 14, 1, -16 }, // 0x4A 'J'
|
||||
{ 807, 11, 17, 14, 2, -16 }, // 0x4B 'K'
|
||||
{ 831, 10, 17, 14, 2, -16 }, // 0x4C 'L'
|
||||
{ 853, 11, 17, 14, 1, -16 }, // 0x4D 'M'
|
||||
{ 877, 11, 17, 14, 1, -16 }, // 0x4E 'N'
|
||||
{ 901, 12, 17, 14, 1, -16 }, // 0x4F 'O'
|
||||
{ 927, 11, 17, 14, 2, -16 }, // 0x50 'P'
|
||||
{ 951, 12, 22, 14, 1, -16 }, // 0x51 'Q'
|
||||
{ 984, 11, 17, 14, 2, -16 }, // 0x52 'R'
|
||||
{ 1008, 10, 17, 14, 2, -16 }, // 0x53 'S'
|
||||
{ 1030, 12, 17, 14, 1, -16 }, // 0x54 'T'
|
||||
{ 1056, 11, 17, 14, 1, -16 }, // 0x55 'U'
|
||||
{ 1080, 14, 17, 14, 0, -16 }, // 0x56 'V'
|
||||
{ 1110, 14, 17, 14, 0, -16 }, // 0x57 'W'
|
||||
{ 1140, 12, 17, 14, 1, -16 }, // 0x58 'X'
|
||||
{ 1166, 12, 17, 14, 1, -16 }, // 0x59 'Y'
|
||||
{ 1192, 12, 17, 14, 1, -16 }, // 0x5A 'Z'
|
||||
{ 1218, 6, 21, 14, 5, -16 }, // 0x5B '['
|
||||
{ 1234, 10, 17, 14, 2, -16 }, // 0x5C '\'
|
||||
{ 1256, 6, 21, 14, 2, -16 }, // 0x5D ']'
|
||||
{ 1272, 12, 11, 14, 1, -16 }, // 0x5E '^'
|
||||
{ 1289, 14, 1, 14, 0, 3 }, // 0x5F '_'
|
||||
{ 1291, 5, 4, 14, 4, -18 }, // 0x60 '`'
|
||||
{ 1294, 10, 13, 14, 2, -12 }, // 0x61 'a'
|
||||
{ 1311, 11, 18, 14, 2, -17 }, // 0x62 'b'
|
||||
{ 1336, 10, 13, 14, 2, -12 }, // 0x63 'c'
|
||||
{ 1353, 11, 18, 14, 1, -17 }, // 0x64 'd'
|
||||
{ 1378, 12, 13, 14, 1, -12 }, // 0x65 'e'
|
||||
{ 1398, 12, 18, 14, 1, -17 }, // 0x66 'f'
|
||||
{ 1425, 13, 19, 14, 1, -12 }, // 0x67 'g'
|
||||
{ 1456, 10, 18, 14, 2, -17 }, // 0x68 'h'
|
||||
{ 1479, 10, 18, 14, 2, -17 }, // 0x69 'i'
|
||||
{ 1502, 8, 24, 14, 2, -17 }, // 0x6A 'j'
|
||||
{ 1526, 10, 18, 14, 3, -17 }, // 0x6B 'k'
|
||||
{ 1549, 10, 18, 14, 2, -17 }, // 0x6C 'l'
|
||||
{ 1572, 12, 13, 14, 1, -12 }, // 0x6D 'm'
|
||||
{ 1592, 10, 13, 14, 2, -12 }, // 0x6E 'n'
|
||||
{ 1609, 12, 13, 14, 1, -12 }, // 0x6F 'o'
|
||||
{ 1629, 11, 19, 14, 2, -12 }, // 0x70 'p'
|
||||
{ 1656, 11, 19, 14, 1, -12 }, // 0x71 'q'
|
||||
{ 1683, 9, 13, 14, 3, -12 }, // 0x72 'r'
|
||||
{ 1698, 10, 13, 14, 2, -12 }, // 0x73 's'
|
||||
{ 1715, 10, 16, 14, 2, -15 }, // 0x74 't'
|
||||
{ 1735, 10, 13, 14, 2, -12 }, // 0x75 'u'
|
||||
{ 1752, 12, 13, 14, 1, -12 }, // 0x76 'v'
|
||||
{ 1772, 14, 13, 14, 0, -12 }, // 0x77 'w'
|
||||
{ 1795, 12, 13, 14, 1, -12 }, // 0x78 'x'
|
||||
{ 1815, 12, 19, 14, 1, -12 }, // 0x79 'y'
|
||||
{ 1844, 10, 13, 14, 2, -12 }, // 0x7A 'z'
|
||||
{ 1861, 9, 21, 14, 2, -16 }, // 0x7B '{'
|
||||
{ 1885, 2, 24, 14, 6, -17 }, // 0x7C '|'
|
||||
{ 1891, 9, 21, 14, 3, -16 }, // 0x7D '}'
|
||||
{ 1915, 10, 3, 14, 2, -9 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont NotoMono12pt7b PROGMEM = {
|
||||
(uint8_t *)NotoMono12pt7bBitmaps,
|
||||
(GFXglyph *)NotoMono12pt7bGlyphs,
|
||||
0x20, 0x7E, 28 };
|
||||
|
||||
// Approx. 2591 bytes
|
382
hardware/sd_card_formatter/src/guislice/NotoMono16pt7b.h
Normal file
382
hardware/sd_card_formatter/src/guislice/NotoMono16pt7b.h
Normal file
|
@ -0,0 +1,382 @@
|
|||
const uint8_t NotoMono16pt7bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0xFE, 0xE6, 0x66, 0x66, 0x66, 0x66, 0x60, 0x00, 0xEF, 0xFE,
|
||||
0xF1, 0xFC, 0x3B, 0x87, 0x70, 0xEE, 0x1D, 0xC3, 0xB8, 0x73, 0x06, 0x03,
|
||||
0x06, 0x03, 0x83, 0x01, 0xC3, 0x80, 0xC1, 0x80, 0x60, 0xC0, 0x30, 0x61,
|
||||
0xFF, 0xFE, 0xFF, 0xFF, 0x0C, 0x18, 0x06, 0x0C, 0x03, 0x06, 0x01, 0x83,
|
||||
0x00, 0xC1, 0x87, 0xFF, 0xFB, 0xFF, 0xFC, 0x30, 0x60, 0x18, 0x30, 0x0C,
|
||||
0x18, 0x06, 0x0C, 0x07, 0x0E, 0x03, 0x07, 0x01, 0x83, 0x00, 0x03, 0x00,
|
||||
0x18, 0x00, 0xC0, 0x1F, 0xC3, 0xFF, 0x3D, 0xBB, 0x8C, 0x1C, 0x60, 0xE3,
|
||||
0x07, 0x18, 0x1E, 0xC0, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x0D, 0xC0, 0x67,
|
||||
0x03, 0x38, 0x19, 0xC0, 0xCF, 0xF7, 0xEF, 0xFE, 0x1F, 0xC0, 0x0C, 0x00,
|
||||
0x60, 0x03, 0x00, 0x3E, 0x07, 0x0F, 0xE0, 0xC1, 0x8C, 0x38, 0x71, 0xC6,
|
||||
0x0C, 0x19, 0xC1, 0x83, 0x30, 0x30, 0x6E, 0x07, 0x1D, 0x80, 0x63, 0x70,
|
||||
0x0F, 0xEC, 0x00, 0xF9, 0x80, 0x00, 0x67, 0xC0, 0x0D, 0xFC, 0x03, 0xB1,
|
||||
0x80, 0x6E, 0x38, 0x1D, 0x83, 0x03, 0x30, 0x60, 0xE6, 0x0C, 0x18, 0xE3,
|
||||
0x87, 0x0C, 0x60, 0xC1, 0xFC, 0x38, 0x1F, 0x00, 0x07, 0xC0, 0x07, 0xFC,
|
||||
0x03, 0xC7, 0x80, 0xE0, 0xE0, 0x38, 0x38, 0x0E, 0x0E, 0x03, 0x83, 0x80,
|
||||
0x71, 0xC0, 0x1F, 0xE0, 0x03, 0xF0, 0x00, 0xF0, 0x00, 0xFE, 0x00, 0x79,
|
||||
0xC3, 0x9C, 0x78, 0xEE, 0x0F, 0x73, 0x81, 0xFC, 0xE0, 0x3E, 0x38, 0x07,
|
||||
0x8F, 0x03, 0xE1, 0xF7, 0xFC, 0x3F, 0xE7, 0x87, 0xE0, 0xF0, 0xFE, 0xEE,
|
||||
0xEE, 0xE6, 0x01, 0xC0, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x0E, 0x03,
|
||||
0x80, 0x70, 0x0C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00,
|
||||
0xE0, 0x0C, 0x01, 0xC0, 0x38, 0x03, 0x80, 0x70, 0x07, 0x00, 0x70, 0x07,
|
||||
0x00, 0x70, 0x07, 0x00, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x0E, 0x01, 0xC0,
|
||||
0x70, 0x0E, 0x03, 0x80, 0x70, 0x1C, 0x07, 0x01, 0xC0, 0x70, 0x1C, 0x07,
|
||||
0x01, 0xC0, 0x70, 0x38, 0x0E, 0x03, 0x01, 0xC0, 0xE0, 0x38, 0x1C, 0x0E,
|
||||
0x07, 0x00, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x04, 0x18, 0x2F,
|
||||
0x37, 0xFF, 0xFF, 0x83, 0xF0, 0x07, 0xC0, 0x0D, 0xC0, 0x3B, 0x80, 0xE3,
|
||||
0x83, 0xC7, 0x81, 0x04, 0x00, 0x03, 0x00, 0x0C, 0x00, 0x30, 0x00, 0xC0,
|
||||
0x03, 0x00, 0x0C, 0x0F, 0xFF, 0xFF, 0xFF, 0x03, 0x00, 0x0C, 0x00, 0x30,
|
||||
0x00, 0xC0, 0x03, 0x00, 0x0C, 0x00, 0x7B, 0xDC, 0xE7, 0x73, 0x98, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0x80, 0x77, 0xFF, 0xF7, 0x00, 0x00, 0x38, 0x01, 0x80,
|
||||
0x1C, 0x00, 0xC0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x38, 0x03, 0x80, 0x1C,
|
||||
0x01, 0xC0, 0x0E, 0x00, 0xE0, 0x07, 0x00, 0x30, 0x03, 0x80, 0x18, 0x01,
|
||||
0xC0, 0x0C, 0x00, 0xE0, 0x06, 0x00, 0x70, 0x00, 0x07, 0xC0, 0x3F, 0xE0,
|
||||
0xF1, 0xE3, 0xC1, 0xC7, 0x01, 0xCC, 0x01, 0xB8, 0x03, 0xF0, 0x07, 0xE0,
|
||||
0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03,
|
||||
0xF0, 0x07, 0x60, 0x0C, 0xE0, 0x39, 0xE0, 0xF1, 0xE3, 0xC1, 0xFF, 0x00,
|
||||
0xF8, 0x00, 0x07, 0x1F, 0x3F, 0x77, 0xE7, 0x47, 0x07, 0x07, 0x07, 0x07,
|
||||
0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
|
||||
0x0F, 0xC0, 0x7F, 0xE3, 0xF3, 0xE3, 0x01, 0xE0, 0x01, 0xC0, 0x03, 0x80,
|
||||
0x07, 0x00, 0x0E, 0x00, 0x18, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1E,
|
||||
0x00, 0x78, 0x01, 0xE0, 0x07, 0x80, 0x1C, 0x00, 0x70, 0x01, 0xC0, 0x07,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x1F, 0xC1, 0xFF, 0x8F, 0xCF, 0x10,
|
||||
0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x1C, 0x00, 0xF0, 0x7F, 0x01,
|
||||
0xFC, 0x00, 0x7C, 0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x07, 0x00, 0x1C,
|
||||
0x00, 0x78, 0x03, 0xBE, 0x7E, 0xFF, 0xF0, 0xFE, 0x00, 0x00, 0x38, 0x00,
|
||||
0x78, 0x00, 0xF8, 0x00, 0xF8, 0x01, 0xF8, 0x03, 0xB8, 0x03, 0x38, 0x07,
|
||||
0x38, 0x0E, 0x38, 0x0C, 0x38, 0x1C, 0x38, 0x38, 0x38, 0x30, 0x38, 0x70,
|
||||
0x38, 0xE0, 0x38, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x38, 0x00,
|
||||
0x38, 0x00, 0x38, 0x00, 0x38, 0x7F, 0xE3, 0xFF, 0x1F, 0xF8, 0xC0, 0x0E,
|
||||
0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xFF, 0x87, 0xFF, 0x18, 0xFC, 0x00,
|
||||
0xE0, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x1D,
|
||||
0xE7, 0xCF, 0xFC, 0x1F, 0xC0, 0x01, 0xF8, 0x1F, 0xF0, 0x7E, 0x21, 0xE0,
|
||||
0x03, 0x80, 0x0E, 0x00, 0x1C, 0x00, 0x30, 0x00, 0xE3, 0xE1, 0xDF, 0xF3,
|
||||
0xF0, 0xF7, 0x80, 0xEE, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0,
|
||||
0x0E, 0xE0, 0x1D, 0xE0, 0x71, 0xF3, 0xC1, 0xFF, 0x00, 0xFC, 0x00, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xF8, 0x00, 0x60, 0x01, 0xC0, 0x03, 0x80, 0x0E,
|
||||
0x00, 0x1C, 0x00, 0x70, 0x00, 0xE0, 0x03, 0x80, 0x07, 0x00, 0x1C, 0x00,
|
||||
0x38, 0x00, 0x60, 0x01, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x70,
|
||||
0x00, 0xE0, 0x03, 0x80, 0x00, 0x07, 0xE0, 0x3F, 0xE0, 0xF1, 0xE3, 0x80,
|
||||
0xE7, 0x01, 0xCE, 0x03, 0x9C, 0x07, 0x1C, 0x1C, 0x3C, 0x78, 0x3F, 0xC0,
|
||||
0x1F, 0x00, 0xFF, 0x83, 0x87, 0x8E, 0x03, 0xB8, 0x03, 0xF0, 0x07, 0xE0,
|
||||
0x0F, 0xC0, 0x1F, 0xC0, 0x73, 0xE3, 0xE3, 0xFF, 0x81, 0xFC, 0x00, 0x0F,
|
||||
0xC0, 0x7F, 0xE1, 0xF3, 0xE3, 0x81, 0xEE, 0x01, 0xDC, 0x01, 0xB8, 0x03,
|
||||
0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1D, 0xC0, 0x7B, 0xC3, 0xF3, 0xFE, 0xE1,
|
||||
0xF1, 0xC0, 0x03, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xE1, 0x0F,
|
||||
0x83, 0xFE, 0x07, 0xE0, 0x00, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x0F,
|
||||
0xFF, 0xF0, 0x7B, 0xDE, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3D, 0xEE,
|
||||
0x73, 0xB9, 0xCC, 0x00, 0x00, 0x02, 0x00, 0x1C, 0x01, 0xF8, 0x0F, 0xC0,
|
||||
0x7C, 0x03, 0xE0, 0x3F, 0x00, 0x70, 0x00, 0x7C, 0x00, 0x3E, 0x00, 0x1F,
|
||||
0x00, 0x0F, 0xC0, 0x07, 0xE0, 0x01, 0xC0, 0x00, 0x80, 0xFF, 0xFF, 0xFF,
|
||||
0xFC, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3F, 0xFF, 0xFF, 0xFF,
|
||||
0x80, 0x01, 0xC0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0x7C, 0x00, 0x3E, 0x00,
|
||||
0x1F, 0x80, 0x07, 0x00, 0x7C, 0x03, 0xE0, 0x1F, 0x01, 0xF8, 0x0F, 0xC0,
|
||||
0x1C, 0x00, 0x20, 0x00, 0x00, 0x1F, 0x87, 0xFF, 0x3F, 0x7C, 0x80, 0x70,
|
||||
0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x70, 0x0F, 0x00, 0xF0, 0x0F,
|
||||
0x00, 0x70, 0x03, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xC0,
|
||||
0x1E, 0x00, 0xF0, 0x03, 0x00, 0x01, 0xF8, 0x00, 0xFF, 0xC0, 0x38, 0x1C,
|
||||
0x0E, 0x01, 0xC3, 0x80, 0x1C, 0xE0, 0x01, 0x98, 0x3F, 0x33, 0x1F, 0xE7,
|
||||
0xE7, 0x0C, 0x78, 0xC1, 0x8F, 0x38, 0x31, 0xE7, 0x06, 0x3C, 0xC0, 0xC7,
|
||||
0x98, 0x38, 0xF3, 0x07, 0x1E, 0x70, 0xE6, 0xC6, 0x34, 0xDC, 0xFE, 0xF9,
|
||||
0x8F, 0x8E, 0x38, 0x00, 0x03, 0x00, 0x00, 0x70, 0x00, 0x07, 0x80, 0xC0,
|
||||
0x3F, 0xF8, 0x01, 0xFC, 0x00, 0x01, 0xE0, 0x00, 0x78, 0x00, 0x1E, 0x00,
|
||||
0x0F, 0xC0, 0x03, 0xF0, 0x00, 0xCC, 0x00, 0x73, 0x80, 0x1C, 0xE0, 0x06,
|
||||
0x18, 0x03, 0x87, 0x00, 0xE1, 0xC0, 0x38, 0x30, 0x1C, 0x0E, 0x07, 0xFF,
|
||||
0x81, 0xFF, 0xE0, 0xE0, 0x1C, 0x38, 0x07, 0x0C, 0x00, 0xC7, 0x00, 0x39,
|
||||
0xC0, 0x0E, 0xE0, 0x01, 0xB8, 0x00, 0x70, 0xFF, 0xE0, 0xFF, 0xF8, 0xE0,
|
||||
0xFC, 0xE0, 0x1E, 0xE0, 0x0E, 0xE0, 0x0E, 0xE0, 0x0E, 0xE0, 0x0E, 0xE0,
|
||||
0x3C, 0xFF, 0xF0, 0xFF, 0xF0, 0xE0, 0x7C, 0xE0, 0x0E, 0xE0, 0x07, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0E, 0xE0, 0x7E, 0xFF,
|
||||
0xFC, 0xFF, 0xF0, 0x01, 0xFC, 0x0F, 0xFF, 0x1F, 0xFE, 0x3C, 0x02, 0x38,
|
||||
0x00, 0x70, 0x00, 0x70, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0,
|
||||
0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x70,
|
||||
0x00, 0x78, 0x00, 0x3C, 0x00, 0x1F, 0xFE, 0x0F, 0xFE, 0x03, 0xFC, 0xFF,
|
||||
0x80, 0xFF, 0xF0, 0xE3, 0xF8, 0xE0, 0x3C, 0xE0, 0x1C, 0xE0, 0x0E, 0xE0,
|
||||
0x0E, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0,
|
||||
0x07, 0xE0, 0x07, 0xE0, 0x07, 0xE0, 0x0E, 0xE0, 0x0E, 0xE0, 0x1C, 0xE0,
|
||||
0x7C, 0xE3, 0xF8, 0xFF, 0xE0, 0xFF, 0x80, 0xFF, 0xFF, 0xFF, 0xF8, 0x01,
|
||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0xFF, 0xBF,
|
||||
0xFD, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00,
|
||||
0x38, 0x01, 0xC0, 0x0F, 0xFF, 0xFF, 0xFC, 0xFF, 0xFF, 0xFF, 0xF8, 0x01,
|
||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x3F,
|
||||
0xFD, 0xFF, 0xEE, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00,
|
||||
0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x00, 0x03, 0xF8, 0x1F, 0xFC, 0x7F,
|
||||
0xF1, 0xE0, 0x27, 0x80, 0x0E, 0x00, 0x1C, 0x00, 0x70, 0x00, 0xE0, 0x01,
|
||||
0xC0, 0x03, 0x81, 0xFF, 0x03, 0xFE, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xB8,
|
||||
0x07, 0x70, 0x0E, 0xF0, 0x1C, 0xF0, 0x38, 0xFF, 0xF0, 0xFF, 0xE0, 0xFF,
|
||||
0x00, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01,
|
||||
0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x7E,
|
||||
0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80,
|
||||
0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xC0, 0xFF, 0xFF, 0xFC, 0x38, 0x07,
|
||||
0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00,
|
||||
0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x0F, 0xFF,
|
||||
0xFF, 0xC0, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C,
|
||||
0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80,
|
||||
0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x03, 0xC0, 0x1D, 0xFF, 0xCF, 0xFC,
|
||||
0x3F, 0x80, 0xE0, 0x0F, 0xC0, 0x3B, 0x80, 0xE7, 0x03, 0x8E, 0x0E, 0x1C,
|
||||
0x38, 0x38, 0xF0, 0x71, 0xC0, 0xE7, 0x01, 0xDC, 0x03, 0xFC, 0x07, 0xF8,
|
||||
0x0F, 0x38, 0x1C, 0x78, 0x38, 0x70, 0x70, 0x70, 0xE0, 0xF1, 0xC0, 0xE3,
|
||||
0x80, 0xE7, 0x01, 0xEE, 0x01, 0xDC, 0x01, 0xC0, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xFF, 0xFF, 0xFF, 0xF0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7F, 0x81,
|
||||
0xFD, 0x83, 0x7B, 0x06, 0xF6, 0x0D, 0xEC, 0x1B, 0xD8, 0x77, 0x98, 0xCF,
|
||||
0x31, 0x9E, 0x63, 0x3C, 0xC6, 0x79, 0x98, 0xF1, 0xB1, 0xE3, 0x63, 0xC6,
|
||||
0xC7, 0x8D, 0x8F, 0x0E, 0x1E, 0x1C, 0x3C, 0x38, 0x78, 0x70, 0xC0, 0xE0,
|
||||
0x0F, 0xE0, 0x1F, 0xE0, 0x3F, 0xC0, 0x7D, 0xC0, 0xFB, 0x81, 0xF3, 0x83,
|
||||
0xF7, 0x07, 0xE7, 0x0F, 0xCE, 0x1F, 0x8E, 0x3F, 0x1C, 0x7E, 0x1C, 0xFC,
|
||||
0x39, 0xF8, 0x3B, 0xF0, 0x77, 0xE0, 0x77, 0xC0, 0xEF, 0x80, 0xFF, 0x00,
|
||||
0xFE, 0x01, 0xFC, 0x01, 0xC0, 0x07, 0xF0, 0x0F, 0xFC, 0x0F, 0xDF, 0x87,
|
||||
0x01, 0xC7, 0x00, 0x73, 0x80, 0x3B, 0xC0, 0x1D, 0xC0, 0x07, 0xE0, 0x03,
|
||||
0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x3F, 0x00, 0x1F, 0x80,
|
||||
0x0F, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x8E, 0x03, 0x87, 0xEF, 0x81,
|
||||
0xFF, 0x80, 0x3F, 0x80, 0xFF, 0xC3, 0xFF, 0xCE, 0x1F, 0xB8, 0x0E, 0xE0,
|
||||
0x1F, 0x80, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0xEE, 0x07, 0xBF,
|
||||
0xFC, 0xFF, 0xC3, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E,
|
||||
0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x00, 0x07, 0xF0, 0x0F, 0xFC, 0x0F,
|
||||
0xDF, 0x87, 0x01, 0xC7, 0x00, 0x73, 0x80, 0x3B, 0xC0, 0x1D, 0xC0, 0x07,
|
||||
0xE0, 0x03, 0xF0, 0x01, 0xF8, 0x00, 0xFC, 0x00, 0x7E, 0x00, 0x3F, 0x00,
|
||||
0x1F, 0x80, 0x0F, 0xE0, 0x0E, 0x70, 0x07, 0x38, 0x03, 0x8E, 0x03, 0x87,
|
||||
0xEF, 0x81, 0xFF, 0x80, 0x3F, 0xC0, 0x00, 0xE0, 0x00, 0x38, 0x00, 0x1E,
|
||||
0x00, 0x07, 0xC0, 0x01, 0xC0, 0x00, 0x60, 0xFF, 0x81, 0xFF, 0xC3, 0x8F,
|
||||
0xC7, 0x03, 0x8E, 0x03, 0x9C, 0x07, 0x38, 0x0E, 0x70, 0x1C, 0xE0, 0x39,
|
||||
0xC0, 0xE3, 0x83, 0xC7, 0xFF, 0x0F, 0xF8, 0x1C, 0x70, 0x38, 0x70, 0x70,
|
||||
0x70, 0xE0, 0xE1, 0xC0, 0xE3, 0x80, 0xE7, 0x01, 0xEE, 0x01, 0xDC, 0x01,
|
||||
0xC0, 0x0F, 0xF8, 0x7F, 0xFD, 0xFF, 0xF7, 0x80, 0x2E, 0x00, 0x1C, 0x00,
|
||||
0x38, 0x00, 0x78, 0x00, 0x78, 0x00, 0x7C, 0x00, 0x7F, 0x00, 0x3F, 0x80,
|
||||
0x0F, 0xC0, 0x03, 0x80, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1E, 0x00,
|
||||
0x77, 0xE7, 0xEF, 0xFF, 0x87, 0xF8, 0x00, 0xFF, 0xFF, 0xFF, 0xFC, 0x0E,
|
||||
0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80,
|
||||
0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01,
|
||||
0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70,
|
||||
0x00, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01,
|
||||
0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E,
|
||||
0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xE0, 0x3D, 0xC0,
|
||||
0x73, 0xF7, 0xC3, 0xFF, 0x01, 0xFC, 0x00, 0xE0, 0x01, 0xD8, 0x00, 0xE7,
|
||||
0x00, 0x39, 0xC0, 0x0E, 0x30, 0x03, 0x0E, 0x01, 0xC3, 0x80, 0x70, 0x60,
|
||||
0x18, 0x1C, 0x0E, 0x07, 0x03, 0x80, 0xC0, 0xC0, 0x38, 0x70, 0x0E, 0x1C,
|
||||
0x01, 0x86, 0x00, 0x73, 0x80, 0x1C, 0xE0, 0x03, 0x30, 0x00, 0xFC, 0x00,
|
||||
0x3F, 0x00, 0x07, 0x80, 0x01, 0xE0, 0x00, 0x78, 0x00, 0xE0, 0x00, 0xFC,
|
||||
0x00, 0x1F, 0x80, 0x03, 0xB0, 0x00, 0x76, 0x00, 0x0C, 0xC0, 0x01, 0x9C,
|
||||
0x00, 0x33, 0x87, 0x06, 0x70, 0xE0, 0xCE, 0x36, 0x38, 0xC6, 0xC7, 0x18,
|
||||
0xD8, 0xE3, 0x1B, 0x98, 0x67, 0x33, 0x0E, 0xC6, 0x61, 0xD8, 0xEC, 0x3B,
|
||||
0x0D, 0x83, 0xC1, 0xB0, 0x78, 0x36, 0x0F, 0x03, 0xC1, 0xE0, 0x70, 0x38,
|
||||
0x0E, 0x00, 0xE0, 0x07, 0x38, 0x07, 0x0E, 0x03, 0x87, 0x03, 0x81, 0xC3,
|
||||
0x80, 0xE1, 0xC0, 0x39, 0xC0, 0x0E, 0xE0, 0x07, 0xE0, 0x01, 0xE0, 0x00,
|
||||
0x70, 0x00, 0x78, 0x00, 0x7E, 0x00, 0x3B, 0x80, 0x39, 0xC0, 0x1C, 0x70,
|
||||
0x1C, 0x1C, 0x0C, 0x0E, 0x0E, 0x03, 0x8E, 0x01, 0xC7, 0x00, 0x77, 0x00,
|
||||
0x1C, 0xE0, 0x03, 0xB8, 0x03, 0x9C, 0x01, 0xC7, 0x01, 0xC3, 0x80, 0xE0,
|
||||
0xE0, 0xE0, 0x30, 0x60, 0x1C, 0x70, 0x06, 0x30, 0x03, 0xB8, 0x00, 0xF8,
|
||||
0x00, 0x7C, 0x00, 0x1C, 0x00, 0x0E, 0x00, 0x07, 0x00, 0x03, 0x80, 0x01,
|
||||
0xC0, 0x00, 0xE0, 0x00, 0x70, 0x00, 0x38, 0x00, 0x1C, 0x00, 0x0E, 0x00,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x07, 0x00,
|
||||
0x1C, 0x00, 0x70, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x1C, 0x00, 0x70,
|
||||
0x01, 0xC0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0x70, 0x01, 0xC0, 0x07,
|
||||
0x00, 0x0F, 0xFF, 0xFF, 0xFF, 0xC0, 0xFF, 0xFF, 0xF8, 0x1C, 0x0E, 0x07,
|
||||
0x03, 0x81, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0,
|
||||
0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x7F, 0xFF,
|
||||
0xE0, 0xE0, 0x03, 0x00, 0x1C, 0x00, 0x60, 0x03, 0x80, 0x0C, 0x00, 0x70,
|
||||
0x01, 0x80, 0x0E, 0x00, 0x70, 0x01, 0xC0, 0x0E, 0x00, 0x38, 0x01, 0xC0,
|
||||
0x06, 0x00, 0x38, 0x00, 0xC0, 0x07, 0x00, 0x18, 0x00, 0xE0, 0x03, 0x00,
|
||||
0x1C, 0xFF, 0xFF, 0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81,
|
||||
0xC0, 0xE0, 0x70, 0x38, 0x1C, 0x0E, 0x07, 0x03, 0x81, 0xC0, 0xE0, 0x70,
|
||||
0x38, 0x1C, 0x0E, 0x07, 0x03, 0xFF, 0xFF, 0xE0, 0x03, 0x00, 0x07, 0x00,
|
||||
0x1E, 0x00, 0x3E, 0x00, 0xCC, 0x01, 0x9C, 0x07, 0x18, 0x0C, 0x38, 0x38,
|
||||
0x30, 0x60, 0x70, 0xC0, 0x63, 0x00, 0xE6, 0x00, 0xDC, 0x01, 0xC0, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFC, 0xF1, 0xC3, 0x86, 0x0C, 0x0F, 0xE1, 0xFF, 0xE3,
|
||||
0xC7, 0x80, 0x07, 0x00, 0x1C, 0x00, 0x70, 0x01, 0xC1, 0xFF, 0x3F, 0xFD,
|
||||
0xE0, 0x7E, 0x01, 0xF8, 0x07, 0xE0, 0x1F, 0x80, 0xFF, 0x0F, 0xDF, 0xF3,
|
||||
0x1F, 0x8C, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C,
|
||||
0x00, 0x38, 0x00, 0x73, 0xF0, 0xEF, 0xF1, 0xF8, 0xF3, 0xC0, 0x77, 0x00,
|
||||
0xEE, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F,
|
||||
0x80, 0x3F, 0x00, 0xEF, 0x01, 0xDF, 0x8F, 0x33, 0xFC, 0x63, 0xF0, 0x07,
|
||||
0xF0, 0xFF, 0xCF, 0xDC, 0xF0, 0x07, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00,
|
||||
0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x07, 0x00, 0x3C, 0x00, 0xFD, 0xE3,
|
||||
0xFF, 0x07, 0xF0, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00,
|
||||
0xE0, 0x01, 0xC0, 0x03, 0x87, 0xE7, 0x1F, 0xEE, 0x78, 0xFD, 0xC0, 0x7B,
|
||||
0x80, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x3B, 0x80, 0x77, 0x01, 0xE7, 0x8F, 0xC7, 0xF9, 0x87, 0xE3,
|
||||
0x07, 0xE0, 0x3F, 0xE0, 0xF1, 0xE3, 0x80, 0xE7, 0x00, 0xFC, 0x01, 0xF8,
|
||||
0x03, 0xFF, 0xFF, 0xFF, 0xFF, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x07, 0x00,
|
||||
0x0F, 0x00, 0x0F, 0xDF, 0x0F, 0xFE, 0x07, 0xF0, 0x00, 0xFE, 0x07, 0xFC,
|
||||
0x0E, 0x10, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0, 0x7F, 0xFE, 0xFF,
|
||||
0xFC, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0xE0, 0x01, 0xC0,
|
||||
0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00,
|
||||
0xE0, 0x01, 0xC0, 0x03, 0x80, 0x0F, 0xFE, 0x3F, 0xFC, 0xE1, 0xC3, 0x81,
|
||||
0xC7, 0x03, 0x8E, 0x07, 0x1C, 0x0E, 0x38, 0x1C, 0x38, 0x70, 0x7F, 0xC0,
|
||||
0x3F, 0x00, 0xC0, 0x03, 0x00, 0x07, 0x00, 0x0F, 0xFE, 0x0F, 0xFE, 0x78,
|
||||
0x7F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFE, 0x07, 0x9F, 0xFE,
|
||||
0x0F, 0xF0, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C,
|
||||
0x00, 0x38, 0x00, 0x71, 0xF8, 0xEF, 0xF9, 0xFC, 0x7B, 0xC0, 0x7F, 0x80,
|
||||
0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F,
|
||||
0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0x07,
|
||||
0x00, 0x38, 0x01, 0xC0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0F, 0xE0,
|
||||
0x7F, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00,
|
||||
0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x83, 0xFF,
|
||||
0xFF, 0xFF, 0x00, 0xE0, 0x1C, 0x03, 0x80, 0x00, 0x00, 0x00, 0x00, 0x01,
|
||||
0xFF, 0x3F, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07,
|
||||
0x00, 0xE0, 0x1C, 0x03, 0x80, 0x70, 0x0E, 0x01, 0xC0, 0x38, 0x07, 0x00,
|
||||
0xE0, 0x1C, 0x03, 0x80, 0x7C, 0x3D, 0xFF, 0x3F, 0xC0, 0xE0, 0x01, 0xC0,
|
||||
0x03, 0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x0E,
|
||||
0xE0, 0x39, 0xC0, 0xE3, 0x83, 0x87, 0x0E, 0x0E, 0x38, 0x1D, 0xE0, 0x3F,
|
||||
0x80, 0x7F, 0x80, 0xF7, 0x81, 0xC7, 0x03, 0x87, 0x07, 0x07, 0x0E, 0x07,
|
||||
0x1C, 0x07, 0x38, 0x0F, 0x70, 0x0F, 0x7F, 0x03, 0xF8, 0x01, 0xC0, 0x0E,
|
||||
0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0,
|
||||
0x0E, 0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
|
||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0x83, 0xFF, 0xFF, 0xFF, 0xCF, 0x1E, 0x6F,
|
||||
0xDF, 0xBC, 0xED, 0xFC, 0x38, 0x7E, 0x1C, 0x3F, 0x0E, 0x1F, 0x87, 0x0F,
|
||||
0xC3, 0x87, 0xE1, 0xC3, 0xF0, 0xE1, 0xF8, 0x70, 0xFC, 0x38, 0x7E, 0x1C,
|
||||
0x3F, 0x0E, 0x1F, 0x87, 0x0F, 0xC3, 0x87, 0xE1, 0xC3, 0x80, 0xC3, 0xF1,
|
||||
0x9F, 0xF3, 0xF8, 0xF7, 0x80, 0xFF, 0x00, 0xFC, 0x01, 0xF8, 0x03, 0xF0,
|
||||
0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00, 0xFC, 0x01,
|
||||
0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0E, 0x07, 0xC0, 0x3F, 0xE0, 0xF1, 0xE3,
|
||||
0x80, 0xE7, 0x01, 0xDC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0,
|
||||
0x1F, 0x80, 0x3F, 0x00, 0x77, 0x01, 0xCE, 0x03, 0x8F, 0x1E, 0x0F, 0xF8,
|
||||
0x07, 0xC0, 0xC7, 0xE1, 0xDF, 0xE3, 0xF1, 0xE7, 0x80, 0xEE, 0x01, 0xDC,
|
||||
0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00,
|
||||
0x7E, 0x01, 0xDE, 0x03, 0xBF, 0x1E, 0x77, 0xF8, 0xE7, 0xE1, 0xC0, 0x03,
|
||||
0x80, 0x07, 0x00, 0x0E, 0x00, 0x1C, 0x00, 0x38, 0x00, 0x70, 0x00, 0x0F,
|
||||
0xC6, 0x3F, 0xCC, 0xF1, 0xFB, 0x80, 0xF7, 0x00, 0xFC, 0x01, 0xF8, 0x03,
|
||||
0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x77, 0x00, 0xEE,
|
||||
0x03, 0xCF, 0x1F, 0x8F, 0xF7, 0x0F, 0xCE, 0x00, 0x1C, 0x00, 0x38, 0x00,
|
||||
0x70, 0x00, 0xE0, 0x01, 0xC0, 0x03, 0x80, 0x07, 0xC3, 0xEC, 0xFF, 0xDE,
|
||||
0x6F, 0x00, 0xF0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0,
|
||||
0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0xE0, 0x00, 0x1F, 0xE3,
|
||||
0xFF, 0xFE, 0x1D, 0xC0, 0x0E, 0x00, 0x70, 0x01, 0xE0, 0x07, 0xE0, 0x0F,
|
||||
0xC0, 0x1F, 0x80, 0x1E, 0x00, 0x70, 0x03, 0x80, 0x1F, 0xC3, 0xDF, 0xFC,
|
||||
0x7F, 0x80, 0x06, 0x00, 0x18, 0x00, 0xE0, 0x03, 0x80, 0x7F, 0xFF, 0xFF,
|
||||
0xF0, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E,
|
||||
0x00, 0x38, 0x00, 0xE0, 0x03, 0x80, 0x0E, 0x00, 0x38, 0x00, 0x70, 0x41,
|
||||
0xFF, 0x01, 0xFC, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F, 0x00, 0x7E, 0x00,
|
||||
0xFC, 0x01, 0xF8, 0x03, 0xF0, 0x07, 0xE0, 0x0F, 0xC0, 0x1F, 0x80, 0x3F,
|
||||
0x00, 0x7E, 0x00, 0xFE, 0x03, 0xDE, 0x3F, 0x9F, 0xF3, 0x1F, 0x86, 0xE0,
|
||||
0x03, 0xB0, 0x01, 0x9C, 0x01, 0xCE, 0x00, 0xE3, 0x80, 0xE1, 0xC0, 0x70,
|
||||
0x60, 0x30, 0x38, 0x38, 0x1C, 0x1C, 0x07, 0x1C, 0x03, 0x8E, 0x00, 0xC6,
|
||||
0x00, 0x77, 0x00, 0x3B, 0x80, 0x0D, 0x80, 0x07, 0xC0, 0x01, 0xE0, 0x00,
|
||||
0xE0, 0xE0, 0xFC, 0x1C, 0x1D, 0x83, 0xC3, 0x30, 0xD8, 0x66, 0x1B, 0x0C,
|
||||
0xE3, 0x61, 0x9C, 0x6C, 0x71, 0x9D, 0xCC, 0x33, 0x19, 0x86, 0x63, 0x30,
|
||||
0xCC, 0x66, 0x1D, 0x8D, 0xC1, 0xE0, 0xF0, 0x3C, 0x1E, 0x07, 0x83, 0xC0,
|
||||
0xF0, 0x78, 0x1E, 0x0F, 0x00, 0x70, 0x07, 0x3C, 0x07, 0x8E, 0x03, 0x83,
|
||||
0x83, 0x80, 0xE3, 0x80, 0x3B, 0x80, 0x1F, 0xC0, 0x07, 0xC0, 0x01, 0xC0,
|
||||
0x01, 0xF0, 0x01, 0xDC, 0x01, 0xE7, 0x00, 0xE3, 0x80, 0xE0, 0xE0, 0xE0,
|
||||
0x38, 0xE0, 0x0E, 0xF0, 0x07, 0x80, 0xE0, 0x03, 0xB0, 0x01, 0x9C, 0x01,
|
||||
0xCE, 0x00, 0xE3, 0x80, 0xE1, 0xC0, 0x70, 0x70, 0x30, 0x38, 0x38, 0x0C,
|
||||
0x1C, 0x07, 0x1C, 0x03, 0x8E, 0x00, 0xEE, 0x00, 0x77, 0x00, 0x1B, 0x00,
|
||||
0x0F, 0x80, 0x03, 0xC0, 0x01, 0xC0, 0x00, 0xE0, 0x00, 0x60, 0x00, 0x70,
|
||||
0x00, 0x70, 0x00, 0x78, 0x03, 0xF8, 0x01, 0xF0, 0x00, 0x7F, 0xFB, 0xFF,
|
||||
0xC0, 0x0E, 0x00, 0xE0, 0x0E, 0x00, 0x60, 0x07, 0x00, 0x70, 0x07, 0x00,
|
||||
0x70, 0x03, 0x00, 0x38, 0x03, 0x80, 0x38, 0x03, 0x80, 0x1F, 0xFF, 0xFF,
|
||||
0xF8, 0x00, 0x78, 0x0F, 0xC0, 0xF8, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E,
|
||||
0x00, 0x70, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x1E, 0x0F, 0xE0, 0x7E, 0x00,
|
||||
0x7C, 0x00, 0xE0, 0x03, 0x80, 0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01,
|
||||
0xC0, 0x0E, 0x00, 0x70, 0x03, 0xE0, 0x0F, 0xC0, 0x1E, 0xFF, 0xFF, 0xFF,
|
||||
0xFF, 0xFF, 0xFF, 0xFF, 0xFC, 0xF0, 0x07, 0xE0, 0x0F, 0x80, 0x1C, 0x00,
|
||||
0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x0E, 0x00, 0x70, 0x03, 0x80, 0x0F,
|
||||
0x00, 0x3F, 0x80, 0xFC, 0x1F, 0x00, 0xE0, 0x0E, 0x00, 0x70, 0x03, 0x80,
|
||||
0x1C, 0x00, 0xE0, 0x07, 0x00, 0x38, 0x01, 0xC0, 0x3C, 0x07, 0xE0, 0x3C,
|
||||
0x00, 0x3E, 0x03, 0xFF, 0x9F, 0x9F, 0xFC, 0x07, 0xC0 };
|
||||
|
||||
const GFXglyph NotoMono16pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 19, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 4, 22, 19, 8, -21 }, // 0x21 '!'
|
||||
{ 12, 11, 8, 19, 4, -21 }, // 0x22 '"'
|
||||
{ 23, 17, 22, 19, 1, -21 }, // 0x23 '#'
|
||||
{ 70, 13, 25, 19, 3, -23 }, // 0x24 '$'
|
||||
{ 111, 19, 22, 19, 0, -21 }, // 0x25 '%'
|
||||
{ 164, 18, 22, 19, 1, -21 }, // 0x26 '&'
|
||||
{ 214, 4, 8, 19, 8, -21 }, // 0x27 '''
|
||||
{ 218, 11, 27, 19, 4, -21 }, // 0x28 '('
|
||||
{ 256, 10, 27, 19, 5, -21 }, // 0x29 ')'
|
||||
{ 290, 15, 14, 19, 2, -23 }, // 0x2A '*'
|
||||
{ 317, 14, 14, 19, 2, -17 }, // 0x2B '+'
|
||||
{ 342, 5, 8, 19, 7, -3 }, // 0x2C ','
|
||||
{ 347, 11, 3, 19, 4, -9 }, // 0x2D '-'
|
||||
{ 352, 5, 5, 19, 7, -4 }, // 0x2E '.'
|
||||
{ 356, 13, 22, 19, 3, -21 }, // 0x2F '/'
|
||||
{ 392, 15, 22, 19, 2, -21 }, // 0x30 '0'
|
||||
{ 434, 8, 22, 19, 4, -21 }, // 0x31 '1'
|
||||
{ 456, 15, 22, 19, 2, -21 }, // 0x32 '2'
|
||||
{ 498, 14, 22, 19, 2, -21 }, // 0x33 '3'
|
||||
{ 537, 16, 22, 19, 1, -21 }, // 0x34 '4'
|
||||
{ 581, 13, 22, 19, 3, -21 }, // 0x35 '5'
|
||||
{ 617, 15, 22, 19, 2, -21 }, // 0x36 '6'
|
||||
{ 659, 15, 22, 19, 2, -21 }, // 0x37 '7'
|
||||
{ 701, 15, 22, 19, 2, -21 }, // 0x38 '8'
|
||||
{ 743, 15, 22, 19, 2, -21 }, // 0x39 '9'
|
||||
{ 785, 4, 17, 19, 8, -16 }, // 0x3A ':'
|
||||
{ 794, 5, 21, 19, 7, -16 }, // 0x3B ';'
|
||||
{ 808, 15, 15, 19, 2, -18 }, // 0x3C '<'
|
||||
{ 837, 15, 8, 19, 2, -14 }, // 0x3D '='
|
||||
{ 852, 15, 15, 19, 2, -18 }, // 0x3E '>'
|
||||
{ 881, 13, 22, 19, 3, -21 }, // 0x3F '?'
|
||||
{ 917, 19, 25, 19, 0, -21 }, // 0x40 '@'
|
||||
{ 977, 18, 22, 19, 1, -21 }, // 0x41 'A'
|
||||
{ 1027, 16, 22, 19, 2, -21 }, // 0x42 'B'
|
||||
{ 1071, 16, 22, 19, 2, -21 }, // 0x43 'C'
|
||||
{ 1115, 16, 22, 19, 2, -21 }, // 0x44 'D'
|
||||
{ 1159, 13, 22, 19, 3, -21 }, // 0x45 'E'
|
||||
{ 1195, 13, 22, 19, 4, -21 }, // 0x46 'F'
|
||||
{ 1231, 15, 22, 19, 2, -21 }, // 0x47 'G'
|
||||
{ 1273, 15, 22, 19, 2, -21 }, // 0x48 'H'
|
||||
{ 1315, 11, 22, 19, 4, -21 }, // 0x49 'I'
|
||||
{ 1346, 13, 22, 19, 2, -21 }, // 0x4A 'J'
|
||||
{ 1382, 15, 22, 19, 3, -21 }, // 0x4B 'K'
|
||||
{ 1424, 12, 22, 19, 4, -21 }, // 0x4C 'L'
|
||||
{ 1457, 15, 22, 19, 2, -21 }, // 0x4D 'M'
|
||||
{ 1499, 15, 22, 19, 2, -21 }, // 0x4E 'N'
|
||||
{ 1541, 17, 22, 19, 1, -21 }, // 0x4F 'O'
|
||||
{ 1588, 14, 22, 19, 3, -21 }, // 0x50 'P'
|
||||
{ 1627, 17, 28, 19, 1, -21 }, // 0x51 'Q'
|
||||
{ 1687, 15, 22, 19, 3, -21 }, // 0x52 'R'
|
||||
{ 1729, 15, 22, 19, 2, -21 }, // 0x53 'S'
|
||||
{ 1771, 15, 22, 19, 2, -21 }, // 0x54 'T'
|
||||
{ 1813, 15, 22, 19, 2, -21 }, // 0x55 'U'
|
||||
{ 1855, 18, 22, 19, 1, -21 }, // 0x56 'V'
|
||||
{ 1905, 19, 22, 19, 0, -21 }, // 0x57 'W'
|
||||
{ 1958, 17, 22, 19, 1, -21 }, // 0x58 'X'
|
||||
{ 2005, 17, 22, 19, 1, -21 }, // 0x59 'Y'
|
||||
{ 2052, 15, 22, 19, 2, -21 }, // 0x5A 'Z'
|
||||
{ 2094, 9, 27, 19, 6, -21 }, // 0x5B '['
|
||||
{ 2125, 13, 22, 19, 3, -21 }, // 0x5C '\'
|
||||
{ 2161, 9, 27, 19, 4, -21 }, // 0x5D ']'
|
||||
{ 2192, 15, 14, 19, 2, -21 }, // 0x5E '^'
|
||||
{ 2219, 19, 2, 19, 0, 4 }, // 0x5F '_'
|
||||
{ 2224, 6, 5, 19, 7, -23 }, // 0x60 '`'
|
||||
{ 2228, 14, 17, 19, 2, -16 }, // 0x61 'a'
|
||||
{ 2258, 15, 24, 19, 2, -23 }, // 0x62 'b'
|
||||
{ 2303, 13, 17, 19, 3, -16 }, // 0x63 'c'
|
||||
{ 2331, 15, 24, 19, 2, -23 }, // 0x64 'd'
|
||||
{ 2376, 15, 17, 19, 2, -16 }, // 0x65 'e'
|
||||
{ 2408, 15, 24, 19, 2, -23 }, // 0x66 'f'
|
||||
{ 2453, 15, 24, 19, 2, -16 }, // 0x67 'g'
|
||||
{ 2498, 15, 24, 19, 2, -23 }, // 0x68 'h'
|
||||
{ 2543, 13, 24, 19, 3, -23 }, // 0x69 'i'
|
||||
{ 2582, 11, 31, 19, 2, -23 }, // 0x6A 'j'
|
||||
{ 2625, 15, 24, 19, 3, -23 }, // 0x6B 'k'
|
||||
{ 2670, 13, 24, 19, 3, -23 }, // 0x6C 'l'
|
||||
{ 2709, 17, 17, 19, 1, -16 }, // 0x6D 'm'
|
||||
{ 2746, 15, 17, 19, 2, -16 }, // 0x6E 'n'
|
||||
{ 2778, 15, 17, 19, 2, -16 }, // 0x6F 'o'
|
||||
{ 2810, 15, 24, 19, 2, -16 }, // 0x70 'p'
|
||||
{ 2855, 15, 24, 19, 2, -16 }, // 0x71 'q'
|
||||
{ 2900, 12, 17, 19, 4, -16 }, // 0x72 'r'
|
||||
{ 2926, 13, 17, 19, 3, -16 }, // 0x73 's'
|
||||
{ 2954, 14, 21, 19, 2, -20 }, // 0x74 't'
|
||||
{ 2991, 15, 17, 19, 2, -16 }, // 0x75 'u'
|
||||
{ 3023, 17, 17, 19, 1, -16 }, // 0x76 'v'
|
||||
{ 3060, 19, 17, 19, 0, -16 }, // 0x77 'w'
|
||||
{ 3101, 17, 17, 19, 1, -16 }, // 0x78 'x'
|
||||
{ 3138, 17, 24, 19, 1, -16 }, // 0x79 'y'
|
||||
{ 3189, 13, 17, 19, 3, -16 }, // 0x7A 'z'
|
||||
{ 3217, 13, 27, 19, 3, -21 }, // 0x7B '{'
|
||||
{ 3261, 2, 31, 19, 8, -23 }, // 0x7C '|'
|
||||
{ 3269, 13, 27, 19, 3, -21 }, // 0x7D '}'
|
||||
{ 3313, 15, 4, 19, 2, -12 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont NotoMono16pt7b PROGMEM = {
|
||||
(uint8_t *)NotoMono16pt7bBitmaps,
|
||||
(GFXglyph *)NotoMono16pt7bGlyphs,
|
||||
0x20, 0x7E, 37 };
|
||||
|
||||
// Approx. 3993 bytes
|
185
hardware/sd_card_formatter/src/guislice/NotoMono8pt7b.h
Normal file
185
hardware/sd_card_formatter/src/guislice/NotoMono8pt7b.h
Normal file
|
@ -0,0 +1,185 @@
|
|||
const uint8_t NotoMono8pt7bBitmaps[] PROGMEM = {
|
||||
0x00, 0xFF, 0xFD, 0x0F, 0xCF, 0x3C, 0xF3, 0x08, 0x86, 0x61, 0x11, 0xFF,
|
||||
0x11, 0x0C, 0xC2, 0x23, 0xFE, 0x22, 0x08, 0x84, 0x41, 0x10, 0x10, 0x21,
|
||||
0xFE, 0x89, 0x1A, 0x1C, 0x0E, 0x16, 0x26, 0x5F, 0xE1, 0x02, 0x00, 0x71,
|
||||
0xA2, 0x48, 0xB2, 0x28, 0x74, 0x01, 0x00, 0x80, 0x2E, 0x14, 0x4D, 0x12,
|
||||
0x45, 0x8E, 0x38, 0x36, 0x11, 0x08, 0x82, 0x81, 0x89, 0xE5, 0x96, 0x86,
|
||||
0x63, 0x33, 0xCF, 0x30, 0xFF, 0x11, 0x98, 0x8C, 0x63, 0x10, 0xC6, 0x30,
|
||||
0x86, 0x18, 0x40, 0x43, 0x0C, 0x21, 0x8C, 0x61, 0x18, 0xC6, 0x23, 0x31,
|
||||
0x00, 0x10, 0x22, 0x4F, 0xF2, 0x8D, 0x99, 0x00, 0x10, 0x20, 0x47, 0xF1,
|
||||
0x02, 0x04, 0x00, 0x6F, 0x60, 0xFC, 0xF0, 0x0C, 0x20, 0x86, 0x10, 0xC3,
|
||||
0x08, 0x61, 0x04, 0x30, 0x3C, 0x66, 0x42, 0xC3, 0xC3, 0x81, 0x81, 0xC3,
|
||||
0xC3, 0x42, 0x66, 0x3C, 0x37, 0xD1, 0x11, 0x11, 0x11, 0x11, 0x3C, 0xE3,
|
||||
0x03, 0x01, 0x03, 0x02, 0x04, 0x08, 0x10, 0x20, 0xC0, 0xFF, 0x7E, 0xC3,
|
||||
0x03, 0x03, 0x06, 0x38, 0x06, 0x03, 0x01, 0x03, 0x86, 0xFC, 0x06, 0x07,
|
||||
0x02, 0x83, 0x43, 0x21, 0x11, 0x09, 0x84, 0xFF, 0x81, 0x00, 0x80, 0x40,
|
||||
0xFE, 0xC0, 0xC0, 0x80, 0x80, 0xFC, 0x06, 0x03, 0x01, 0x03, 0x86, 0xFC,
|
||||
0x1E, 0x30, 0x40, 0xC0, 0xFC, 0xE2, 0xC3, 0x81, 0xC1, 0xC3, 0x66, 0x3C,
|
||||
0xFF, 0x03, 0x02, 0x02, 0x06, 0x04, 0x0C, 0x0C, 0x18, 0x18, 0x10, 0x30,
|
||||
0x3C, 0xC3, 0x81, 0xC3, 0x46, 0x3C, 0x66, 0xC3, 0x81, 0xC3, 0xC2, 0x3C,
|
||||
0x3C, 0x66, 0xC3, 0x83, 0x81, 0xC3, 0x47, 0x3F, 0x03, 0x02, 0x04, 0x78,
|
||||
0xF0, 0x03, 0xC0, 0x6C, 0x00, 0x03, 0x7B, 0x00, 0x01, 0x06, 0x38, 0xE0,
|
||||
0xE0, 0x38, 0x06, 0x01, 0xFF, 0x00, 0x00, 0x00, 0xFF, 0x80, 0x60, 0x1C,
|
||||
0x07, 0x07, 0x1C, 0x60, 0x80, 0x7C, 0xC3, 0x03, 0x01, 0x03, 0x06, 0x18,
|
||||
0x10, 0x30, 0x00, 0x30, 0x30, 0x1E, 0x08, 0x64, 0x09, 0x79, 0x92, 0x68,
|
||||
0x9A, 0x26, 0x89, 0xA6, 0xF7, 0x64, 0x00, 0x80, 0x1F, 0x00, 0x0C, 0x03,
|
||||
0x01, 0xE0, 0x48, 0x12, 0x0C, 0xC2, 0x10, 0xFC, 0x61, 0x90, 0x24, 0x0B,
|
||||
0x03, 0xFE, 0x87, 0x83, 0x83, 0x83, 0xFC, 0x86, 0x83, 0x83, 0x83, 0x86,
|
||||
0xFC, 0x1F, 0x73, 0x60, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0xC0, 0x60, 0x71,
|
||||
0x1F, 0xF8, 0x8E, 0x82, 0x83, 0x83, 0x83, 0x83, 0x83, 0x83, 0x86, 0x8C,
|
||||
0xF8, 0xFF, 0x02, 0x04, 0x08, 0x1F, 0xE0, 0x40, 0x81, 0x02, 0x07, 0xF0,
|
||||
0xFF, 0x02, 0x04, 0x08, 0x1F, 0xE0, 0x40, 0x81, 0x02, 0x04, 0x00, 0x1E,
|
||||
0x72, 0x40, 0xC0, 0xC0, 0xC7, 0xC1, 0xC1, 0xC1, 0x41, 0x73, 0x3F, 0x81,
|
||||
0x81, 0x81, 0x81, 0x81, 0xFF, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xFC,
|
||||
0x82, 0x08, 0x20, 0x82, 0x08, 0x20, 0x82, 0x3F, 0x02, 0x04, 0x08, 0x10,
|
||||
0x20, 0x40, 0x81, 0x02, 0x0E, 0x37, 0xC0, 0x81, 0xC1, 0xA1, 0x91, 0x89,
|
||||
0x85, 0x83, 0x61, 0x18, 0x84, 0x43, 0x20, 0xD0, 0x30, 0x80, 0x80, 0x80,
|
||||
0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0xFF, 0xC3, 0xC3, 0xC3,
|
||||
0xC3, 0xA5, 0xA5, 0xA5, 0xA5, 0x99, 0x99, 0x99, 0x91, 0xC1, 0xC1, 0xA1,
|
||||
0xA1, 0x91, 0x91, 0x89, 0x89, 0x85, 0x85, 0x83, 0x83, 0x3C, 0x66, 0x42,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, 0xFC, 0x86, 0x83,
|
||||
0x83, 0x83, 0x82, 0xFC, 0x80, 0x80, 0x80, 0x80, 0x80, 0x3C, 0x66, 0x42,
|
||||
0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0xC3, 0x42, 0x66, 0x3C, 0x04, 0x02, 0x01,
|
||||
0xFC, 0x43, 0x20, 0xD0, 0x68, 0x34, 0x13, 0xF1, 0x18, 0x86, 0x41, 0x20,
|
||||
0xD0, 0x30, 0x3F, 0xE3, 0xC0, 0xC0, 0xC0, 0x78, 0x0E, 0x03, 0x01, 0x03,
|
||||
0x86, 0xFC, 0xFF, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10, 0x10,
|
||||
0x10, 0x10, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0xC3, 0xC3,
|
||||
0x66, 0x3C, 0xC0, 0xD0, 0x24, 0x09, 0x86, 0x21, 0x08, 0x43, 0x30, 0x48,
|
||||
0x12, 0x07, 0x80, 0xC0, 0x30, 0x80, 0x70, 0x1C, 0x0F, 0x03, 0x4C, 0x93,
|
||||
0x24, 0xC9, 0x4A, 0x52, 0x94, 0xA6, 0x18, 0x84, 0xC0, 0xD8, 0x62, 0x10,
|
||||
0xCC, 0x1E, 0x03, 0x00, 0xC0, 0x78, 0x33, 0x08, 0x44, 0x1B, 0x03, 0xC0,
|
||||
0x90, 0x66, 0x10, 0x88, 0x12, 0x05, 0x00, 0xC0, 0x20, 0x08, 0x02, 0x00,
|
||||
0x80, 0x20, 0xFF, 0x03, 0x02, 0x04, 0x0C, 0x08, 0x10, 0x30, 0x20, 0x40,
|
||||
0xC0, 0xFF, 0xF8, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0xF0, 0xC1, 0x04,
|
||||
0x18, 0x20, 0xC3, 0x04, 0x18, 0x20, 0x83, 0xF1, 0x11, 0x11, 0x11, 0x11,
|
||||
0x11, 0x11, 0xF0, 0x18, 0x18, 0x24, 0x24, 0x46, 0x42, 0x83, 0xFF, 0xC0,
|
||||
0xC8, 0x80, 0x7E, 0x43, 0x03, 0x01, 0x3F, 0xC1, 0x83, 0xC7, 0x7D, 0x80,
|
||||
0x80, 0x80, 0x80, 0xBC, 0xE6, 0xC3, 0x83, 0x81, 0x83, 0xC3, 0xE6, 0xBC,
|
||||
0x3F, 0x61, 0xC0, 0xC0, 0x80, 0xC0, 0xC0, 0x61, 0x3F, 0x01, 0x01, 0x01,
|
||||
0x01, 0x3D, 0x67, 0xC3, 0xC1, 0x81, 0xC1, 0xC3, 0x67, 0x3D, 0x3C, 0x66,
|
||||
0xC3, 0xC1, 0xFF, 0x80, 0xC0, 0x61, 0x3E, 0x1E, 0x60, 0x81, 0x0F, 0xC4,
|
||||
0x08, 0x10, 0x20, 0x40, 0x81, 0x02, 0x00, 0x3F, 0xB1, 0x90, 0x48, 0x26,
|
||||
0x31, 0xF1, 0x80, 0x80, 0x7F, 0x60, 0xE0, 0x38, 0x37, 0xE0, 0x80, 0x80,
|
||||
0x80, 0x80, 0xBE, 0xE3, 0xC3, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x10,
|
||||
0x20, 0x00, 0x07, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x8F, 0xE0, 0x0C,
|
||||
0x30, 0x00, 0x7C, 0x10, 0x41, 0x04, 0x10, 0x41, 0x04, 0x10, 0x43, 0xF8,
|
||||
0x80, 0x80, 0x80, 0x80, 0x84, 0x88, 0x90, 0xA0, 0xE0, 0x90, 0x88, 0x84,
|
||||
0x86, 0x70, 0x20, 0x40, 0x81, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x8F,
|
||||
0xE0, 0xB6, 0xDB, 0xD9, 0x99, 0x99, 0x99, 0x99, 0x99, 0x99, 0xBE, 0xE3,
|
||||
0xC3, 0x81, 0x81, 0x81, 0x81, 0x81, 0x81, 0x3C, 0x66, 0xC3, 0xC3, 0x81,
|
||||
0xC3, 0xC3, 0x66, 0x3C, 0xBC, 0xE6, 0xC3, 0x83, 0x81, 0x83, 0xC3, 0xE6,
|
||||
0xBC, 0x80, 0x80, 0x80, 0x80, 0x3D, 0x67, 0xC3, 0xC1, 0x81, 0xC1, 0xC3,
|
||||
0x67, 0x3D, 0x01, 0x01, 0x01, 0x01, 0x9F, 0x47, 0x04, 0x08, 0x10, 0x20,
|
||||
0x40, 0x80, 0x7F, 0x18, 0x38, 0x38, 0x30, 0x63, 0xF8, 0x20, 0x43, 0xF9,
|
||||
0x02, 0x04, 0x08, 0x10, 0x20, 0x60, 0x78, 0x81, 0x81, 0x81, 0x81, 0x81,
|
||||
0x81, 0xC3, 0xC7, 0x7D, 0xC3, 0x42, 0x42, 0x66, 0x24, 0x24, 0x3C, 0x18,
|
||||
0x18, 0x8C, 0x73, 0x34, 0xC9, 0x7A, 0x52, 0x94, 0xA5, 0x28, 0x8C, 0x21,
|
||||
0x00, 0x43, 0x66, 0x24, 0x18, 0x18, 0x3C, 0x24, 0x66, 0xC3, 0xC3, 0x42,
|
||||
0x42, 0x66, 0x24, 0x24, 0x3C, 0x18, 0x18, 0x18, 0x10, 0x30, 0xE0, 0xFC,
|
||||
0x30, 0x84, 0x30, 0x84, 0x30, 0xFC, 0x1C, 0xC2, 0x08, 0x20, 0x82, 0x30,
|
||||
0x60, 0x82, 0x08, 0x20, 0xC1, 0xC0, 0xFF, 0xFF, 0x80, 0xE0, 0xC1, 0x04,
|
||||
0x10, 0x41, 0x03, 0x18, 0x41, 0x04, 0x10, 0xCE, 0x00, 0x70, 0x99, 0x0E };
|
||||
|
||||
const GFXglyph NotoMono8pt7bGlyphs[] PROGMEM = {
|
||||
{ 0, 1, 1, 10, 0, 0 }, // 0x20 ' '
|
||||
{ 1, 2, 12, 10, 4, -11 }, // 0x21 '!'
|
||||
{ 4, 6, 4, 10, 2, -11 }, // 0x22 '"'
|
||||
{ 7, 10, 12, 10, 0, -11 }, // 0x23 '#'
|
||||
{ 22, 7, 14, 10, 2, -12 }, // 0x24 '$'
|
||||
{ 35, 10, 12, 10, 0, -11 }, // 0x25 '%'
|
||||
{ 50, 9, 12, 10, 1, -11 }, // 0x26 '&'
|
||||
{ 64, 2, 4, 10, 4, -11 }, // 0x27 '''
|
||||
{ 65, 5, 15, 10, 3, -11 }, // 0x28 '('
|
||||
{ 75, 5, 15, 10, 2, -11 }, // 0x29 ')'
|
||||
{ 85, 7, 7, 10, 1, -12 }, // 0x2A '*'
|
||||
{ 92, 7, 7, 10, 1, -8 }, // 0x2B '+'
|
||||
{ 99, 3, 4, 10, 3, -1 }, // 0x2C ','
|
||||
{ 101, 6, 1, 10, 2, -4 }, // 0x2D '-'
|
||||
{ 102, 2, 2, 10, 4, -1 }, // 0x2E '.'
|
||||
{ 103, 6, 12, 10, 2, -11 }, // 0x2F '/'
|
||||
{ 112, 8, 12, 10, 1, -11 }, // 0x30 '0'
|
||||
{ 124, 4, 12, 10, 2, -11 }, // 0x31 '1'
|
||||
{ 130, 8, 12, 10, 1, -11 }, // 0x32 '2'
|
||||
{ 142, 8, 12, 10, 1, -11 }, // 0x33 '3'
|
||||
{ 154, 9, 12, 10, 1, -11 }, // 0x34 '4'
|
||||
{ 168, 8, 12, 10, 1, -11 }, // 0x35 '5'
|
||||
{ 180, 8, 12, 10, 1, -11 }, // 0x36 '6'
|
||||
{ 192, 8, 12, 10, 1, -11 }, // 0x37 '7'
|
||||
{ 204, 8, 12, 10, 1, -11 }, // 0x38 '8'
|
||||
{ 216, 8, 12, 10, 1, -11 }, // 0x39 '9'
|
||||
{ 228, 2, 9, 10, 4, -8 }, // 0x3A ':'
|
||||
{ 231, 3, 11, 10, 3, -8 }, // 0x3B ';'
|
||||
{ 236, 8, 8, 10, 1, -9 }, // 0x3C '<'
|
||||
{ 244, 8, 5, 10, 1, -7 }, // 0x3D '='
|
||||
{ 249, 8, 8, 10, 1, -9 }, // 0x3E '>'
|
||||
{ 257, 8, 12, 10, 1, -11 }, // 0x3F '?'
|
||||
{ 269, 10, 13, 10, 0, -11 }, // 0x40 '@'
|
||||
{ 286, 10, 12, 10, 0, -11 }, // 0x41 'A'
|
||||
{ 301, 8, 12, 10, 1, -11 }, // 0x42 'B'
|
||||
{ 313, 8, 12, 10, 1, -11 }, // 0x43 'C'
|
||||
{ 325, 8, 12, 10, 1, -11 }, // 0x44 'D'
|
||||
{ 337, 7, 12, 10, 2, -11 }, // 0x45 'E'
|
||||
{ 348, 7, 12, 10, 2, -11 }, // 0x46 'F'
|
||||
{ 359, 8, 12, 10, 1, -11 }, // 0x47 'G'
|
||||
{ 371, 8, 12, 10, 1, -11 }, // 0x48 'H'
|
||||
{ 383, 6, 12, 10, 2, -11 }, // 0x49 'I'
|
||||
{ 392, 7, 12, 10, 1, -11 }, // 0x4A 'J'
|
||||
{ 403, 9, 12, 10, 1, -11 }, // 0x4B 'K'
|
||||
{ 417, 8, 12, 10, 1, -11 }, // 0x4C 'L'
|
||||
{ 429, 8, 12, 10, 1, -11 }, // 0x4D 'M'
|
||||
{ 441, 8, 12, 10, 1, -11 }, // 0x4E 'N'
|
||||
{ 453, 8, 12, 10, 1, -11 }, // 0x4F 'O'
|
||||
{ 465, 8, 12, 10, 1, -11 }, // 0x50 'P'
|
||||
{ 477, 8, 15, 10, 1, -11 }, // 0x51 'Q'
|
||||
{ 492, 9, 12, 10, 1, -11 }, // 0x52 'R'
|
||||
{ 506, 8, 12, 10, 1, -11 }, // 0x53 'S'
|
||||
{ 518, 8, 12, 10, 1, -11 }, // 0x54 'T'
|
||||
{ 530, 8, 12, 10, 1, -11 }, // 0x55 'U'
|
||||
{ 542, 10, 12, 10, 0, -11 }, // 0x56 'V'
|
||||
{ 557, 10, 12, 10, 0, -11 }, // 0x57 'W'
|
||||
{ 572, 10, 12, 10, 0, -11 }, // 0x58 'X'
|
||||
{ 587, 10, 12, 10, 0, -11 }, // 0x59 'Y'
|
||||
{ 602, 8, 12, 10, 1, -11 }, // 0x5A 'Z'
|
||||
{ 614, 4, 15, 10, 4, -11 }, // 0x5B '['
|
||||
{ 622, 6, 12, 10, 2, -11 }, // 0x5C '\'
|
||||
{ 631, 4, 15, 10, 2, -11 }, // 0x5D ']'
|
||||
{ 639, 8, 7, 10, 1, -11 }, // 0x5E '^'
|
||||
{ 646, 10, 1, 10, 0, 2 }, // 0x5F '_'
|
||||
{ 648, 3, 3, 10, 4, -12 }, // 0x60 '`'
|
||||
{ 650, 8, 9, 10, 1, -8 }, // 0x61 'a'
|
||||
{ 659, 8, 13, 10, 1, -12 }, // 0x62 'b'
|
||||
{ 672, 8, 9, 10, 1, -8 }, // 0x63 'c'
|
||||
{ 681, 8, 13, 10, 1, -12 }, // 0x64 'd'
|
||||
{ 694, 8, 9, 10, 1, -8 }, // 0x65 'e'
|
||||
{ 703, 7, 13, 10, 2, -12 }, // 0x66 'f'
|
||||
{ 715, 9, 13, 10, 0, -8 }, // 0x67 'g'
|
||||
{ 730, 8, 13, 10, 1, -12 }, // 0x68 'h'
|
||||
{ 743, 7, 13, 10, 1, -12 }, // 0x69 'i'
|
||||
{ 755, 6, 17, 10, 1, -12 }, // 0x6A 'j'
|
||||
{ 768, 8, 13, 10, 2, -12 }, // 0x6B 'k'
|
||||
{ 781, 7, 13, 10, 1, -12 }, // 0x6C 'l'
|
||||
{ 793, 8, 9, 10, 1, -8 }, // 0x6D 'm'
|
||||
{ 802, 8, 9, 10, 1, -8 }, // 0x6E 'n'
|
||||
{ 811, 8, 9, 10, 1, -8 }, // 0x6F 'o'
|
||||
{ 820, 8, 13, 10, 1, -8 }, // 0x70 'p'
|
||||
{ 833, 8, 13, 10, 1, -8 }, // 0x71 'q'
|
||||
{ 846, 7, 9, 10, 2, -8 }, // 0x72 'r'
|
||||
{ 854, 6, 9, 10, 2, -8 }, // 0x73 's'
|
||||
{ 861, 7, 11, 10, 2, -10 }, // 0x74 't'
|
||||
{ 871, 8, 9, 10, 1, -8 }, // 0x75 'u'
|
||||
{ 880, 8, 9, 10, 1, -8 }, // 0x76 'v'
|
||||
{ 889, 10, 9, 10, 0, -8 }, // 0x77 'w'
|
||||
{ 901, 8, 9, 10, 1, -8 }, // 0x78 'x'
|
||||
{ 910, 8, 13, 10, 1, -8 }, // 0x79 'y'
|
||||
{ 923, 6, 9, 10, 2, -8 }, // 0x7A 'z'
|
||||
{ 930, 6, 15, 10, 2, -11 }, // 0x7B '{'
|
||||
{ 942, 1, 17, 10, 4, -12 }, // 0x7C '|'
|
||||
{ 945, 6, 15, 10, 2, -11 }, // 0x7D '}'
|
||||
{ 957, 8, 3, 10, 1, -6 } }; // 0x7E '~'
|
||||
|
||||
const GFXfont NotoMono8pt7b PROGMEM = {
|
||||
(uint8_t *)NotoMono8pt7bBitmaps,
|
||||
(GFXglyph *)NotoMono8pt7bGlyphs,
|
||||
0x20, 0x7E, 18 };
|
||||
|
||||
// Approx. 1632 bytes
|
517
hardware/sd_card_formatter/src/guislice/XCheckbox.c
Normal file
517
hardware/sd_card_formatter/src/guislice/XCheckbox.c
Normal file
|
@ -0,0 +1,517 @@
|
|||
// =======================================================================
|
||||
// GUIslice library (extensions)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XCheckbox.c
|
||||
|
||||
|
||||
|
||||
// GUIslice library
|
||||
#include "GUIslice.h"
|
||||
#include "GUIslice_drv.h"
|
||||
|
||||
#include "XCheckbox.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if (GSLC_USE_PROGMEM)
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Error Messages
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern const char GSLC_PMEM ERRSTR_NULL[];
|
||||
extern const char GSLC_PMEM ERRSTR_PXD_NULL[];
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Extended element definitions
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// - This file extends the core GUIslice functionality with
|
||||
// additional widget types
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: Checkbox
|
||||
// - Checkbox with custom handler for touch tracking which
|
||||
// enables glow to be defined whenever touch is tracked over
|
||||
// the element.
|
||||
// ============================================================================
|
||||
|
||||
// Create a checkbox element and add it to the GUI element list
|
||||
// - Defines default styling for the element
|
||||
// - Defines callback for redraw but does not track touch/click
|
||||
gslc_tsElemRef* gslc_ElemXCheckboxCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t nPage,
|
||||
gslc_tsXCheckbox* pXData,gslc_tsRect rElem,bool bRadio,gslc_teXCheckboxStyle nStyle,
|
||||
gslc_tsColor colCheck,bool bChecked)
|
||||
{
|
||||
if ((pGui == NULL) || (pXData == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxCreate";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return NULL;
|
||||
}
|
||||
gslc_tsElem sElem;
|
||||
gslc_tsElemRef* pElemRef = NULL;
|
||||
sElem = gslc_ElemCreate(pGui,nElemId,nPage,GSLC_TYPEX_CHECKBOX,rElem,NULL,0,GSLC_FONT_NONE);
|
||||
sElem.nFeatures &= ~GSLC_ELEM_FEA_FRAME_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_CLICK_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_GLOW_EN;
|
||||
|
||||
// Default group assignment. Can override later with ElemSetGroup()
|
||||
sElem.nGroup = GSLC_GROUP_ID_NONE;
|
||||
|
||||
// Define other extended data
|
||||
pXData->bRadio = bRadio;
|
||||
pXData->bChecked = bChecked;
|
||||
pXData->colCheck = colCheck;
|
||||
pXData->nStyle = nStyle;
|
||||
pXData->pfuncXToggle = NULL;
|
||||
sElem.pXData = (void*)(pXData);
|
||||
// Specify the custom drawing callback
|
||||
sElem.pfuncXDraw = &gslc_ElemXCheckboxDraw;
|
||||
// Specify the custom touch tracking callback
|
||||
// - NOTE: This is optional (and can be set to NULL).
|
||||
// See the discussion under gslc_ElemXCheckboxTouch()
|
||||
sElem.pfuncXTouch = &gslc_ElemXCheckboxTouch;
|
||||
sElem.colElemFill = GSLC_COL_BLACK;
|
||||
sElem.colElemFillGlow = GSLC_COL_BLACK;
|
||||
sElem.colElemFrame = GSLC_COL_GRAY;
|
||||
sElem.colElemFrameGlow = GSLC_COL_WHITE;
|
||||
if (nPage != GSLC_PAGE_NONE) {
|
||||
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_DEFAULT);
|
||||
return pElemRef;
|
||||
#if (GSLC_FEATURE_COMPOUND)
|
||||
} else {
|
||||
// Save as temporary element
|
||||
pGui->sElemTmp = sElem;
|
||||
pGui->sElemRefTmp.pElem = &(pGui->sElemTmp);
|
||||
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
|
||||
return &(pGui->sElemRefTmp);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool gslc_ElemXCheckboxGetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
|
||||
{
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return false;
|
||||
|
||||
return pCheckbox->bChecked;
|
||||
}
|
||||
|
||||
|
||||
// Determine which checkbox in the group has been "checked"
|
||||
gslc_tsElemRef* gslc_ElemXCheckboxFindChecked(gslc_tsGui* pGui,int16_t nGroupId)
|
||||
{
|
||||
int16_t nCurInd;
|
||||
gslc_tsElemRef* pCurElemRef = NULL;
|
||||
gslc_tsElem* pCurElem = NULL;
|
||||
int16_t nCurType;
|
||||
int16_t nCurGroup;
|
||||
bool bCurChecked;
|
||||
gslc_tsElemRef* pFoundElemRef = NULL;
|
||||
|
||||
// Operate on current page
|
||||
// TODO: Support other page layers
|
||||
gslc_tsPage* pPage = pGui->apPageStack[GSLC_STACK_CUR];
|
||||
if (pPage == NULL) {
|
||||
return NULL; // No page added yet
|
||||
}
|
||||
|
||||
if (pGui == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxFindChecked";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gslc_tsCollect* pCollect = &pPage->sCollect;
|
||||
for (nCurInd=0;nCurInd<pCollect->nElemCnt;nCurInd++) {
|
||||
// Fetch extended data
|
||||
pCurElemRef = &(pCollect->asElemRef[nCurInd]);
|
||||
pCurElem = gslc_GetElemFromRef(pGui,pCurElemRef);
|
||||
nCurType = pCurElem->nType;
|
||||
// Only want to proceed if it is a checkbox
|
||||
if (nCurType != GSLC_TYPEX_CHECKBOX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nCurGroup = pCurElem->nGroup;
|
||||
bCurChecked = gslc_ElemXCheckboxGetState(pGui,pCurElemRef);
|
||||
|
||||
// If this is in a different group, ignore it
|
||||
if (nCurGroup != nGroupId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Did we find an element in the group that was checked?
|
||||
if (bCurChecked) {
|
||||
pFoundElemRef = pCurElemRef;
|
||||
break;
|
||||
}
|
||||
} // nCurInd
|
||||
return pFoundElemRef;
|
||||
}
|
||||
|
||||
// Assign the callback function for checkbox/radio state change events
|
||||
void gslc_ElemXCheckboxSetStateFunc(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, GSLC_CB_XCHECKBOX pfuncCb)
|
||||
{
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return;
|
||||
|
||||
pCheckbox->pfuncXToggle = pfuncCb;
|
||||
}
|
||||
|
||||
// Helper routine for gslc_ElemXCheckboxSetState()
|
||||
// - Updates the checkbox/radio control's state but does
|
||||
// not touch any other controls in the group
|
||||
void gslc_ElemXCheckboxSetStateHelp(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bChecked,bool bDoCb)
|
||||
{
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return;
|
||||
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
|
||||
// Update our data element
|
||||
bool const bCheckedOld = pCheckbox->bChecked;
|
||||
pCheckbox->bChecked = bChecked;
|
||||
|
||||
// Element needs redraw
|
||||
if (bChecked != bCheckedOld) {
|
||||
// Only need an incremental redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||||
} else {
|
||||
// Same state as before
|
||||
// - No need to do anything further since we don't need to
|
||||
// trigger any callbacks or redraw
|
||||
return;
|
||||
}
|
||||
|
||||
// If no callbacks requested, exit now
|
||||
if (!bDoCb) {
|
||||
return;
|
||||
}
|
||||
|
||||
// If any state callback is defined, call it now
|
||||
// - In all cases, return the ElementRef of the element that issued the callback
|
||||
//
|
||||
// For checkbox:
|
||||
// - If not selected: return current ID and state=false
|
||||
// - If selected: return current ID and state=true
|
||||
// For radio button:
|
||||
// - If none selected: return ID_NONE and state=false
|
||||
// - If one selected: return selected ID and state=true
|
||||
if (pCheckbox->pfuncXToggle != NULL) {
|
||||
gslc_tsElemRef* pRetRef = NULL;
|
||||
int16_t nGroup = GSLC_GROUP_ID_NONE;
|
||||
int16_t nSelId = GSLC_ID_NONE;
|
||||
if (!pCheckbox->bRadio) {
|
||||
// Checkbox
|
||||
nSelId = pElem->nId;
|
||||
} else {
|
||||
// Radio button
|
||||
// - Determine the group that the radio button belongs to
|
||||
nGroup = pElem->nGroup;
|
||||
// Determine if any radio button in the group has been selected
|
||||
pRetRef = gslc_ElemXCheckboxFindChecked(pGui, nGroup);
|
||||
if (pRetRef != NULL) {
|
||||
// One has been selected, return its ID
|
||||
bChecked = true;
|
||||
nSelId = pRetRef->pElem->nId;
|
||||
} else {
|
||||
// No radio button selected, return ID NONE
|
||||
bChecked = false;
|
||||
nSelId = GSLC_ID_NONE;
|
||||
}
|
||||
}
|
||||
// Now send the callback notification
|
||||
(*pCheckbox->pfuncXToggle)((void*)(pGui), (void*)(pElemRef), nSelId, bChecked);
|
||||
} // pfuncXToggle
|
||||
|
||||
}
|
||||
|
||||
// Update the checkbox/radio control's state. If it is a radio button
|
||||
// then also update the state of all other buttons in the group.
|
||||
void gslc_ElemXCheckboxSetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bChecked)
|
||||
{
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return;
|
||||
|
||||
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsPage* pPage = NULL;
|
||||
|
||||
bool bRadio = pCheckbox->bRadio;
|
||||
int16_t nGroup = pElem->nGroup;
|
||||
int16_t nElemId = pElem->nId;
|
||||
|
||||
// Special handling when we select a radio button
|
||||
if (bRadio && bChecked) {
|
||||
|
||||
// If we are selecting a radio button that is already
|
||||
// selected, then skip further update events.
|
||||
// NOTE: This check is not very efficient, but it avoids
|
||||
// the creation of extra events.
|
||||
gslc_tsElemRef* pTmpRef = gslc_ElemXCheckboxFindChecked(pGui, nGroup);
|
||||
if (pTmpRef == pElemRef) {
|
||||
// Same element, so skip
|
||||
return;
|
||||
}
|
||||
|
||||
// Proceed to deselect any other selected items in the group.
|
||||
// Note that SetState calls itself to deselect other items so it
|
||||
// is important to qualify this logic with bChecked=true
|
||||
int16_t nCurInd;
|
||||
int16_t nCurId;
|
||||
gslc_tsElem* pCurElem = NULL;
|
||||
gslc_tsElemRef* pCurElemRef = NULL;
|
||||
int16_t nCurType;
|
||||
int16_t nCurGroup;
|
||||
|
||||
// We use the GUI pointer for access to other elements
|
||||
|
||||
// Check all pages in case we are affecting radio buttons on other pages
|
||||
for (int8_t nPageInd=0;nPageInd<pGui->nPageCnt;nPageInd++) {
|
||||
pPage = &pGui->asPage[nPageInd];
|
||||
if (!pPage) {
|
||||
// If this stack page is not enabled, skip to next stack page
|
||||
continue;
|
||||
}
|
||||
|
||||
gslc_tsCollect* pCollect = &pPage->sCollect;
|
||||
for (nCurInd=0;nCurInd<pCollect->nElemRefCnt;nCurInd++) {
|
||||
// Fetch extended data
|
||||
pCurElemRef = &pCollect->asElemRef[nCurInd];
|
||||
pCurElem = gslc_GetElemFromRef(pGui,pCurElemRef);
|
||||
|
||||
// FIXME: Handle pCurElemRef->eElemFlags
|
||||
nCurId = pCurElem->nId;
|
||||
nCurType = pCurElem->nType;
|
||||
|
||||
// Only want to proceed if it is a checkbox
|
||||
if (nCurType != GSLC_TYPEX_CHECKBOX) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nCurGroup = pCurElem->nGroup;
|
||||
|
||||
// If this is in a different group, ignore it
|
||||
if (nCurGroup != nGroup) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Is this our element? If so, ignore the deselect operation
|
||||
if (nCurId == nElemId) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Deselect all other elements
|
||||
// - But don't trigger any callbacks
|
||||
gslc_ElemXCheckboxSetStateHelp(pGui,pCurElemRef,false,false);
|
||||
|
||||
} // nInd
|
||||
} // nStackPage
|
||||
|
||||
} // bRadio
|
||||
|
||||
// Set the state of the current element
|
||||
// - Trigger callback if enabled
|
||||
gslc_ElemXCheckboxSetStateHelp(pGui,pElemRef,bChecked,true);
|
||||
}
|
||||
|
||||
// Toggle the checkbox control's state
|
||||
void gslc_ElemXCheckboxToggleState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXCheckboxToggleState";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
// Update the data element
|
||||
bool bCheckNew = (gslc_ElemXCheckboxGetState(pGui,pElemRef))? false : true;
|
||||
gslc_ElemXCheckboxSetState(pGui,pElemRef,bCheckNew);
|
||||
|
||||
// Element needs redraw
|
||||
// - Only incremental is needed
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||||
}
|
||||
|
||||
// Redraw the checkbox
|
||||
// - Note that this redraw is for the entire element rect region
|
||||
// - The Draw function parameters use void pointers to allow for
|
||||
// simpler callback function definition & scalability.
|
||||
bool gslc_ElemXCheckboxDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
// Typecast the parameters to match the GUI and element types
|
||||
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||||
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||||
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return false;
|
||||
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsRect rInner;
|
||||
|
||||
bool bChecked = pCheckbox->bChecked;
|
||||
gslc_teXCheckboxStyle nStyle = pCheckbox->nStyle;
|
||||
bool bGlow = (pElem->nFeatures & GSLC_ELEM_FEA_GLOW_EN) && gslc_ElemGetGlow(pGui,pElemRef);
|
||||
|
||||
// Draw the background
|
||||
gslc_DrawFillRect(pGui,pElem->rElem,pElem->colElemFill);
|
||||
|
||||
// Generic coordinate calcs
|
||||
int16_t nX0,nY0,nX1,nY1,nMidX,nMidY;
|
||||
nX0 = pElem->rElem.x;
|
||||
nY0 = pElem->rElem.y;
|
||||
nX1 = pElem->rElem.x + pElem->rElem.w - 1;
|
||||
nY1 = pElem->rElem.y + pElem->rElem.h - 1;
|
||||
nMidX = (nX0+nX1)/2;
|
||||
nMidY = (nY0+nY1)/2;
|
||||
if (nStyle == GSLCX_CHECKBOX_STYLE_BOX) {
|
||||
// Draw the center indicator if checked
|
||||
rInner = gslc_ExpandRect(pElem->rElem,-5,-5);
|
||||
if (bChecked) {
|
||||
// If checked, fill in the inner region
|
||||
gslc_DrawFillRect(pGui,rInner,pCheckbox->colCheck);
|
||||
} else {
|
||||
// Assume the background fill has already been done so
|
||||
// we don't need to do anything more in the unchecked case
|
||||
}
|
||||
// Draw a frame around the checkbox
|
||||
gslc_DrawFrameRect(pGui,pElem->rElem,(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||||
|
||||
} else if (nStyle == GSLCX_CHECKBOX_STYLE_X) {
|
||||
// Draw an X through center if checked
|
||||
if (bChecked) {
|
||||
gslc_DrawLine(pGui,nX0,nY0,nX1,nY1,pCheckbox->colCheck);
|
||||
gslc_DrawLine(pGui,nX0,nY1,nX1,nY0,pCheckbox->colCheck);
|
||||
}
|
||||
// Draw a frame around the checkbox
|
||||
gslc_DrawFrameRect(pGui,pElem->rElem,(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||||
|
||||
} else if (nStyle == GSLCX_CHECKBOX_STYLE_ROUND) {
|
||||
// Draw inner circle if checked
|
||||
if (bChecked) {
|
||||
gslc_DrawFillCircle(pGui,nMidX,nMidY,5,pCheckbox->colCheck);
|
||||
}
|
||||
// Draw a frame around the checkbox
|
||||
gslc_DrawFrameCircle(pGui,nMidX,nMidY,(pElem->rElem.w/2),(bGlow)?pElem->colElemFrameGlow:pElem->colElemFrame);
|
||||
|
||||
}
|
||||
|
||||
// Clear the redraw flag
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_NONE);
|
||||
|
||||
// Mark page as needing flip
|
||||
gslc_PageFlipSet(pGui,true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// This callback function is called by gslc_ElemSendEventTouch()
|
||||
// after any touch event
|
||||
// - NOTE: Adding this touch callback is optional. Without it, we
|
||||
// can still have a functional checkbox, but doing the touch
|
||||
// tracking allows us to change the glow state of the element
|
||||
// dynamically, as well as updating the checkbox state if the
|
||||
// user releases over it (ie. a click event).
|
||||
//
|
||||
bool gslc_ElemXCheckboxTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16_t nRelX,int16_t nRelY)
|
||||
{
|
||||
#if defined(DRV_TOUCH_NONE)
|
||||
return false;
|
||||
#else
|
||||
|
||||
// Typecast the parameters to match the GUI and element types
|
||||
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||||
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||||
|
||||
gslc_tsXCheckbox* pCheckbox = (gslc_tsXCheckbox*)gslc_GetXDataFromRef(pGui, pElemRef, GSLC_TYPEX_CHECKBOX, __LINE__);
|
||||
if (!pCheckbox) return false;
|
||||
|
||||
//gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
|
||||
bool bRadio = pCheckbox->bRadio;
|
||||
bool bCheckedOld = pCheckbox->bChecked;
|
||||
bool bGlowingOld = gslc_ElemGetGlow(pGui,pElemRef);
|
||||
|
||||
switch(eTouch) {
|
||||
|
||||
case GSLC_TOUCH_DOWN_IN:
|
||||
gslc_ElemSetGlow(pGui,pElemRef,true);
|
||||
break;
|
||||
|
||||
case GSLC_TOUCH_MOVE_IN:
|
||||
gslc_ElemSetGlow(pGui,pElemRef,true);
|
||||
break;
|
||||
case GSLC_TOUCH_MOVE_OUT:
|
||||
gslc_ElemSetGlow(pGui,pElemRef,false);
|
||||
break;
|
||||
|
||||
case GSLC_TOUCH_UP_IN:
|
||||
gslc_ElemSetGlow(pGui,pElemRef,false);
|
||||
// Now that we released on element, update the state
|
||||
bool bCheckNew;
|
||||
if (bRadio) {
|
||||
// Radio button action: set
|
||||
bCheckNew = true;
|
||||
} else {
|
||||
// Checkbox button action: toggle
|
||||
bCheckNew = (pCheckbox->bChecked)?false:true;
|
||||
}
|
||||
gslc_ElemXCheckboxSetState(pGui,pElemRef,bCheckNew);
|
||||
break;
|
||||
case GSLC_TOUCH_UP_OUT:
|
||||
gslc_ElemSetGlow(pGui,pElemRef,false);
|
||||
break;
|
||||
|
||||
default:
|
||||
return false;
|
||||
break;
|
||||
}
|
||||
|
||||
// If the checkbox changed state, redraw
|
||||
bool bChanged = false;
|
||||
if (gslc_ElemGetGlow(pGui,pElemRef) != bGlowingOld) { bChanged = true; }
|
||||
if (pCheckbox->bChecked != bCheckedOld) { bChanged = true; }
|
||||
if (bChanged) {
|
||||
// Incremental redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||||
}
|
||||
|
||||
return true;
|
||||
#endif // !DRV_TOUCH_NONE
|
||||
}
|
||||
|
||||
// ============================================================================
|
290
hardware/sd_card_formatter/src/guislice/XCheckbox.h
Normal file
290
hardware/sd_card_formatter/src/guislice/XCheckbox.h
Normal file
|
@ -0,0 +1,290 @@
|
|||
#ifndef _GUISLICE_EX_XCHECKBOX_H_
|
||||
#define _GUISLICE_EX_XCHECKBOX_H_
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library extension: Checkbox/Radio button control
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XCheckbox.h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: Checkbox
|
||||
// ============================================================================
|
||||
|
||||
// Define unique identifier for extended element type
|
||||
// - Select any number above GSLC_TYPE_BASE_EXTEND
|
||||
#define GSLC_TYPEX_CHECKBOX GSLC_TYPE_BASE_EXTEND + 1
|
||||
|
||||
/// Checkbox drawing style
|
||||
typedef enum {
|
||||
GSLCX_CHECKBOX_STYLE_BOX, ///< Inner box
|
||||
GSLCX_CHECKBOX_STYLE_X, ///< Crossed
|
||||
GSLCX_CHECKBOX_STYLE_ROUND, ///< Circular
|
||||
} gslc_teXCheckboxStyle;
|
||||
|
||||
/// Callback function for checkbox/radio element state change
|
||||
/// - nSelId: Selected element's ID or GSLC_ID_NONE
|
||||
/// - bChecked: Element was selected if true, false otherwise
|
||||
typedef bool (*GSLC_CB_XCHECKBOX)(void* pvGui,void* pvElemRef,int16_t nSelId, bool bChecked);
|
||||
|
||||
// Extended element data structures
|
||||
// - These data structures are maintained in the gslc_tsElem
|
||||
// structure via the pXData pointer
|
||||
|
||||
/// Extended data for Checkbox element
|
||||
typedef struct {
|
||||
bool bRadio; ///< Radio-button operation if true
|
||||
gslc_teXCheckboxStyle nStyle; ///< Drawing style for element
|
||||
bool bChecked; ///< Indicates if it is selected (checked)
|
||||
gslc_tsColor colCheck; ///< Color of checked inner fill
|
||||
GSLC_CB_XCHECKBOX pfuncXToggle; ///< Callback event to say element has changed
|
||||
} gslc_tsXCheckbox;
|
||||
|
||||
|
||||
///
|
||||
/// Create a Checkbox or Radio button Element
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nElemId: Element ID to assign (0..16383 or GSLC_ID_AUTO to autogen)
|
||||
/// \param[in] nPage: Page ID to attach element to
|
||||
/// \param[in] pXData: Ptr to extended element data structure
|
||||
/// \param[in] rElem: Rectangle coordinates defining checkbox size
|
||||
/// \param[in] bRadio: Radio-button functionality if true
|
||||
/// \param[in] nStyle: Drawing style for checkbox / radio button
|
||||
/// \param[in] colCheck: Color for inner fill when checked
|
||||
/// \param[in] bChecked: Default state
|
||||
///
|
||||
/// \return Pointer to Element reference or NULL if failure
|
||||
///
|
||||
gslc_tsElemRef* gslc_ElemXCheckboxCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t nPage,
|
||||
gslc_tsXCheckbox* pXData,gslc_tsRect rElem,bool bRadio,
|
||||
gslc_teXCheckboxStyle nStyle,gslc_tsColor colCheck,bool bChecked);
|
||||
|
||||
|
||||
///
|
||||
/// Get a Checkbox element's current state
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
///
|
||||
/// \return Current state
|
||||
///
|
||||
bool gslc_ElemXCheckboxGetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef);
|
||||
|
||||
///
|
||||
/// Set a Checkbox element's current state
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] bChecked: New state
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXCheckboxSetState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bChecked);
|
||||
|
||||
///
|
||||
/// Find the checkbox within a group that has been checked
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nGroupId: Group ID to search
|
||||
///
|
||||
/// \return Element Ptr or NULL if none checked
|
||||
///
|
||||
gslc_tsElemRef* gslc_ElemXCheckboxFindChecked(gslc_tsGui* pGui,int16_t nGroupId);
|
||||
|
||||
///
|
||||
/// Toggle a Checkbox element's current state
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXCheckboxToggleState(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef);
|
||||
|
||||
///
|
||||
/// Assign the state callback function for a checkbox/radio button
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] pfuncCb: Function pointer to callback routine (or NULL for none)
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXCheckboxSetStateFunc(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, GSLC_CB_XCHECKBOX pfuncCb);
|
||||
|
||||
///
|
||||
/// Draw a Checkbox element on the screen
|
||||
/// - Called from gslc_ElemDraw()
|
||||
///
|
||||
/// \param[in] pvGui: Void ptr to GUI (typecast to gslc_tsGui*)
|
||||
/// \param[in] pvElemRef: Void ptr to Element reference (typecast to gslc_tsElemRef*)
|
||||
/// \param[in] eRedraw: Redraw mode
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXCheckboxDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw);
|
||||
|
||||
///
|
||||
/// Handle touch events to Checkbox element
|
||||
/// - Called from gslc_ElemSendEventTouch()
|
||||
///
|
||||
/// \param[in] pvGui: Void ptr to GUI (typecast to gslc_tsGui*)
|
||||
/// \param[in] pvElemRef: Void ptr to Element reference (typecast to gslc_tsElemRef*)
|
||||
/// \param[in] eTouch: Touch event type
|
||||
/// \param[in] nRelX: Touch X coord relative to element
|
||||
/// \param[in] nRelY: Touch Y coord relative to element
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXCheckboxTouch(void* pvGui,void* pvElemRef,gslc_teTouch eTouch,int16_t nRelX,int16_t nRelY);
|
||||
// ============================================================================
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Read-only element macros
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Macro initializers for Read-Only Elements in Flash/PROGMEM
|
||||
//
|
||||
|
||||
|
||||
/// \def gslc_ElemXCheckboxCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,nGroup,bRadio_,nStyle_,colCheck_,bChecked_)
|
||||
///
|
||||
/// Create a Checkbox or Radio button Element in Flash
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nElemId: Unique element ID to assign
|
||||
/// \param[in] nPage: Page ID to attach element to
|
||||
/// \param[in] nX: X coordinate of element
|
||||
/// \param[in] nY: Y coordinate of element
|
||||
/// \param[in] nW: Width of element
|
||||
/// \param[in] nH: Height of element
|
||||
/// \param[in] colFill: Color for the control background fill
|
||||
/// \param[in] bFillEn: True if background filled, false otherwise (recommend True)
|
||||
/// \param[in] nGroup: Group ID that radio buttons belong to (else GSLC_GROUP_NONE)
|
||||
/// \param[in] bRadio_: Radio-button functionality if true
|
||||
/// \param[in] nStyle_: Drawing style for checkbox / radio button
|
||||
/// \param[in] colCheck_: Color for inner fill when checked
|
||||
/// \param[in] bChecked_: Default state
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
|
||||
#if (GSLC_USE_PROGMEM)
|
||||
|
||||
#define gslc_ElemXCheckboxCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,colFill,bFillEn,nGroup,bRadio_,nStyle_,colCheck_,bChecked_) \
|
||||
static const uint8_t nFeatures##nElemId = GSLC_ELEM_FEA_VALID | \
|
||||
GSLC_ELEM_FEA_GLOW_EN | GSLC_ELEM_FEA_CLICK_EN | (bFillEn?GSLC_ELEM_FEA_FILL_EN:0); \
|
||||
static gslc_tsXCheckbox sCheckbox##nElemId; \
|
||||
sCheckbox##nElemId.bRadio = bRadio_; \
|
||||
sCheckbox##nElemId.bChecked = bChecked_; \
|
||||
sCheckbox##nElemId.colCheck = colCheck_; \
|
||||
sCheckbox##nElemId.nStyle = nStyle_; \
|
||||
static const gslc_tsElem sElem##nElemId PROGMEM = { \
|
||||
nElemId, \
|
||||
nFeatures##nElemId, \
|
||||
GSLC_TYPEX_CHECKBOX, \
|
||||
(gslc_tsRect){nX,nY,nW,nH}, \
|
||||
nGroup, \
|
||||
GSLC_COL_GRAY,colFill,GSLC_COL_WHITE,GSLC_COL_BLACK, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
0, \
|
||||
(gslc_teTxtFlags)(GSLC_TXT_DEFAULT), \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_ALIGN_MID_MID, \
|
||||
0, \
|
||||
0, \
|
||||
NULL, \
|
||||
(void*)(&sCheckbox##nElemId), \
|
||||
NULL, \
|
||||
&gslc_ElemXCheckboxDraw, \
|
||||
&gslc_ElemXCheckboxTouch, \
|
||||
NULL, \
|
||||
}; \
|
||||
gslc_ElemAdd(pGui,nPage,(gslc_tsElem*)&sElem##nElemId, \
|
||||
(gslc_teElemRefFlags)(GSLC_ELEMREF_SRC_PROG | GSLC_ELEMREF_VISIBLE | GSLC_ELEMREF_REDRAW_FULL));
|
||||
|
||||
|
||||
#else
|
||||
|
||||
#define gslc_ElemXCheckboxCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,colFill,bFillEn,nGroup,bRadio_,nStyle_,colCheck_,bChecked_) \
|
||||
static const uint8_t nFeatures##nElemId = GSLC_ELEM_FEA_VALID | \
|
||||
GSLC_ELEM_FEA_GLOW_EN | GSLC_ELEM_FEA_CLICK_EN | (bFillEn?GSLC_ELEM_FEA_FILL_EN:0); \
|
||||
static gslc_tsXCheckbox sCheckbox##nElemId; \
|
||||
sCheckbox##nElemId.bRadio = bRadio_; \
|
||||
sCheckbox##nElemId.bChecked = bChecked_; \
|
||||
sCheckbox##nElemId.colCheck = colCheck_; \
|
||||
sCheckbox##nElemId.nStyle = nStyle_; \
|
||||
static const gslc_tsElem sElem##nElemId = { \
|
||||
nElemId, \
|
||||
nFeatures##nElemId, \
|
||||
GSLC_TYPEX_CHECKBOX, \
|
||||
(gslc_tsRect){nX,nY,nW,nH}, \
|
||||
nGroup, \
|
||||
GSLC_COL_GRAY,colFill,GSLC_COL_WHITE,GSLC_COL_BLACK, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
0, \
|
||||
(gslc_teTxtFlags)(GSLC_TXT_DEFAULT), \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_ALIGN_MID_MID, \
|
||||
0, \
|
||||
0, \
|
||||
NULL, \
|
||||
(void*)(&sCheckbox##nElemId), \
|
||||
NULL, \
|
||||
&gslc_ElemXCheckboxDraw, \
|
||||
&gslc_ElemXCheckboxTouch, \
|
||||
NULL, \
|
||||
}; \
|
||||
gslc_ElemAdd(pGui,nPage,(gslc_tsElem*)&sElem##nElemId, \
|
||||
(gslc_teElemRefFlags)(GSLC_ELEMREF_SRC_CONST | GSLC_ELEMREF_VISIBLE | GSLC_ELEMREF_REDRAW_FULL));
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_EX_XCHECKBOX_H_
|
||||
|
699
hardware/sd_card_formatter/src/guislice/XGauge.c
Normal file
699
hardware/sd_card_formatter/src/guislice/XGauge.c
Normal file
|
@ -0,0 +1,699 @@
|
|||
// =======================================================================
|
||||
// GUIslice library (extensions)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XGauge.c
|
||||
|
||||
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
|
||||
// WARNING: The XGauge element has been replaced by XProgress / XRadial / XRamp
|
||||
// Please update your code according to the migration notes in:
|
||||
// https://github.com/ImpulseAdventure/GUIslice/pull/157
|
||||
// XGauge may be removed in a future release.
|
||||
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
|
||||
|
||||
|
||||
// GUIslice library
|
||||
#include "GUIslice.h"
|
||||
#include "GUIslice_drv.h"
|
||||
|
||||
#include "XGauge.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include <math.h> // For sin/cos in XGauge(RADIAL)
|
||||
|
||||
#if (GSLC_USE_PROGMEM)
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Error Messages
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern const char GSLC_PMEM ERRSTR_NULL[];
|
||||
extern const char GSLC_PMEM ERRSTR_PXD_NULL[];
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Extended element definitions
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// - This file extends the core GUIslice functionality with
|
||||
// additional widget types
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: Gauge
|
||||
// - Basic progress bar with support for positive/negative state
|
||||
// and vertical / horizontal orientation.
|
||||
// ============================================================================
|
||||
|
||||
// Create a gauge element and add it to the GUI element list
|
||||
// - Defines default styling for the element
|
||||
// - Defines callback for redraw but does not track touch/click
|
||||
gslc_tsElemRef* gslc_ElemXGaugeCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t nPage,
|
||||
gslc_tsXGauge* pXData,gslc_tsRect rElem,
|
||||
int16_t nMin,int16_t nMax,int16_t nVal,gslc_tsColor colGauge,bool bVert)
|
||||
{
|
||||
if ((pGui == NULL) || (pXData == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeCreate";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return NULL;
|
||||
}
|
||||
gslc_tsElem sElem;
|
||||
gslc_tsElemRef* pElemRef = NULL;
|
||||
sElem = gslc_ElemCreate(pGui,nElemId,nPage,GSLC_TYPEX_GAUGE,rElem,NULL,0,GSLC_FONT_NONE);
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_FRAME_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
|
||||
sElem.nFeatures &= ~GSLC_ELEM_FEA_CLICK_EN; // Element is not "clickable"
|
||||
sElem.nFeatures &= ~GSLC_ELEM_FEA_GLOW_EN;
|
||||
sElem.nGroup = GSLC_GROUP_ID_NONE;
|
||||
pXData->nMin = nMin;
|
||||
pXData->nMax = nMax;
|
||||
pXData->nVal = nVal;
|
||||
pXData->nStyle = GSLCX_GAUGE_STYLE_PROG_BAR; // Default to progress bar
|
||||
pXData->bVert = bVert;
|
||||
pXData->bFlip = false;
|
||||
pXData->colGauge = colGauge;
|
||||
pXData->colTick = GSLC_COL_GRAY;
|
||||
pXData->nTickCnt = 8;
|
||||
pXData->nTickLen = 5;
|
||||
pXData->nIndicLen = 10; // Dummy default to be overridden
|
||||
pXData->nIndicTip = 3; // Dummy default to be overridden
|
||||
pXData->bIndicFill = false;
|
||||
sElem.pXData = (void*)(pXData);
|
||||
sElem.pfuncXDraw = &gslc_ElemXGaugeDraw;
|
||||
sElem.pfuncXTouch = NULL; // No need to track touches
|
||||
sElem.colElemFill = GSLC_COL_BLACK;
|
||||
sElem.colElemFillGlow = GSLC_COL_BLACK;
|
||||
sElem.colElemFrame = GSLC_COL_GRAY;
|
||||
sElem.colElemFrameGlow = GSLC_COL_GRAY;
|
||||
GSLC_DEBUG_PRINT("NOTE: XGauge has been replaced by XProgress/XRadial/XRamp\n","");
|
||||
if (nPage != GSLC_PAGE_NONE) {
|
||||
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_DEFAULT);
|
||||
return pElemRef;
|
||||
#if (GSLC_FEATURE_COMPOUND)
|
||||
} else {
|
||||
// Save as temporary element
|
||||
pGui->sElemTmp = sElem;
|
||||
pGui->sElemRefTmp.pElem = &(pGui->sElemTmp);
|
||||
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
|
||||
return &(pGui->sElemRefTmp);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void gslc_ElemXGaugeSetStyle(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teXGaugeStyle nStyle)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeSetStyle";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
// Update the type element
|
||||
pGauge->nStyle = nStyle;
|
||||
|
||||
// Just in case we were called at runtime, mark as needing redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
void gslc_ElemXGaugeSetIndicator(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_tsColor colGauge,
|
||||
uint16_t nIndicLen,uint16_t nIndicTip,bool bIndicFill)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeSetIndicator";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
// Update the config
|
||||
pGauge->colGauge = colGauge;
|
||||
pGauge->nIndicLen = nIndicLen;
|
||||
pGauge->nIndicTip = nIndicTip;
|
||||
pGauge->bIndicFill = bIndicFill;
|
||||
|
||||
// Just in case we were called at runtime, mark as needing redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
void gslc_ElemXGaugeSetTicks(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_tsColor colTick,uint16_t nTickCnt,uint16_t nTickLen)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeSetTicks";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
// Update the config
|
||||
pGauge->colTick = colTick;
|
||||
pGauge->nTickCnt = nTickCnt;
|
||||
pGauge->nTickLen = nTickLen;
|
||||
|
||||
// Just in case we were called at runtime, mark as needing redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
// Update the gauge control's current position
|
||||
void gslc_ElemXGaugeUpdate(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,int16_t nVal)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeUpdate";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
// Update the data element
|
||||
int16_t nValOld = pGauge->nVal;
|
||||
pGauge->nVal = nVal;
|
||||
|
||||
// Element needs redraw
|
||||
if (nVal != nValOld) {
|
||||
// We only need an incremental redraw
|
||||
// NOTE: If the user configures the indicator to be
|
||||
// long enough that it overlaps some of the gauge indicators
|
||||
// then a full redraw should be done instead.
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Update the gauge's fill direction
|
||||
// - Setting bFlip causes the gauge to be filled in the reverse direction
|
||||
// to the default
|
||||
// - Default fill direction for horizontal gauges: left-to-right
|
||||
// - Default fill direction for vertical gauges: bottom-to-top
|
||||
void gslc_ElemXGaugeSetFlip(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bFlip)
|
||||
{
|
||||
if (pElemRef == NULL) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeSetFlip";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
|
||||
// Fetch the element's extended data structure
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
if (pGauge == NULL) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: gslc_ElemXGaugeSetFlip(%s) pXData is NULL\n","");
|
||||
return;
|
||||
}
|
||||
pGauge->bFlip = bFlip;
|
||||
|
||||
// Mark for redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
|
||||
}
|
||||
|
||||
|
||||
// Redraw the gauge
|
||||
// - Note that this redraw is for the entire element rect region
|
||||
// - The Draw function parameters use void pointers to allow for
|
||||
// simpler callback function definition & scalability.
|
||||
bool gslc_ElemXGaugeDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
if ((pvGui == NULL) || (pvElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGaugeDraw";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Typecast the parameters to match the GUI and element types
|
||||
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||||
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
|
||||
// Fetch the element's extended data structure
|
||||
gslc_tsXGauge* pGauge;
|
||||
pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
if (pGauge == NULL) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: ElemXGaugeDraw(%s) pXData is NULL\n","");
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (pGauge->nStyle) {
|
||||
case GSLCX_GAUGE_STYLE_PROG_BAR:
|
||||
gslc_ElemXGaugeDrawProgressBar(pGui,pElemRef,eRedraw);
|
||||
break;
|
||||
case GSLCX_GAUGE_STYLE_RADIAL:
|
||||
#if (GSLC_FEATURE_XGAUGE_RADIAL)
|
||||
gslc_ElemXGaugeDrawRadial(pGui,pElemRef,eRedraw);
|
||||
#endif
|
||||
break;
|
||||
case GSLCX_GAUGE_STYLE_RAMP:
|
||||
#if (GSLC_FEATURE_XGAUGE_RAMP)
|
||||
gslc_ElemXGaugeDrawRamp(pGui,pElemRef,eRedraw);
|
||||
#endif
|
||||
break;
|
||||
default:
|
||||
// ERROR
|
||||
break;
|
||||
}
|
||||
|
||||
// Save as "last state" to support incremental erase/redraw
|
||||
pGauge->nValLast = pGauge->nVal;
|
||||
pGauge->bValLastValid = true;
|
||||
|
||||
// Clear the redraw flag
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_NONE);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool gslc_ElemXGaugeDrawProgressBar(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
gslc_tsRect rTmp; // Temporary rect for drawing
|
||||
gslc_tsRect rGauge; // Filled portion of gauge
|
||||
gslc_tsRect rEmpty; // Empty portion of gauge
|
||||
uint16_t nElemW,nElemH;
|
||||
int16_t nElemX0,nElemY0,nElemX1,nElemY1;
|
||||
int16_t nGaugeX0,nGaugeY0,nGaugeX1,nGaugeY1;
|
||||
|
||||
nElemX0 = pElem->rElem.x;
|
||||
nElemY0 = pElem->rElem.y;
|
||||
nElemX1 = pElem->rElem.x + pElem->rElem.w - 1;
|
||||
nElemY1 = pElem->rElem.y + pElem->rElem.h - 1;
|
||||
nElemW = pElem->rElem.w;
|
||||
nElemH = pElem->rElem.h;
|
||||
|
||||
bool bVert = pGauge->bVert;
|
||||
bool bFlip = pGauge->bFlip;
|
||||
int16_t nMax = pGauge->nMax;
|
||||
int16_t nMin = pGauge->nMin;
|
||||
int16_t nRng = pGauge->nMax - pGauge->nMin;
|
||||
|
||||
uint32_t nScl = 1;
|
||||
int16_t nGaugeMid = 0;
|
||||
int16_t nLen = 0;
|
||||
int16_t nTmp = 0;
|
||||
int32_t nTmpL = 0;
|
||||
|
||||
if (nRng == 0) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: ElemXGaugeDraw() Zero gauge range [%d,%d]\n",nMin,nMax);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (bVert) {
|
||||
nScl = nElemH*32768/nRng;
|
||||
} else {
|
||||
nScl = nElemW*32768/nRng;
|
||||
}
|
||||
|
||||
// Calculate the control midpoint/zeropoint (for display purposes)
|
||||
nTmpL = -((int32_t)nMin * (int32_t)nScl / 32768);
|
||||
nGaugeMid = (int16_t)nTmpL;
|
||||
|
||||
|
||||
// Calculate the length of the bar
|
||||
// - Use long mult/divide to avoid need for floating point
|
||||
nTmpL = (int32_t)(pGauge->nVal) * (int32_t)(nScl) / 32768;
|
||||
nLen = (int16_t)(nTmpL);
|
||||
|
||||
// Define the gauge's fill rectangle region
|
||||
// depending on the orientation (bVert) and whether
|
||||
// the current position is negative or positive.
|
||||
if (nLen >= 0) {
|
||||
if (bVert) {
|
||||
nGaugeY0 = nElemY0 + nGaugeMid;
|
||||
nGaugeY1 = nElemY0 + nGaugeMid + nLen;
|
||||
} else {
|
||||
nGaugeX0 = nElemX0 + nGaugeMid;
|
||||
nGaugeX1 = nElemX0 + nGaugeMid + nLen;
|
||||
}
|
||||
} else {
|
||||
if (bVert) {
|
||||
nGaugeY0 = nElemY0 + nGaugeMid + nLen;
|
||||
nGaugeY1 = nElemY0 + nGaugeMid;
|
||||
} else {
|
||||
nGaugeX0 = nElemX0 + nGaugeMid + nLen;
|
||||
nGaugeX1 = nElemX0 + nGaugeMid;
|
||||
}
|
||||
}
|
||||
if (bVert) {
|
||||
nGaugeX0 = nElemX0;
|
||||
nGaugeX1 = nElemX1;
|
||||
} else {
|
||||
nGaugeY0 = nElemY0;
|
||||
nGaugeY1 = nElemY1;
|
||||
}
|
||||
|
||||
|
||||
// Clip the region
|
||||
nGaugeX0 = (nGaugeX0 < nElemX0)? nElemX0 : nGaugeX0;
|
||||
nGaugeY0 = (nGaugeY0 < nElemY0)? nElemY0 : nGaugeY0;
|
||||
nGaugeX1 = (nGaugeX1 > nElemX1)? nElemX1 : nGaugeX1;
|
||||
nGaugeY1 = (nGaugeY1 > nElemY1)? nElemY1 : nGaugeY1;
|
||||
|
||||
// Support flipping of gauge directionality
|
||||
// - The bFlip flag reverses the fill direction
|
||||
// - Vertical gauges are flipped by default
|
||||
|
||||
if (bVert && !bFlip) {
|
||||
nTmp = nElemY0+(nElemY1-nGaugeY1); // nTmp will be swapped into nGaugeY0
|
||||
nGaugeY1 = nElemY1-(nGaugeY0-nElemY0);
|
||||
nGaugeY0 = nTmp;
|
||||
nGaugeMid = nElemH-nGaugeMid-1;
|
||||
} else if (!bVert && bFlip) {
|
||||
nTmp = nElemX0+(nElemX1-nGaugeX1); // nTmp will be swapped into nGaugeX0
|
||||
nGaugeX1 = nElemX1-(nGaugeX0-nElemX0);
|
||||
nGaugeX0 = nTmp;
|
||||
nGaugeMid = nElemW-nGaugeMid-1;
|
||||
}
|
||||
|
||||
#ifdef DBG_LOG
|
||||
//printf("Gauge: nMin=%4d nMax=%4d nRng=%d nVal=%4d fScl=%6.3f nGaugeMid=%4d RectX=%4d RectW=%4d\n",
|
||||
// nMin,nMax,nRng,pGauge->nGaugeVal,fScl,nGaugeMid,rGauge.x,rGauge.w);
|
||||
#endif
|
||||
|
||||
// Draw a frame around the gauge
|
||||
// - Only draw this during full redraw
|
||||
if (eRedraw == GSLC_REDRAW_FULL) {
|
||||
gslc_DrawFrameRect(pGui, pElem->rElem, pElem->colElemFrame);
|
||||
}
|
||||
|
||||
// To avoid flicker, we only erase the portion of the gauge
|
||||
// that isn't "filled". Determine the gauge empty region and erase it
|
||||
// There are two empty regions (one in negative and one in positive)
|
||||
int16_t nEmptyPos;
|
||||
if (bVert) {
|
||||
// Empty Region #1 (negative)
|
||||
nEmptyPos = (nGaugeY0 > nElemY1) ? nElemY1 : nGaugeY0;
|
||||
rEmpty = (gslc_tsRect){nElemX0,nElemY0,nElemX1-nElemX0+1,nEmptyPos-nElemY0+1};
|
||||
rTmp = gslc_ExpandRect(rEmpty,-1,-1);
|
||||
gslc_DrawFillRect(pGui,rTmp,pElem->colElemFill);
|
||||
// Empty Region #2 (positive)
|
||||
nEmptyPos = (nGaugeY1 < nElemY0) ? nElemY0 : nGaugeY1;
|
||||
rEmpty = (gslc_tsRect){nElemX0,nEmptyPos,nElemX1-nElemX0+1,nElemY1-nEmptyPos+1};
|
||||
rTmp = gslc_ExpandRect(rEmpty,-1,-1);
|
||||
gslc_DrawFillRect(pGui,rTmp,pElem->colElemFill);
|
||||
} else {
|
||||
// Empty Region #1 (negative)
|
||||
nEmptyPos = (nGaugeX0 > nElemX1) ? nElemX1 : nGaugeX0;
|
||||
rEmpty = (gslc_tsRect){nElemX0,nElemY0,nEmptyPos-nElemX0+1,nElemY1-nElemY0+1};
|
||||
rTmp = gslc_ExpandRect(rEmpty,-1,-1);
|
||||
gslc_DrawFillRect(pGui, rTmp, pElem->colElemFill);
|
||||
// Empty Region #2 (positive)
|
||||
nEmptyPos = (nGaugeX1 < nElemX0) ? nElemX0 : nGaugeX1;
|
||||
rEmpty = (gslc_tsRect){nEmptyPos,nElemY0,nElemX1-nEmptyPos+1,nElemY1-nElemY0+1};
|
||||
rTmp = gslc_ExpandRect(rEmpty,-1,-1);
|
||||
gslc_DrawFillRect(pGui, rTmp, pElem->colElemFill);
|
||||
}
|
||||
|
||||
// Draw the gauge fill region
|
||||
rGauge = (gslc_tsRect){nGaugeX0,nGaugeY0,nGaugeX1-nGaugeX0+1,nGaugeY1-nGaugeY0+1};
|
||||
rTmp = gslc_ExpandRect(rGauge,-1,-1);
|
||||
gslc_DrawFillRect(pGui,rTmp,pGauge->colGauge);
|
||||
|
||||
|
||||
// Draw the midpoint line
|
||||
if (bVert) {
|
||||
if (nElemY0 + nGaugeMid < nElemY1) {
|
||||
gslc_DrawLine(pGui, nElemX0, nElemY0 + nGaugeMid, nElemX1, nElemY0 + nGaugeMid, pElem->colElemFrame);
|
||||
}
|
||||
} else {
|
||||
if (nElemX0 + nGaugeMid < nElemX1) {
|
||||
gslc_DrawLine(pGui, nElemX0 + nGaugeMid, nElemY0, nElemX0 + nGaugeMid, nElemY1, pElem->colElemFrame);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#if (GSLC_FEATURE_XGAUGE_RADIAL)
|
||||
void gslc_ElemXGaugeDrawRadialHelp(gslc_tsGui* pGui,int16_t nX,int16_t nY,uint16_t nArrowLen,uint16_t nArrowSz,int16_t n64Ang,bool bFill,gslc_tsColor colFrame)
|
||||
{
|
||||
int16_t nTipX,nTipY;
|
||||
int16_t nBaseX1,nBaseY1,nBaseX2,nBaseY2;
|
||||
int16_t nTipBaseX,nTipBaseY;
|
||||
|
||||
gslc_PolarToXY(nArrowLen,n64Ang,&nTipX,&nTipY);
|
||||
gslc_PolarToXY(nArrowLen-nArrowSz,n64Ang,&nTipBaseX,&nTipBaseY);
|
||||
gslc_PolarToXY(nArrowSz,n64Ang-90*64,&nBaseX1,&nBaseY1);
|
||||
gslc_PolarToXY(nArrowSz,n64Ang+90*64,&nBaseX2,&nBaseY2);
|
||||
|
||||
if (!bFill) {
|
||||
// Framed
|
||||
gslc_DrawLine(pGui,nX+nBaseX1,nY+nBaseY1,nX+nBaseX1+nTipBaseX,nY+nBaseY1+nTipBaseY,colFrame);
|
||||
gslc_DrawLine(pGui,nX+nBaseX2,nY+nBaseY2,nX+nBaseX2+nTipBaseX,nY+nBaseY2+nTipBaseY,colFrame);
|
||||
gslc_DrawLine(pGui,nX+nBaseX1+nTipBaseX,nY+nBaseY1+nTipBaseY,nX+nTipX,nY+nTipY,colFrame);
|
||||
gslc_DrawLine(pGui,nX+nBaseX2+nTipBaseX,nY+nBaseY2+nTipBaseY,nX+nTipX,nY+nTipY,colFrame);
|
||||
gslc_DrawLine(pGui,nX+nBaseX1,nY+nBaseY1,nX+nBaseX2,nY+nBaseY2,colFrame);
|
||||
|
||||
} else {
|
||||
// Filled
|
||||
gslc_tsPt asPt[4];
|
||||
|
||||
// Main body of pointer
|
||||
asPt[0] = (gslc_tsPt){nX+nBaseX1,nY+nBaseY1};
|
||||
asPt[1] = (gslc_tsPt){nX+nBaseX1+nTipBaseX,nY+nBaseY1+nTipBaseY};
|
||||
asPt[2] = (gslc_tsPt){nX+nBaseX2+nTipBaseX,nY+nBaseY2+nTipBaseY};
|
||||
asPt[3] = (gslc_tsPt){nX+nBaseX2,nY+nBaseY2};
|
||||
gslc_DrawFillQuad(pGui,asPt,colFrame);
|
||||
|
||||
// Tip of pointer
|
||||
asPt[0] = (gslc_tsPt){nX+nBaseX1+nTipBaseX,nY+nBaseY1+nTipBaseY};
|
||||
asPt[1] = (gslc_tsPt){nX+nTipX,nY+nTipY};
|
||||
asPt[2] = (gslc_tsPt){nX+nBaseX2+nTipBaseX,nY+nBaseY2+nTipBaseY};
|
||||
gslc_DrawFillTriangle(pGui,asPt[0].x,asPt[0].y,asPt[1].x,asPt[1].y,asPt[2].x,asPt[2].y,colFrame);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool gslc_ElemXGaugeDrawRadial(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
uint16_t nElemW,nElemH,nElemRad;
|
||||
int16_t nElemX0,nElemY0,nElemX1,nElemY1;
|
||||
int16_t nElemMidX,nElemMidY;
|
||||
nElemX0 = pElem->rElem.x;
|
||||
nElemY0 = pElem->rElem.y;
|
||||
nElemX1 = pElem->rElem.x + pElem->rElem.w - 1;
|
||||
nElemY1 = pElem->rElem.y + pElem->rElem.h - 1;
|
||||
nElemMidX = (nElemX0+nElemX1)/2;
|
||||
nElemMidY = (nElemY0+nElemY1)/2;
|
||||
nElemW = pElem->rElem.w;
|
||||
nElemH = pElem->rElem.h;
|
||||
nElemRad = (nElemW>=nElemH)? nElemH/2 : nElemW/2;
|
||||
|
||||
int16_t nMax = pGauge->nMax;
|
||||
int16_t nMin = pGauge->nMin;
|
||||
int16_t nRng = pGauge->nMax - pGauge->nMin;
|
||||
int16_t nVal = pGauge->nVal;
|
||||
int16_t nValLast = pGauge->nValLast;
|
||||
bool bValLastValid = pGauge->bValLastValid;
|
||||
uint16_t nTickLen = pGauge->nTickLen;
|
||||
uint16_t nTickAng = 360 / pGauge->nTickCnt;
|
||||
uint16_t nArrowLen = pGauge->nIndicLen;
|
||||
uint16_t nArrowSize = pGauge->nIndicTip;
|
||||
bool bFill = pGauge->bIndicFill;
|
||||
|
||||
int16_t n64Ang,n64AngLast;
|
||||
int16_t nInd;
|
||||
|
||||
|
||||
if (nRng == 0) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: ElemXRadialDraw() Zero range [%d,%d]\n",nMin,nMax);
|
||||
return false;
|
||||
}
|
||||
|
||||
// Support reversing of direction
|
||||
// TODO: Clean up excess integer typecasting
|
||||
if (pGauge->bFlip) {
|
||||
n64Ang = (int32_t)(nMax - nVal )* 360*64 /nRng;
|
||||
n64AngLast = (int32_t)(nMax - nValLast)* 360*64 /nRng;
|
||||
} else {
|
||||
n64Ang = (int32_t)(nVal - nMin)* 360*64 /nRng;
|
||||
n64AngLast = (int32_t)(nValLast - nMin)* 360*64 /nRng;
|
||||
}
|
||||
|
||||
// Clear old
|
||||
if (bValLastValid) {
|
||||
gslc_ElemXGaugeDrawRadialHelp(pGui,nElemMidX,nElemMidY,nArrowLen,nArrowSize,n64AngLast,bFill,pElem->colElemFill);
|
||||
}
|
||||
|
||||
// Draw frame
|
||||
if (eRedraw == GSLC_REDRAW_FULL) {
|
||||
gslc_DrawFillCircle(pGui,nElemMidX,nElemMidY,nElemRad,pElem->colElemFill); // Erase first
|
||||
gslc_DrawFrameCircle(pGui,nElemMidX,nElemMidY,nElemRad,pElem->colElemFrame);
|
||||
for (nInd=0;nInd<360;nInd+=nTickAng) {
|
||||
gslc_DrawLinePolar(pGui,nElemMidX,nElemMidY,nElemRad-nTickLen,nElemRad,nInd*64,pGauge->colTick);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw pointer
|
||||
gslc_ElemXGaugeDrawRadialHelp(pGui,nElemMidX,nElemMidY,nArrowLen,nArrowSize,n64Ang,bFill,pGauge->colGauge);
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // GSLC_FEATURE_XGAUGE_RADIAL
|
||||
|
||||
#ifdef GSLC_FEATURE_XGAUGE_RAMP
|
||||
bool gslc_ElemXGaugeDrawRamp(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGauge* pGauge = (gslc_tsXGauge*)(pElem->pXData);
|
||||
|
||||
uint16_t nElemW,nElemH;
|
||||
int16_t nElemX0,nElemY1;
|
||||
nElemX0 = pElem->rElem.x;
|
||||
nElemY1 = pElem->rElem.y + pElem->rElem.h - 1;
|
||||
nElemW = pElem->rElem.w;
|
||||
nElemH = pElem->rElem.h;
|
||||
|
||||
int16_t nMax = pGauge->nMax;
|
||||
int16_t nMin = pGauge->nMin;
|
||||
int16_t nRng = pGauge->nMax - pGauge->nMin;
|
||||
int16_t nVal = pGauge->nVal;
|
||||
int16_t nValLast = pGauge->nValLast;
|
||||
bool bValLastValid = pGauge->bValLastValid;
|
||||
int16_t nInd;
|
||||
|
||||
if (nRng == 0) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: gslc_ElemXGaugeDrawRamp() Zero range [%d,%d]\n",nMin,nMax);
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t nSclFX;
|
||||
uint16_t nHeight;
|
||||
int32_t nHeightTmp;
|
||||
uint16_t nHeightBot;
|
||||
uint16_t nX;
|
||||
uint16_t nColInd;
|
||||
|
||||
// Calculate region to draw or clear
|
||||
bool bModeErase;
|
||||
int16_t nValStart;
|
||||
int16_t nValEnd;
|
||||
if ((eRedraw == GSLC_REDRAW_INC) && (!bValLastValid)) {
|
||||
// - If the request was incremental (GSLC_REDRAW_INC) but
|
||||
// the last value wasn't marked as valid (!bValLastValid)
|
||||
// then we want to force a full redraw.
|
||||
// - We don't expect to enter here since bValLastValid
|
||||
// should always be set after we perform our first
|
||||
// redraw.
|
||||
eRedraw = GSLC_REDRAW_FULL;
|
||||
}
|
||||
if (eRedraw == GSLC_REDRAW_FULL) {
|
||||
// If we haven't drawn anything before, draw full range from zero
|
||||
bModeErase = false;
|
||||
nValStart = 0;
|
||||
nValEnd = nVal;
|
||||
} else {
|
||||
if (nVal >= nValLast) {
|
||||
// As we are advancing the control, we just draw the new range
|
||||
bModeErase = false;
|
||||
nValStart = nValLast;
|
||||
nValEnd = nVal;
|
||||
} else {
|
||||
// Since we are retracting the control, we erase the new range
|
||||
bModeErase = true;
|
||||
nValStart = nVal;
|
||||
nValEnd = nValLast;
|
||||
}
|
||||
}
|
||||
|
||||
// Calculate the scaled gauge position
|
||||
// - TODO: Also support reversing of direction
|
||||
int16_t nPosXStart,nPosXEnd;
|
||||
nPosXStart = (nValStart - nMin)*nElemW/nRng;
|
||||
nPosXEnd = (nValEnd - nMin)*nElemW/nRng;
|
||||
|
||||
nSclFX = (uint32_t)nElemH*32767/(nElemW*nElemW);
|
||||
|
||||
for (nX=nPosXStart;nX<nPosXEnd;nX++) {
|
||||
nInd = nElemW-nX;
|
||||
nHeightTmp = nSclFX * nInd*nInd /32767;
|
||||
nHeight = nElemH-nHeightTmp;
|
||||
if (nHeight >= 20) {
|
||||
nHeightBot = nHeight-20;
|
||||
} else {
|
||||
nHeightBot = 0;
|
||||
}
|
||||
gslc_tsColor nCol;
|
||||
uint16_t nSteps = 10;
|
||||
uint16_t nGap = 3;
|
||||
|
||||
if (nSteps == 0) {
|
||||
nColInd = nX*1000/nElemW;
|
||||
nCol = gslc_ColorBlend3(GSLC_COL_GREEN,GSLC_COL_YELLOW,GSLC_COL_RED,500,nColInd);
|
||||
} else {
|
||||
uint16_t nBlockLen,nSegLen,nSegInd,nSegOffset,nSegStart;
|
||||
nBlockLen = (nElemW-(nSteps-1)*nGap)/nSteps;
|
||||
nSegLen = nBlockLen + nGap;
|
||||
nSegInd = nX/nSegLen;
|
||||
nSegOffset = nX % nSegLen;
|
||||
nSegStart = nSegInd * nSegLen;
|
||||
|
||||
if (nSegOffset <= nBlockLen) {
|
||||
// Inside block
|
||||
nColInd = (uint32_t)nSegStart*1000/nElemW;
|
||||
nCol = gslc_ColorBlend3(GSLC_COL_GREEN,GSLC_COL_YELLOW,GSLC_COL_RED,500,nColInd);
|
||||
|
||||
} else {
|
||||
// Inside gap
|
||||
// - No draw
|
||||
nCol = pElem->colElemFill;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (bModeErase) {
|
||||
nCol = pElem->colElemFill;
|
||||
}
|
||||
gslc_DrawLine(pGui,nElemX0+nX,nElemY1-nHeightBot,nElemX0+nX,nElemY1-nHeight,nCol);
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
#endif // GLSC_FEATURE_XGAUGE_RAMP
|
||||
|
||||
|
||||
// ============================================================================
|
394
hardware/sd_card_formatter/src/guislice/XGauge.h
Normal file
394
hardware/sd_card_formatter/src/guislice/XGauge.h
Normal file
|
@ -0,0 +1,394 @@
|
|||
#ifndef _GUISLICE_EX_XGAUGE_H_
|
||||
#define _GUISLICE_EX_XGAUGE_H_
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library extension: Gauge control (See replacement warning below)
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XGauge.h
|
||||
|
||||
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
|
||||
// WARNING: The XGauge element has been replaced by XProgress / XRadial / XRamp
|
||||
// Please update your code according to the migration notes in:
|
||||
// https://github.com/ImpulseAdventure/GUIslice/pull/157
|
||||
// XGauge may be removed in a future release.
|
||||
// *-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-*-
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: Gauge
|
||||
// ============================================================================
|
||||
|
||||
// Define unique identifier for extended element type
|
||||
// - Select any number above GSLC_TYPE_BASE_EXTEND
|
||||
#define GSLC_TYPEX_GAUGE GSLC_TYPE_BASE_EXTEND + 0
|
||||
|
||||
|
||||
/// Gauge drawing style
|
||||
typedef enum {
|
||||
GSLCX_GAUGE_STYLE_PROG_BAR, ///< Progress bar
|
||||
GSLCX_GAUGE_STYLE_RADIAL, ///< Radial indicator
|
||||
GSLCX_GAUGE_STYLE_RAMP, ///< Ramp indicator
|
||||
} gslc_teXGaugeStyle;
|
||||
|
||||
// Extended element data structures
|
||||
// - These data structures are maintained in the gslc_tsElem
|
||||
// structure via the pXData pointer
|
||||
|
||||
/// Extended data for Gauge element
|
||||
typedef struct {
|
||||
// Range config
|
||||
int16_t nMin; ///< Minimum control value
|
||||
int16_t nMax; ///< Maximum control value
|
||||
|
||||
// Current value
|
||||
int16_t nVal; ///< Current control value
|
||||
// Previous value
|
||||
int16_t nValLast; ///< Last value
|
||||
bool bValLastValid; ///< Last value valid?
|
||||
|
||||
// Appearance config
|
||||
gslc_teXGaugeStyle nStyle; ///< Gauge sub-type
|
||||
gslc_tsColor colGauge; ///< Color of gauge fill bar
|
||||
gslc_tsColor colTick; ///< Color of gauge tick marks
|
||||
uint16_t nTickCnt; ///< Number of gauge tick marks
|
||||
uint16_t nTickLen; ///< Length of gauge tick marks
|
||||
bool bVert; ///< Vertical if true, else Horizontal
|
||||
bool bFlip; ///< Reverse direction of gauge
|
||||
uint16_t nIndicLen; ///< Indicator length
|
||||
uint16_t nIndicTip; ///< Size of tip at end of indicator
|
||||
bool bIndicFill; ///< Fill the indicator if true
|
||||
|
||||
} gslc_tsXGauge;
|
||||
|
||||
|
||||
///
|
||||
/// Create a Gauge Element
|
||||
/// - Draws a gauge element that represents a proportion (nVal)
|
||||
/// between nMin and nMax.
|
||||
/// - Support gauge sub-types:
|
||||
/// - GSLC_TYPEX_GAUGE_PROG_BAR: Horizontal or vertical box with filled region
|
||||
/// - GSLC_TYPEX_GAUGE_RADIAL: Radial / compass indicator
|
||||
/// - Default appearance is a horizontal progress bar, but can be changed
|
||||
/// with gslc_ElemXGaugeSetStyle())
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nElemId: Element ID to assign (0..16383 or GSLC_ID_AUTO to autogen)
|
||||
/// \param[in] nPage: Page ID to attach element to
|
||||
/// \param[in] pXData: Ptr to extended element data structure
|
||||
/// \param[in] rElem: Rectangle coordinates defining gauge size
|
||||
/// \param[in] nMin: Minimum value of gauge for nVal comparison
|
||||
/// \param[in] nMax: Maximum value of gauge for nVal comparison
|
||||
/// \param[in] nVal: Starting value of gauge
|
||||
/// \param[in] colGauge: Color for the gauge indicator
|
||||
/// \param[in] bVert: Flag to indicate vertical vs horizontal action
|
||||
/// (true = vertical, false = horizontal)
|
||||
///
|
||||
/// \return Pointer to Element reference or NULL if failure
|
||||
///
|
||||
gslc_tsElemRef* gslc_ElemXGaugeCreate(gslc_tsGui* pGui,int16_t nElemId,int16_t nPage,
|
||||
gslc_tsXGauge* pXData,gslc_tsRect rElem,int16_t nMin,int16_t nMax,int16_t nVal,gslc_tsColor colGauge,bool bVert);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the style of a Gauge element
|
||||
/// - This function is used to select between one of several gauge types
|
||||
/// (eg. progress bar, radial dial, etc.)
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] nType: Gauge style enumeration
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXGaugeSetStyle(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teXGaugeStyle nType);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the appearance of the Gauge indicator
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] colGauge: Color of the indicator
|
||||
/// \param[in] nIndicLen: Length of the indicator
|
||||
/// \param[in] nIndicTip: Size of the indicator tip
|
||||
/// \param[in] bIndicFill: Fill in the indicator if true
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXGaugeSetIndicator(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_tsColor colGauge,
|
||||
uint16_t nIndicLen,uint16_t nIndicTip,bool bIndicFill);
|
||||
|
||||
|
||||
///
|
||||
/// Configure the appearance of the Gauge ticks
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] colTick: Color of the gauge ticks
|
||||
/// \param[in] nTickCnt: Number of ticks to draw around / along gauge
|
||||
/// \param[in] nTickLen: Length of the tick marks to draw
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXGaugeSetTicks(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_tsColor colTick,uint16_t nTickCnt,uint16_t nTickLen);
|
||||
|
||||
|
||||
///
|
||||
/// Update a Gauge element's current value
|
||||
/// - Note that min & max values are assigned in create()
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] nVal: New value to show in gauge
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXGaugeUpdate(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,int16_t nVal);
|
||||
|
||||
|
||||
///
|
||||
/// Set a Gauge element's fill direction
|
||||
/// - Setting bFlip reverses the default fill direction
|
||||
/// - Default fill direction for horizontal gauges: left-to-right
|
||||
/// - Default fill direction for vertical gauges: bottom-to-top
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] pElemRef: Pointer to Element reference
|
||||
/// \param[in] bFlip: If set, reverse direction of fill from default
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
void gslc_ElemXGaugeSetFlip(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,bool bFlip);
|
||||
|
||||
|
||||
///
|
||||
/// Draw a gauge element on the screen
|
||||
/// - Called from gslc_ElemDraw()
|
||||
///
|
||||
/// \param[in] pvGui: Void ptr to GUI (typecast to gslc_tsGui*)
|
||||
/// \param[in] pvElemRef: Void ptr to Element reference (typecast to gslc_tsElemRef*)
|
||||
/// \param[in] eRedraw: Redraw mode
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXGaugeDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw);
|
||||
|
||||
|
||||
///
|
||||
/// Helper function to draw a gauge with style: progress bar
|
||||
/// - Called from gslc_ElemXGaugeDraw()
|
||||
///
|
||||
/// \param[in] pGui: Ptr to GUI
|
||||
/// \param[in] pElemRef: Ptr to Element reference
|
||||
/// \param[in] eRedraw: Redraw status
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXGaugeDrawProgressBar(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw);
|
||||
|
||||
#if (GSLC_FEATURE_XGAUGE_RADIAL)
|
||||
///
|
||||
/// Helper function to draw a gauge with style: radial
|
||||
/// - Called from gslc_ElemXGaugeDraw()
|
||||
///
|
||||
/// \param[in] pGui: Ptr to GUI
|
||||
/// \param[in] pElemRef: Ptr to Element reference
|
||||
/// \param[in] eRedraw: Redraw status
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXGaugeDrawRadial(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw);
|
||||
#endif
|
||||
|
||||
#if (GSLC_FEATURE_XGAUGE_RAMP)
|
||||
///
|
||||
/// Helper function to draw a gauge with style: ramp
|
||||
/// - Called from gslc_ElemXGaugeDraw()
|
||||
///
|
||||
/// \param[in] pGui: Ptr to GUI
|
||||
/// \param[in] pElemRef: Ptr to Element reference
|
||||
/// \param[in] eRedraw: Redraw status
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXGaugeDrawRamp(gslc_tsGui* pGui,gslc_tsElemRef* pElemRef,gslc_teRedrawType eRedraw);
|
||||
#endif
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Read-only element macros
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Macro initializers for Read-Only Elements in Flash/PROGMEM
|
||||
//
|
||||
|
||||
|
||||
/// \def gslc_ElemXGaugeCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,
|
||||
/// nMin_,nMax_,nVal_,colFrame_,colFill_,colGauge_,bVert_)
|
||||
///
|
||||
/// Create a Gauge Element in Flash
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nElemId: Unique element ID to assign
|
||||
/// \param[in] nPage: Page ID to attach element to
|
||||
/// \param[in] nX: X coordinate of element
|
||||
/// \param[in] nY: Y coordinate of element
|
||||
/// \param[in] nW: Width of element
|
||||
/// \param[in] nH: Height of element
|
||||
/// \param[in] nMin_: Minimum value of gauge for nVal comparison
|
||||
/// \param[in] nMax_: Maximum value of gauge for nVal comparison
|
||||
/// \param[in] nVal_: Starting value of gauge
|
||||
/// \param[in] colFrame_: Color for the gauge frame
|
||||
/// \param[in] colFill_: Color for the gauge background fill
|
||||
/// \param[in] colGauge_: Color for the gauge indicator
|
||||
/// \param[in] bVert_: Flag to indicate vertical vs horizontal action
|
||||
/// (true = vertical, false = horizontal)
|
||||
///
|
||||
/// \return none
|
||||
///
|
||||
|
||||
|
||||
#if (GSLC_USE_PROGMEM)
|
||||
|
||||
|
||||
#define gslc_ElemXGaugeCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,\
|
||||
nMin_,nMax_,nVal_,colFrame_,colFill_,colGauge_,bVert_) \
|
||||
static const uint8_t nFeatures##nElemId = GSLC_ELEM_FEA_VALID | \
|
||||
GSLC_ELEM_FEA_GLOW_EN | GSLC_ELEM_FEA_FILL_EN; \
|
||||
static gslc_tsXGauge sGauge##nElemId; \
|
||||
sGauge##nElemId.nMin = nMin_; \
|
||||
sGauge##nElemId.nMax = nMax_; \
|
||||
sGauge##nElemId.nVal = nVal_; \
|
||||
sGauge##nElemId.nValLast = nVal_; \
|
||||
sGauge##nElemId.bValLastValid = false; \
|
||||
sGauge##nElemId.nStyle = GSLCX_GAUGE_STYLE_PROG_BAR; \
|
||||
sGauge##nElemId.colGauge = colGauge_; \
|
||||
sGauge##nElemId.colTick = GSLC_COL_GRAY; \
|
||||
sGauge##nElemId.nTickCnt = 8; \
|
||||
sGauge##nElemId.nTickLen = 5; \
|
||||
sGauge##nElemId.bVert = bVert_; \
|
||||
sGauge##nElemId.bFlip = false; \
|
||||
sGauge##nElemId.nIndicLen = 10; \
|
||||
sGauge##nElemId.nIndicTip = 3; \
|
||||
sGauge##nElemId.bIndicFill = false; \
|
||||
static const gslc_tsElem sElem##nElemId PROGMEM = { \
|
||||
nElemId, \
|
||||
nFeatures##nElemId, \
|
||||
GSLC_TYPEX_GAUGE, \
|
||||
(gslc_tsRect){nX,nY,nW,nH}, \
|
||||
GSLC_GROUP_ID_NONE, \
|
||||
colFrame_,colFill_,colFrame_,colFill_, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
0, \
|
||||
(gslc_teTxtFlags)(GSLC_TXT_DEFAULT), \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_ALIGN_MID_MID, \
|
||||
0, \
|
||||
0, \
|
||||
NULL, \
|
||||
(void*)(&sGauge##nElemId), \
|
||||
NULL, \
|
||||
&gslc_ElemXGaugeDraw, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
}; \
|
||||
gslc_ElemAdd(pGui,nPage,(gslc_tsElem*)&sElem##nElemId, \
|
||||
(gslc_teElemRefFlags)(GSLC_ELEMREF_SRC_PROG | GSLC_ELEMREF_VISIBLE | GSLC_ELEMREF_REDRAW_FULL));
|
||||
|
||||
#else
|
||||
|
||||
|
||||
#define gslc_ElemXGaugeCreate_P(pGui,nElemId,nPage,nX,nY,nW,nH,\
|
||||
nMin_,nMax_,nVal_,colFrame_,colFill_,colGauge_,bVert_) \
|
||||
static const uint8_t nFeatures##nElemId = GSLC_ELEM_FEA_VALID | \
|
||||
GSLC_ELEM_FEA_GLOW_EN | GSLC_ELEM_FEA_FILL_EN; \
|
||||
static gslc_tsXGauge sGauge##nElemId; \
|
||||
sGauge##nElemId.nMin = nMin_; \
|
||||
sGauge##nElemId.nMax = nMax_; \
|
||||
sGauge##nElemId.nVal = nVal_; \
|
||||
sGauge##nElemId.nValLast = nVal_; \
|
||||
sGauge##nElemId.bValLastValid = false; \
|
||||
sGauge##nElemId.nStyle = GSLCX_GAUGE_STYLE_PROG_BAR; \
|
||||
sGauge##nElemId.colGauge = colGauge_; \
|
||||
sGauge##nElemId.colTick = GSLC_COL_GRAY; \
|
||||
sGauge##nElemId.nTickCnt = 8; \
|
||||
sGauge##nElemId.nTickLen = 5; \
|
||||
sGauge##nElemId.bVert = bVert_; \
|
||||
sGauge##nElemId.bFlip = false; \
|
||||
sGauge##nElemId.nIndicLen = 10; \
|
||||
sGauge##nElemId.nIndicTip = 3; \
|
||||
sGauge##nElemId.bIndicFill = false; \
|
||||
static const gslc_tsElem sElem##nElemId = { \
|
||||
nElemId, \
|
||||
nFeatures##nElemId, \
|
||||
GSLC_TYPEX_GAUGE, \
|
||||
(gslc_tsRect){nX,nY,nW,nH}, \
|
||||
GSLC_GROUP_ID_NONE, \
|
||||
colFrame_,colFill_,colFrame_,colFill_, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
(gslc_tsImgRef){NULL,NULL,GSLC_IMGREF_NONE,NULL}, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
0, \
|
||||
(gslc_teTxtFlags)(GSLC_TXT_DEFAULT), \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_COL_WHITE, \
|
||||
GSLC_ALIGN_MID_MID, \
|
||||
0, \
|
||||
0, \
|
||||
NULL, \
|
||||
(void*)(&sGauge##nElemId), \
|
||||
NULL, \
|
||||
&gslc_ElemXGaugeDraw, \
|
||||
NULL, \
|
||||
NULL, \
|
||||
}; \
|
||||
gslc_ElemAdd(pGui,nPage,(gslc_tsElem*)&sElem##nElemId, \
|
||||
(gslc_teElemRefFlags)(GSLC_ELEMREF_SRC_CONST | GSLC_ELEMREF_VISIBLE | GSLC_ELEMREF_REDRAW_FULL));
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_EX_XGAUGE_H_
|
||||
|
348
hardware/sd_card_formatter/src/guislice/XGlowball.c
Normal file
348
hardware/sd_card_formatter/src/guislice/XGlowball.c
Normal file
|
@ -0,0 +1,348 @@
|
|||
// =======================================================================
|
||||
// GUIslice library extension: XGlowball
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XGlowball.c
|
||||
|
||||
|
||||
|
||||
// GUIslice library
|
||||
#include "GUIslice.h"
|
||||
#include "GUIslice_drv.h"
|
||||
|
||||
#include "XGlowball.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#if (GSLC_USE_PROGMEM)
|
||||
#include <avr/pgmspace.h>
|
||||
#endif
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Error Messages
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
extern const char GSLC_PMEM ERRSTR_NULL[];
|
||||
extern const char GSLC_PMEM ERRSTR_PXD_NULL[];
|
||||
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
// Extended element definitions
|
||||
// ----------------------------------------------------------------------------
|
||||
//
|
||||
// - This file extends the core GUIslice functionality with
|
||||
// additional widget types
|
||||
//
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: XGlowball
|
||||
// ============================================================================
|
||||
|
||||
// Create a XGlowball element and add it to the GUI element list
|
||||
// - Defines default styling for the element
|
||||
// - Defines callback for redraw and touch
|
||||
gslc_tsElemRef* gslc_ElemXGlowballCreate(gslc_tsGui* pGui, int16_t nElemId, int16_t nPage,
|
||||
gslc_tsXGlowball* pXData, int16_t nMidX, int16_t nMidY, gslc_tsXGlowballRing* pRings, uint8_t nNumRings)
|
||||
{
|
||||
if ((pGui == NULL) || (pXData == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballCreate";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return NULL;
|
||||
}
|
||||
gslc_tsElem sElem;
|
||||
gslc_tsElemRef* pElemRef = NULL;
|
||||
|
||||
// Calculate the actual element dimensions based on the ring defintion
|
||||
// - Note that we use the outer radius of the last ring
|
||||
int16_t nRadMax;
|
||||
gslc_tsRect rElem;
|
||||
nRadMax = pRings[nNumRings - 1].nRad2;
|
||||
rElem.w = 2 * nRadMax;
|
||||
rElem.h = 2 * nRadMax;
|
||||
rElem.x = nMidX - nRadMax;
|
||||
rElem.y = nMidY - nRadMax;
|
||||
|
||||
sElem = gslc_ElemCreate(pGui,nElemId,nPage,GSLC_TYPEX_GLOW,rElem,NULL,0,GSLC_FONT_NONE);
|
||||
sElem.colElemFill = GSLC_COL_BLACK;
|
||||
sElem.colElemFillGlow = GSLC_COL_BLACK;
|
||||
sElem.colElemFrame = GSLC_COL_GRAY;
|
||||
sElem.colElemFrameGlow = GSLC_COL_GRAY;
|
||||
sElem.colElemText = GSLC_COL_WHITE;
|
||||
sElem.colElemTextGlow = GSLC_COL_WHITE;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_FILL_EN;
|
||||
sElem.nFeatures &= ~GSLC_ELEM_FEA_FRAME_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_CLICK_EN;
|
||||
sElem.nFeatures |= GSLC_ELEM_FEA_GLOW_EN;
|
||||
sElem.eTxtAlign = GSLC_ALIGN_MID_LEFT;
|
||||
|
||||
sElem.nGroup = GSLC_GROUP_ID_NONE;
|
||||
|
||||
// Initialize any pxData members with default parameters
|
||||
pXData->nVal = 0;
|
||||
pXData->nQuality = 72;
|
||||
pXData->nAngStart = 0;
|
||||
pXData->nAngEnd = 360;
|
||||
pXData->pRings = pRings;
|
||||
pXData->nNumRings = nNumRings;
|
||||
pXData->nMidX = nMidX;
|
||||
pXData->nMidY = nMidY;
|
||||
pXData->colBg = GSLC_COL_BLACK;
|
||||
pXData->nValLast = 0;
|
||||
|
||||
|
||||
sElem.pXData = (void*)(pXData);
|
||||
// Specify the custom drawing callback
|
||||
sElem.pfuncXDraw = &gslc_ElemXGlowballDraw;
|
||||
// Specify the custom touch tracking callback
|
||||
sElem.pfuncXTouch = NULL;
|
||||
|
||||
if (nPage != GSLC_PAGE_NONE) {
|
||||
pElemRef = gslc_ElemAdd(pGui,nPage,&sElem,GSLC_ELEMREF_DEFAULT);
|
||||
return pElemRef;
|
||||
#if (GSLC_FEATURE_COMPOUND)
|
||||
} else {
|
||||
// Save as temporary element
|
||||
pGui->sElemTmp = sElem;
|
||||
pGui->sElemRefTmp.pElem = &(pGui->sElemTmp);
|
||||
pGui->sElemRefTmp.eElemFlags = GSLC_ELEMREF_DEFAULT | GSLC_ELEMREF_REDRAW_FULL;
|
||||
return &(pGui->sElemRefTmp);
|
||||
#endif
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
void drawXGlowballArc(gslc_tsGui* pGui, gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nRad1, int16_t nRad2, gslc_tsColor cArc, uint16_t nAngStart, uint16_t nAngEnd)
|
||||
{
|
||||
gslc_tsPt anPts[4];
|
||||
// TODO: Cleanup
|
||||
int16_t nStep64 = 64*360 / pGlowball->nQuality;
|
||||
int16_t nAng64;
|
||||
int16_t nX, nY;
|
||||
int16_t nSegStart, nSegEnd;
|
||||
nSegStart = nAngStart * pGlowball->nQuality / 360;
|
||||
nSegEnd = nAngEnd * pGlowball->nQuality / 360;
|
||||
|
||||
for (uint16_t nSegInd = nSegStart; nSegInd < nSegEnd; nSegInd++) {
|
||||
nAng64 = nSegInd * nStep64;
|
||||
nAng64 = nAng64 % (360 * 64);
|
||||
|
||||
gslc_PolarToXY(nRad1, nAng64, &nX, &nY);
|
||||
anPts[0] = (gslc_tsPt) { nMidX + nX, nMidY + nY };
|
||||
gslc_PolarToXY(nRad2, nAng64, &nX, &nY);
|
||||
anPts[1] = (gslc_tsPt) { nMidX + nX, nMidY + nY };
|
||||
gslc_PolarToXY(nRad2, nAng64 + nStep64, &nX, &nY);
|
||||
anPts[2] = (gslc_tsPt) { nMidX + nX, nMidY + nY };
|
||||
gslc_PolarToXY(nRad1, nAng64 + nStep64, &nX, &nY);
|
||||
anPts[3] = (gslc_tsPt) { nMidX + nX, nMidY + nY };
|
||||
|
||||
gslc_DrawFillQuad(pGui, anPts, cArc);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void drawXGlowballRing(gslc_tsGui* pGui, gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nVal, uint16_t nAngStart, uint16_t nAngEnd, bool bErase)
|
||||
{
|
||||
int16_t nRad1, nRad2;
|
||||
gslc_tsColor cCol;
|
||||
|
||||
if ((nVal <= 0) || (nVal > pGlowball->nNumRings)) {
|
||||
return;
|
||||
}
|
||||
|
||||
nRad1 = pGlowball->pRings[nVal - 1].nRad1;
|
||||
nRad2 = pGlowball->pRings[nVal - 1].nRad2;
|
||||
cCol = (bErase) ? pGlowball->colBg : pGlowball->pRings[nVal - 1].cCol;
|
||||
|
||||
drawXGlowballArc(pGui, pGlowball, nMidX, nMidY, nRad1, nRad2, cCol, nAngStart, nAngEnd);
|
||||
}
|
||||
|
||||
// nAngStart & nAngEnd define the range (in degrees) for the XGlowball arcs
|
||||
// - Angles are measured with 0 degrees at the top, incrementing clockwise
|
||||
// - Note that the supported range is 0..510 degrees
|
||||
// nVal represents the value to set (0.. NUM_RINGS)
|
||||
// nMidX,nMidY define the center of the XGlowball
|
||||
void drawXGlowball(gslc_tsGui* pGui,gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nVal, uint16_t nAngStart, uint16_t nAngEnd)
|
||||
{
|
||||
int16_t nValLast = pGlowball->nValLast;
|
||||
int8_t nRingInd;
|
||||
|
||||
if (nVal > nValLast) {
|
||||
for (nRingInd = nValLast + 1; nRingInd <= nVal; nRingInd++) {
|
||||
drawXGlowballRing(pGui, pGlowball, nMidX, nMidY, nRingInd, nAngStart, nAngEnd, false);
|
||||
}
|
||||
} else {
|
||||
for (nRingInd = nValLast; nRingInd > nVal; nRingInd--) {
|
||||
drawXGlowballRing(pGui, pGlowball, nMidX, nMidY, nRingInd, nAngStart, nAngEnd, true);
|
||||
}
|
||||
}
|
||||
pGlowball->nValLast = nVal;
|
||||
}
|
||||
|
||||
void gslc_ElemXGlowballSetVal(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, int16_t nVal)
|
||||
{
|
||||
if ((pGui == NULL) || (pElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballSetVal";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGlowball* pGlowball = (gslc_tsXGlowball*)(pElem->pXData);
|
||||
|
||||
// Update the value
|
||||
pGlowball->nVal = nVal;
|
||||
|
||||
// Mark for redraw
|
||||
// - Only need incremental redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_INC);
|
||||
}
|
||||
|
||||
void gslc_ElemXGlowballSetAngles(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, int16_t nAngStart, int16_t nAngEnd)
|
||||
{
|
||||
if ((pGui == NULL) || (pElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballSetAngles";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGlowball* pGlowball = (gslc_tsXGlowball*)(pElem->pXData);
|
||||
|
||||
// Update the angular ranges
|
||||
pGlowball->nAngStart = nAngStart;
|
||||
pGlowball->nAngEnd = nAngEnd;
|
||||
|
||||
// Mark for redraw
|
||||
// - Force full redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
void gslc_ElemXGlowballSetQuality(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, uint16_t nQuality)
|
||||
{
|
||||
if ((pGui == NULL) || (pElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballSetQuality";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGlowball* pGlowball = (gslc_tsXGlowball*)(pElem->pXData);
|
||||
|
||||
// Update the rendering quality setting
|
||||
pGlowball->nQuality = nQuality;
|
||||
|
||||
// Mark for redraw
|
||||
// - Force full redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
void gslc_ElemXGlowballSetColorBack(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, gslc_tsColor colBg)
|
||||
{
|
||||
if ((pGui == NULL) || (pElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballSetColorBack";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return;
|
||||
}
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
gslc_tsXGlowball* pGlowball = (gslc_tsXGlowball*)(pElem->pXData);
|
||||
|
||||
// Update the background color
|
||||
pGlowball->colBg = colBg;
|
||||
|
||||
// Mark for redraw
|
||||
// - Force full redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_FULL);
|
||||
}
|
||||
|
||||
// Redraw the element
|
||||
// - Note that this redraw is for the entire element rect region
|
||||
// - The Draw function parameters use void pointers to allow for
|
||||
// simpler callback function definition & scalability.
|
||||
bool gslc_ElemXGlowballDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw)
|
||||
{
|
||||
if ((pvGui == NULL) || (pvElemRef == NULL)) {
|
||||
static const char GSLC_PMEM FUNCSTR[] = "ElemXGlowballDraw";
|
||||
GSLC_DEBUG2_PRINT_CONST(ERRSTR_NULL,FUNCSTR);
|
||||
return false;
|
||||
}
|
||||
// Typecast the parameters to match the GUI and element types
|
||||
gslc_tsGui* pGui = (gslc_tsGui*)(pvGui);
|
||||
gslc_tsElemRef* pElemRef = (gslc_tsElemRef*)(pvElemRef);
|
||||
gslc_tsElem* pElem = gslc_GetElemFromRef(pGui,pElemRef);
|
||||
|
||||
// Fetch the element's extended data structure
|
||||
gslc_tsXGlowball* pGlowball;
|
||||
pGlowball = (gslc_tsXGlowball*)(pElem->pXData);
|
||||
if (pGlowball == NULL) {
|
||||
GSLC_DEBUG2_PRINT("ERROR: ElemXGlowballDraw(%s) pXData is NULL\n","");
|
||||
return false;
|
||||
}
|
||||
|
||||
// --------------------------------------------------------------------------
|
||||
// Init for default drawing
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
int16_t nElemX,nElemY;
|
||||
uint16_t nElemW,nElemH;
|
||||
|
||||
nElemX = pElem->rElem.x;
|
||||
nElemY = pElem->rElem.y;
|
||||
nElemW = pElem->rElem.w;
|
||||
nElemH = pElem->rElem.h;
|
||||
|
||||
// Calculate center of XGlowball
|
||||
int16_t nMidX, nMidY;
|
||||
nMidX = nElemX + (nElemW / 2);
|
||||
nMidY = nElemY + (nElemH / 2);
|
||||
|
||||
// Fetch the current value
|
||||
int16_t nVal = pGlowball->nVal;
|
||||
int16_t nAngStart = pGlowball->nAngStart;
|
||||
int16_t nAngEnd = pGlowball->nAngEnd;
|
||||
|
||||
// Check to see if we need full redraw
|
||||
if (eRedraw == GSLC_REDRAW_FULL) {
|
||||
// Erase the region
|
||||
gslc_DrawFillRect(pGui, pElem->rElem, pGlowball->colBg);
|
||||
// Now force redraw from zero level to current value
|
||||
pGlowball->nValLast = 0;
|
||||
}
|
||||
|
||||
// Draw the glowball
|
||||
drawXGlowball(pGui, pGlowball, nMidX, nMidY, nVal, nAngStart, nAngEnd);
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
// Mark the element as no longer requiring redraw
|
||||
gslc_ElemSetRedraw(pGui,pElemRef,GSLC_REDRAW_NONE);
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
// ============================================================================
|
136
hardware/sd_card_formatter/src/guislice/XGlowball.h
Normal file
136
hardware/sd_card_formatter/src/guislice/XGlowball.h
Normal file
|
@ -0,0 +1,136 @@
|
|||
#ifndef _GUISLICE_EX_XGLOWBALL_H_
|
||||
#define _GUISLICE_EX_XGLOWBALL_H_
|
||||
|
||||
#include "GUIslice.h"
|
||||
|
||||
|
||||
// =======================================================================
|
||||
// GUIslice library extension: XGlowball
|
||||
// - Calvin Hass
|
||||
// - https://www.impulseadventure.com/elec/guislice-gui.html
|
||||
// - https://github.com/ImpulseAdventure/GUIslice
|
||||
// =======================================================================
|
||||
//
|
||||
// The MIT License
|
||||
//
|
||||
// Copyright 2016-2020 Calvin Hass
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
//
|
||||
// =======================================================================
|
||||
/// \file XGlowball.h
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif // __cplusplus
|
||||
|
||||
|
||||
// ============================================================================
|
||||
// Extended Element: Example template
|
||||
// ============================================================================
|
||||
|
||||
// Define unique identifier for extended element type
|
||||
// - Select any number above GSLC_TYPE_BASE_EXTEND
|
||||
#define GSLC_TYPEX_GLOW GSLC_TYPE_BASE_EXTEND + 24
|
||||
|
||||
// Defines the attributes of each ring in the XGlowball gauge
|
||||
typedef struct {
|
||||
uint8_t nRad1; // Inner radius
|
||||
uint8_t nRad2; // Outer radius
|
||||
gslc_tsColor cCol; // Fill color
|
||||
} gslc_tsXGlowballRing;
|
||||
|
||||
// Extended element data structures
|
||||
// - These data structures are maintained in the gslc_tsElem
|
||||
// structure via the pXData pointer
|
||||
|
||||
/// Extended data for Slider element
|
||||
typedef struct {
|
||||
// Config
|
||||
int16_t nMidX; ///< Gauge midpoint X coord
|
||||
int16_t nMidY; ///< Gauge midpoint Y coord
|
||||
gslc_tsXGlowballRing* pRings; ///< Ring definition array
|
||||
uint8_t nNumRings; ///< Number of rings in definition
|
||||
// Style config
|
||||
uint16_t nQuality; ///< Rendering quality (number of segments / rotation)
|
||||
int16_t nAngStart; ///< Starting angle (0..510 degrees)
|
||||
int16_t nAngEnd; ///< Ending angle (0..510 degrees)
|
||||
gslc_tsColor colBg; ///< Background color (for redraw)
|
||||
// State
|
||||
int16_t nVal; ///< Current value
|
||||
int16_t nValLast; ///< Previous value
|
||||
// Callbacks
|
||||
} gslc_tsXGlowball;
|
||||
|
||||
|
||||
///
|
||||
/// Create a XGlowball element
|
||||
///
|
||||
/// \param[in] pGui: Pointer to GUI
|
||||
/// \param[in] nElemId: Element ID to assign (0..16383 or GSLC_ID_AUTO to autogen)
|
||||
/// \param[in] nPage: Page ID to attach element to
|
||||
/// \param[in] pXData: Ptr to extended element data structure
|
||||
/// \param[in] nMidX: Center X coordinate
|
||||
/// \param[in] nMidY: Center Y coordinate
|
||||
/// \param[in] pRings: Pointer to tsXGlowballRing structure array defining appearance
|
||||
/// \param[in] nNumRings: Number of rings in pRings array
|
||||
///
|
||||
/// \return Pointer to Element reference or NULL if failure
|
||||
///
|
||||
gslc_tsElemRef* gslc_ElemXGlowballCreate(gslc_tsGui* pGui, int16_t nElemId, int16_t nPage,
|
||||
gslc_tsXGlowball* pXData, int16_t nMidX, int16_t nMidY, gslc_tsXGlowballRing* pRings, uint8_t nNumRings);
|
||||
|
||||
|
||||
///
|
||||
/// Draw the XGlowball element on the screen
|
||||
/// - Called from gslc_ElemDraw()
|
||||
///
|
||||
/// \param[in] pvGui: Void ptr to GUI (typecast to gslc_tsGui*)
|
||||
/// \param[in] pvElemRef: Void ptr to Element (typecast to gslc_tsElemRef*)
|
||||
/// \param[in] eRedraw: Redraw mode
|
||||
///
|
||||
/// \return true if success, false otherwise
|
||||
///
|
||||
bool gslc_ElemXGlowballDraw(void* pvGui,void* pvElemRef,gslc_teRedrawType eRedraw);
|
||||
|
||||
// XGlowball draw helper routines
|
||||
void drawXGlowballArc(gslc_tsGui* pGui, gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nRad1, int16_t nRad2, gslc_tsColor cArc, uint16_t nAngStart, uint16_t nAngEnd);
|
||||
void drawXGlowballRing(gslc_tsGui* pGui, gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nVal, uint16_t nAngStart, uint16_t nAngEnd, bool bErase);
|
||||
void drawXGlowball(gslc_tsGui* pGui, gslc_tsXGlowball* pGlowball, int16_t nMidX, int16_t nMidY, int16_t nVal, uint16_t nAngStart, uint16_t nAngEnd);
|
||||
|
||||
void gslc_ElemXGlowballSetAngles(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, int16_t nAngStart, int16_t nAngEnd);
|
||||
void gslc_ElemXGlowballSetVal(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, int16_t nVal);
|
||||
void gslc_ElemXGlowballSetQuality(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, uint16_t nQuality);
|
||||
void gslc_ElemXGlowballSetColorBack(gslc_tsGui* pGui, gslc_tsElemRef* pElemRef, gslc_tsColor colBg);
|
||||
|
||||
// ============================================================================
|
||||
|
||||
// ------------------------------------------------------------------------
|
||||
// Read-only element macros
|
||||
// ------------------------------------------------------------------------
|
||||
|
||||
// Macro initializers for Read-Only Elements in Flash/PROGMEM
|
||||
//
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif // __cplusplus
|
||||
#endif // _GUISLICE_EX_XGLOWBALL_H_
|
||||
|
Some files were not shown because too many files have changed in this diff Show more
Reference in a new issue