mirror of
https://git.mirrors.martin98.com/https://github.com/luc-github/ESP3D.git
synced 2025-07-31 00:12:01 +08:00
Add base for USB FS (work in progress do not use)
This commit is contained in:
parent
eaba22990a
commit
ce24d85e8d
@ -105,6 +105,11 @@
|
||||
#define ESP_SDCARD_NOT_PRESENT 1
|
||||
#define ESP_SDCARD_BUSY 2
|
||||
|
||||
//USB state
|
||||
#define ESP_USB_IDLE 0
|
||||
#define ESP_USB_NOT_PRESENT 1
|
||||
#define ESP_USB_BUSY 2
|
||||
|
||||
//Notifications
|
||||
#define ESP_NO_NOTIFICATION 0
|
||||
#define ESP_PUSHOVER_NOTIFICATION 1
|
||||
|
@ -26,7 +26,6 @@
|
||||
#include <esp_ota_ops.h>
|
||||
#endif //ARDUINO_ARCH_ESP32
|
||||
|
||||
#define ESP_MAX_OPENHANDLE 4
|
||||
File tFile_handle[ESP_MAX_OPENHANDLE];
|
||||
|
||||
bool ESP_FileSystem::_started = false;
|
||||
|
@ -24,7 +24,6 @@
|
||||
#include "../../core/genLinkedList.h"
|
||||
#include <time.h>
|
||||
|
||||
#define ESP_MAX_SD_OPENHANDLE 4
|
||||
#if ((SD_DEVICE == ESP_SD_NATIVE) || (SD_DEVICE == ESP_SDFAT)) && defined (ARDUINO_ARCH_ESP8266)
|
||||
#define FS_NO_GLOBALS
|
||||
#define NO_GLOBAL_SD
|
||||
|
209
esp3d/src/modules/filesystem/esp_usb.cpp
Normal file
209
esp3d/src/modules/filesystem/esp_usb.cpp
Normal file
@ -0,0 +1,209 @@
|
||||
/*
|
||||
esp_usb.cpp - ESP3D USB support class
|
||||
|
||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with This code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#include "../../include/esp3d_config.h"
|
||||
#ifdef USB_DEVICE
|
||||
#include "esp_usb.h"
|
||||
#include "../../core/genLinkedList.h"
|
||||
#include <time.h>
|
||||
|
||||
//File tUSBFile_handle[ESP_MAX_SD_OPENHANDLE];
|
||||
|
||||
|
||||
bool ESP_USB::_started = false;
|
||||
uint8_t ESP_USB::_state = ESP_USBCARD_NOT_PRESENT;
|
||||
uint8_t ESP_USB::_spi_speed_divider = 1;
|
||||
bool ESP_USB::_sizechanged = true;
|
||||
uint8_t ESP_USB::setState(uint8_t flag)
|
||||
{
|
||||
_state = flag;
|
||||
return _state;
|
||||
}
|
||||
|
||||
bool ESP_USB::accessSD()
|
||||
{
|
||||
bool res = false;
|
||||
#if SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
//need to send the current state to avoid
|
||||
res = (digitalRead(ESP_FLAG_SHARED_SD_PIN) == ESP_FLAG_SHARED_SD_VALUE);
|
||||
if (!res) {
|
||||
digitalWrite(ESP_FLAG_SHARED_SD_PIN, ESP_FLAG_SHARED_SD_VALUE);
|
||||
}
|
||||
#endif //SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
return res;
|
||||
}
|
||||
void ESP_USB::releaseSD()
|
||||
{
|
||||
#if SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
digitalWrite(ESP_FLAG_SHARED_SD_PIN, !ESP_FLAG_SHARED_SD_VALUE);
|
||||
#endif //SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
}
|
||||
|
||||
|
||||
void ESP_USB::handle()
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
//helper to format size to readable string
|
||||
String & ESP_USB::formatBytes (uint64_t bytes)
|
||||
{
|
||||
static String res;
|
||||
if (bytes < 1024) {
|
||||
res = String ((uint16_t)bytes) + " B";
|
||||
} else if (bytes < (1024 * 1024) ) {
|
||||
res = String ((float)(bytes / 1024.0),2) + " KB";
|
||||
} else if (bytes < (1024 * 1024 * 1024) ) {
|
||||
res = String ((float)(bytes / 1024.0 / 1024.0),2) + " MB";
|
||||
} else {
|
||||
res = String ((float)(bytes / 1024.0 / 1024.0 / 1024.0),2) + " GB";
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
ESP_USBFile::ESP_USBFile(const char * name, const char * filename, bool isdir, size_t size)
|
||||
{
|
||||
_isdir = isdir;
|
||||
_dirlist = "";
|
||||
_index = -1;
|
||||
_filename = filename;
|
||||
_name = name;
|
||||
_lastwrite = 0;
|
||||
_iswritemode = false;
|
||||
_size = size;
|
||||
}
|
||||
|
||||
ESP_USBFile::~ESP_USBFile()
|
||||
{
|
||||
//log_esp3d("Destructor %s index %d",(_isdir)?"Dir":"File", _index);
|
||||
}
|
||||
|
||||
ESP_USBFile::operator bool() const
|
||||
{
|
||||
if ((_index != -1) || (_filename.length() > 0)) {
|
||||
//log_esp3d("Bool yes %d %d",_index, _filename.length());
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool ESP_USBFile::isOpen()
|
||||
{
|
||||
return !(_index == -1);
|
||||
}
|
||||
|
||||
const char* ESP_USBFile::name() const
|
||||
{
|
||||
return _name.c_str();
|
||||
}
|
||||
|
||||
const char* ESP_USBFile::filename() const
|
||||
{
|
||||
return _filename.c_str();
|
||||
}
|
||||
|
||||
bool ESP_USBFile::isDirectory()
|
||||
{
|
||||
return _isdir;
|
||||
}
|
||||
|
||||
size_t ESP_USBFile::size()
|
||||
{
|
||||
return _size;
|
||||
}
|
||||
|
||||
time_t ESP_USBFile::getLastWrite()
|
||||
{
|
||||
return _lastwrite;
|
||||
}
|
||||
|
||||
int ESP_USBFile::available()
|
||||
{
|
||||
if (_index == -1 || _isdir) {
|
||||
return 0;
|
||||
}
|
||||
return tSDFile_handle[_index].available();
|
||||
}
|
||||
|
||||
size_t ESP_USBFile::write(uint8_t i)
|
||||
{
|
||||
if ((_index == -1) || _isdir) {
|
||||
return 0;
|
||||
}
|
||||
return tSDFile_handle[_index].write (i);
|
||||
}
|
||||
|
||||
size_t ESP_USBFile::write(const uint8_t *buf, size_t size)
|
||||
{
|
||||
if ((_index == -1) || _isdir) {
|
||||
return 0;
|
||||
}
|
||||
return tSDFile_handle[_index].write (buf, size);
|
||||
}
|
||||
|
||||
int ESP_USBFile::read()
|
||||
{
|
||||
if ((_index == -1) || _isdir) {
|
||||
return -1;
|
||||
}
|
||||
return tSDFile_handle[_index].read();
|
||||
}
|
||||
|
||||
size_t ESP_USBFile::read(uint8_t* buf, size_t size)
|
||||
{
|
||||
if ((_index == -1) || _isdir) {
|
||||
return -1;
|
||||
}
|
||||
return tSDFile_handle[_index].read(buf, size);
|
||||
}
|
||||
|
||||
void ESP_USBFile::flush()
|
||||
{
|
||||
if ((_index == -1) || _isdir) {
|
||||
return;
|
||||
}
|
||||
tSDFile_handle[_index].flush();
|
||||
}
|
||||
|
||||
ESP_USBFile& ESP_USBFile::operator=(const ESP_USBFile & other)
|
||||
{
|
||||
//log_esp3d("Copy %s", other._filename.c_str());
|
||||
_isdir = other._isdir;
|
||||
_index = other._index;
|
||||
_filename = other._filename;
|
||||
_name = other._name;
|
||||
_size = other._size;
|
||||
_iswritemode = other._iswritemode;
|
||||
_dirlist = other._dirlist;
|
||||
_lastwrite = other._lastwrite;
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool ESP_USB::setSPISpeedDivider(uint8_t speeddivider)
|
||||
{
|
||||
if (speeddivider > 0) {
|
||||
_spi_speed_divider = speeddivider;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
#endif //SD_DEVICE
|
103
esp3d/src/modules/filesystem/esp_usb.h
Normal file
103
esp3d/src/modules/filesystem/esp_usb.h
Normal file
@ -0,0 +1,103 @@
|
||||
/*
|
||||
esp_usb.h - ESP3D USB support class
|
||||
|
||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with This code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
#ifndef _ESP_USB_H
|
||||
#define _ESP_USB_H
|
||||
#include "../../include/esp3d_config.h"
|
||||
#include "../../core/esp3doutput.h"
|
||||
#include <time.h>
|
||||
|
||||
#define ESP_USB_FS_HEADER "/USB"
|
||||
|
||||
#define ESP_MAX_USB_OPENHANDLE 4
|
||||
|
||||
class ESP_USBFile
|
||||
{
|
||||
public:
|
||||
ESP_USBFile(void * handle = nullptr, bool isdir =false, bool iswritemode = false, const char * path = nullptr);
|
||||
ESP_USBFile(const char * name, const char * filename, bool isdir = true, size_t size =0);
|
||||
~ESP_USBFile();
|
||||
operator bool() const;
|
||||
bool isDirectory();
|
||||
bool seek(uint32_t pos, uint8_t mode = ESP_SEEK_SET);
|
||||
const char* name() const;
|
||||
const char* shortname() const;
|
||||
const char* filename() const;
|
||||
void close();
|
||||
bool isOpen();
|
||||
ESP_USBFile & operator=(const ESP_USBFile & other);
|
||||
size_t size();
|
||||
time_t getLastWrite();
|
||||
int available();
|
||||
size_t write(uint8_t i);
|
||||
size_t write(const uint8_t *buf, size_t size);
|
||||
int read();
|
||||
size_t read(uint8_t* buf, size_t size);
|
||||
void flush();
|
||||
ESP_USBFile openNextFile();
|
||||
private:
|
||||
String _dirlist;
|
||||
bool _isdir;
|
||||
bool _iswritemode;
|
||||
int8_t _index;
|
||||
String _filename;
|
||||
String _name;
|
||||
size_t _size;
|
||||
time_t _lastwrite;
|
||||
};
|
||||
|
||||
class ESP_SD
|
||||
{
|
||||
public:
|
||||
static String & formatBytes (uint64_t bytes);
|
||||
static bool begin();
|
||||
static bool accessSD();
|
||||
static void releaseSD();
|
||||
static void handle();
|
||||
static void end();
|
||||
static uint8_t getState(bool refresh);
|
||||
static uint8_t setState(uint8_t state);
|
||||
static uint64_t totalBytes();
|
||||
static uint64_t usedBytes();
|
||||
static uint64_t freeBytes();
|
||||
static uint maxPathLength();
|
||||
static const char * FilesystemName();
|
||||
static bool format(ESP3DOutput * output = nullptr);
|
||||
static ESP_USBFile open(const char* path, uint8_t mode = ESP_FILE_READ);
|
||||
static bool exists(const char* path);
|
||||
static bool remove(const char *path);
|
||||
static bool mkdir(const char *path);
|
||||
static bool rmdir(const char *path);
|
||||
static bool rename(const char *oldpath, const char *newpath);
|
||||
static void closeAll();
|
||||
static uint8_t getSPISpeedDivider()
|
||||
{
|
||||
return _spi_speed_divider;
|
||||
}
|
||||
static bool setSPISpeedDivider(uint8_t speeddivider);
|
||||
private:
|
||||
static bool _started;
|
||||
static uint8_t _state;
|
||||
static uint8_t _spi_speed_divider;
|
||||
static bool _sizechanged;
|
||||
};
|
||||
|
||||
|
||||
#endif //_ESP_USB_H
|
@ -235,14 +235,14 @@ ESP_File::ESP_File(void* handle, bool isdir, bool iswritemode, const char * path
|
||||
set = true;
|
||||
} else {
|
||||
log_esp3d("File %d busy", i);
|
||||
log_esp3d(tFile_handle[i].name());
|
||||
log_esp3d("%s", String(tFile_handle[i].name()).c_str());
|
||||
}
|
||||
}
|
||||
if(!set) {
|
||||
log_esp3d("No handle available");
|
||||
#if defined(ESP_DEBUG_FEATURE)
|
||||
for (uint8_t i=0; (i < ESP_MAX_OPENHANDLE) ; i++) {
|
||||
log_esp3d(tFile_handle[i].name());
|
||||
log_esp3d("%s",String(tFile_handle[i].name()).c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
843
esp3d/src/modules/filesystem/usb/usb_ch376s.cpp
Normal file
843
esp3d/src/modules/filesystem/usb/usb_ch376s.cpp
Normal file
@ -0,0 +1,843 @@
|
||||
/*
|
||||
usb_ch376s.cpp - ESP3D usb support class
|
||||
|
||||
Copyright (c) 2014 Luc Lebosse. All rights reserved.
|
||||
|
||||
This code is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU Lesser General Public
|
||||
License as published by the Free Software Foundation; either
|
||||
version 2.1 of the License, or (at your option) any later version.
|
||||
|
||||
This code is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
Lesser General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU Lesser General Public
|
||||
License along with This code; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
#include "../../../include/esp3d_config.h"
|
||||
#if defined (ARDUINO_ARCH_ESP32) && defined(USB_DEVICE)
|
||||
#if (USB_DEVICE == ESP_CH376S)
|
||||
#include "../esp_sd.h"
|
||||
#include "../../../core/genLinkedList.h"
|
||||
#include "../../../core/settings_esp3d.h"
|
||||
#include <Ch376msc.h>
|
||||
extern File tSDFile_handle[ESP_MAX_SD_OPENHANDLE];
|
||||
|
||||
//Max Freq Working
|
||||
SdFat SD;
|
||||
|
||||
void dateTime (uint16_t* date, uint16_t* dtime)
|
||||
{
|
||||
struct tm tmstruct;
|
||||
time_t now;
|
||||
time (&now);
|
||||
localtime_r (&now, &tmstruct);
|
||||
*date = FAT_DATE ( (tmstruct.tm_year) + 1900, ( tmstruct.tm_mon) + 1, tmstruct.tm_mday);
|
||||
*dtime = FAT_TIME (tmstruct.tm_hour, tmstruct.tm_min, tmstruct.tm_sec);
|
||||
}
|
||||
|
||||
time_t getDateTimeFile(File & filehandle)
|
||||
{
|
||||
static time_t dt = 0;
|
||||
struct tm timefile;
|
||||
dir_t d;
|
||||
if(filehandle) {
|
||||
if (filehandle.dirEntry(&d)) {
|
||||
timefile.tm_year = FAT_YEAR(d.lastWriteDate) - 1900;
|
||||
timefile.tm_mon = FAT_MONTH(d.lastWriteDate) - 1;
|
||||
timefile.tm_mday = FAT_DAY(d.lastWriteDate);
|
||||
timefile.tm_hour = FAT_HOUR(d.lastWriteTime);
|
||||
timefile.tm_min = FAT_MINUTE(d.lastWriteTime);
|
||||
timefile.tm_sec = FAT_SECOND(d.lastWriteTime);
|
||||
timefile.tm_isdst = -1;
|
||||
dt = mktime(&timefile);
|
||||
if (dt == -1) {
|
||||
log_esp3d("mktime failed");
|
||||
}
|
||||
} else {
|
||||
log_esp3d("stat file failed");
|
||||
}
|
||||
} else {
|
||||
log_esp3d("check stat file failed");
|
||||
}
|
||||
return dt;
|
||||
}
|
||||
|
||||
|
||||
uint8_t ESP_SD::getState(bool refresh)
|
||||
{
|
||||
#if defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1
|
||||
//no need to go further if SD detect is not correct
|
||||
if (!((digitalRead (ESP_SD_DETECT_PIN) == ESP_SD_DETECT_VALUE) ? true : false)) {
|
||||
_state = ESP_SDCARD_NOT_PRESENT;
|
||||
return _state;
|
||||
}
|
||||
#endif //ESP_SD_DETECT_PIN
|
||||
//if busy doing something return state
|
||||
if (!((_state == ESP_SDCARD_NOT_PRESENT) || _state == ESP_SDCARD_IDLE)) {
|
||||
return _state;
|
||||
}
|
||||
if (!refresh) {
|
||||
return _state; //to avoid refresh=true + busy to reset SD and waste time
|
||||
}
|
||||
//SD is idle or not detected, let see if still the case
|
||||
_state = ESP_SDCARD_NOT_PRESENT;
|
||||
bool isactive = accessSD();
|
||||
log_esp3d("Spi : CS: %d, Miso: %d, Mosi: %d, SCK: %d",ESP_SD_CS_PIN!=-1?ESP_SD_CS_PIN:SS, ESP_SD_MISO_PIN!=-1?ESP_SD_MISO_PIN:MISO, ESP_SD_MOSI_PIN!=-1?ESP_SD_MOSI_PIN:MOSI, ESP_SD_SCK_PIN!=-1?ESP_SD_SCK_PIN:SCK);
|
||||
//refresh content if card was removed
|
||||
if (SD.begin((ESP_SD_CS_PIN == -1)?SS:ESP_SD_CS_PIN, SD_SCK_MHZ(FREQMZ/_spi_speed_divider))) {
|
||||
if (SD.card()->cardSize() > 0 ) {
|
||||
_state = ESP_SDCARD_IDLE;
|
||||
}
|
||||
}
|
||||
if (!isactive) {
|
||||
releaseSD();
|
||||
}
|
||||
return _state;
|
||||
}
|
||||
|
||||
bool ESP_SD::begin()
|
||||
{
|
||||
#if (ESP_SD_CS_PIN != -1) || (ESP_SD_MISO_PIN != -1) || (ESP_SD_MOSI_PIN != -1) || (ESP_SD_SCK_PIN != -1)
|
||||
SPI.begin(ESP_SD_SCK_PIN, ESP_SD_MISO_PIN, ESP_SD_MOSI_PIN, ESP_SD_CS_PIN);
|
||||
#endif
|
||||
_started = true;
|
||||
_state = ESP_SDCARD_NOT_PRESENT;
|
||||
_spi_speed_divider = Settings_ESP3D::read_byte(ESP_SD_SPEED_DIV);
|
||||
//sanity check
|
||||
if (_spi_speed_divider <= 0) {
|
||||
_spi_speed_divider = 1;
|
||||
}
|
||||
#ifdef SD_TIMESTAMP_FEATURE
|
||||
//set callback to get time on files on SD
|
||||
SdFile::dateTimeCallback (dateTime);
|
||||
#endif //SD_TIMESTAMP_FEATURE
|
||||
//Setup pins
|
||||
#if defined(ESP_SD_DETECT_PIN) && ESP_SD_DETECT_PIN != -1
|
||||
pinMode (ESP_SD_DETECT_PIN, INPUT);
|
||||
#endif //ESP_SD_DETECT_PIN
|
||||
#if SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
#if defined(ESP_FLAG_SHARED_SD_PIN) && ESP_FLAG_SHARED_SD_PIN != -1
|
||||
pinMode (ESP_FLAG_SHARED_SD_PIN, OUTPUT);
|
||||
digitalWrite(ESP_FLAG_SHARED_SD_PIN, !ESP_FLAG_SHARED_SD_VALUE);
|
||||
#endif //ESP_FLAG_SHARED_SD_PIN
|
||||
#endif //SD_DEVICE_CONNECTION == ESP_SHARED_SD
|
||||
return _started;
|
||||
}
|
||||
|
||||
void ESP_SD::end()
|
||||
{
|
||||
_state = ESP_SDCARD_NOT_PRESENT;
|
||||
_started = false;
|
||||
}
|
||||
|
||||
uint64_t ESP_SD::totalBytes()
|
||||
{
|
||||
uint64_t volTotal = SD.vol()->clusterCount();
|
||||
uint8_t blocks = SD.vol()->blocksPerCluster();
|
||||
return volTotal * blocks * 512;
|
||||
}
|
||||
|
||||
uint64_t ESP_SD::usedBytes()
|
||||
{
|
||||
if(freeBytes() >totalBytes() ) {
|
||||
_sizechanged = true;
|
||||
}
|
||||
return totalBytes() - freeBytes();
|
||||
}
|
||||
|
||||
uint ESP_SD::maxPathLength()
|
||||
{
|
||||
return 255;
|
||||
}
|
||||
|
||||
uint64_t ESP_SD::freeBytes()
|
||||
{
|
||||
static uint64_t volFree;
|
||||
if (_sizechanged) {
|
||||
volFree = SD.vol()->freeClusterCount();
|
||||
_sizechanged = false;
|
||||
}
|
||||
uint8_t blocks = SD.vol()->blocksPerCluster();
|
||||
return volFree * blocks * 512;
|
||||
}
|
||||
|
||||
bool ESP_SD::rename(const char *oldpath, const char *newpath)
|
||||
{
|
||||
return SD.rename(oldpath,newpath);
|
||||
}
|
||||
|
||||
// strings needed in file system structures
|
||||
#define noName "NO NAME "
|
||||
#define fat16str "FAT16 "
|
||||
#define fat32str "FAT32 "
|
||||
// constants for file system structure
|
||||
#define BU16 128
|
||||
#define BU32 8192
|
||||
#define ERASE_SIZE 262144L
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// write cached block to the card
|
||||
uint8_t writeCache(uint32_t lbn, Sd2Card & card, cache_t & cache)
|
||||
{
|
||||
return card.writeBlock(lbn, cache.data);
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// initialize appropriate sizes for SD capacity
|
||||
bool initSizes(uint32_t cardCapacityMB, uint8_t & sectorsPerCluster, uint8_t & numberOfHeads, uint8_t & sectorsPerTrack)
|
||||
{
|
||||
if (cardCapacityMB <= 6) {
|
||||
return false;
|
||||
} 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;
|
||||
}
|
||||
|
||||
// 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;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// zero cache and optionally set the sector signature
|
||||
void clearCache(uint8_t addSig, cache_t & cache)
|
||||
{
|
||||
memset(&cache, 0, sizeof(cache));
|
||||
if (addSig) {
|
||||
cache.mbr.mbrSig0 = BOOTSIG0;
|
||||
cache.mbr.mbrSig1 = BOOTSIG1;
|
||||
}
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// zero FAT and root dir area on SD
|
||||
bool clearFatDir(uint32_t bgn, uint32_t count, Sd2Card & card, cache_t & cache, ESP3DOutput * output)
|
||||
{
|
||||
clearCache(false, cache);
|
||||
if (!card.writeStart(bgn, count)) {
|
||||
return false;
|
||||
}
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
if ((i & 0XFF) == 0) {
|
||||
if (output) {
|
||||
output->print(".");
|
||||
}
|
||||
}
|
||||
if (!card.writeData(cache.data)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (!card.writeStop()) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// return cylinder number for a logical block number
|
||||
uint16_t lbnToCylinder(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||
{
|
||||
return lbn / (numberOfHeads * sectorsPerTrack);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return head number for a logical block number
|
||||
uint8_t lbnToHead(uint32_t lbn, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||
{
|
||||
return (lbn % (numberOfHeads * sectorsPerTrack)) / sectorsPerTrack;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
// return sector number for a logical block number
|
||||
uint8_t lbnToSector(uint32_t lbn, uint8_t sectorsPerTrack)
|
||||
{
|
||||
return (lbn % sectorsPerTrack) + 1;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// format and write the Master Boot Record
|
||||
bool writeMbr(Sd2Card & card, cache_t & cache, uint8_t partType, uint32_t relSector, uint32_t partSize, uint8_t numberOfHeads, uint8_t sectorsPerTrack)
|
||||
{
|
||||
clearCache(true, cache);
|
||||
part_t* p = cache.mbr.part;
|
||||
p->boot = 0;
|
||||
uint16_t c = lbnToCylinder(relSector, numberOfHeads, sectorsPerTrack);
|
||||
if (c > 1023) {
|
||||
return false;
|
||||
}
|
||||
p->beginCylinderHigh = c >> 8;
|
||||
p->beginCylinderLow = c & 0XFF;
|
||||
p->beginHead = lbnToHead(relSector, numberOfHeads, sectorsPerTrack);
|
||||
p->beginSector = lbnToSector(relSector, sectorsPerTrack);
|
||||
p->type = partType;
|
||||
uint32_t endLbn = relSector + partSize - 1;
|
||||
c = lbnToCylinder(endLbn,numberOfHeads, sectorsPerTrack);
|
||||
if (c <= 1023) {
|
||||
p->endCylinderHigh = c >> 8;
|
||||
p->endCylinderLow = c & 0XFF;
|
||||
p->endHead = lbnToHead(endLbn, numberOfHeads, sectorsPerTrack);
|
||||
p->endSector = lbnToSector(endLbn, sectorsPerTrack);
|
||||
} 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, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
// generate serial number from card size and micros since boot
|
||||
uint32_t volSerialNumber(uint32_t cardSizeBlocks)
|
||||
{
|
||||
return (cardSizeBlocks << 8) + micros();
|
||||
}
|
||||
|
||||
// format the SD as FAT16
|
||||
bool makeFat16(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||
{
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
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
|
||||
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||
return false;
|
||||
}
|
||||
clearCache(true, cache);
|
||||
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(cardSizeBlocks);
|
||||
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||
memcpy(pb->fileSystemType, fat16str, sizeof(pb->fileSystemType));
|
||||
// write partition boot sector
|
||||
if (!writeCache(relSector, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
// clear FAT and root directory
|
||||
clearFatDir(fatStart, dataStart - fatStart, card, cache, output);
|
||||
clearCache(false, cache);
|
||||
cache.fat16[0] = 0XFFF8;
|
||||
cache.fat16[1] = 0XFFFF;
|
||||
// write first block of FAT and backup for reserved clusters
|
||||
if (!writeCache(fatStart, card, cache)
|
||||
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
// format the SD as FAT32
|
||||
bool makeFat32(uint32_t & dataStart, Sd2Card & card, cache_t & cache, uint8_t numberOfHeads, uint8_t sectorsPerTrack, uint32_t cardSizeBlocks, uint8_t sectorsPerCluster, uint32_t &relSector, uint32_t partSize, uint8_t & partType, uint32_t &fatSize, uint32_t &fatStart, uint16_t reservedSectors, ESP3DOutput * output)
|
||||
{
|
||||
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) {
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
if (!writeMbr(card, cache, partType, relSector, partSize, numberOfHeads, sectorsPerTrack)) {
|
||||
return false;
|
||||
}
|
||||
clearCache(true, cache);
|
||||
|
||||
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(cardSizeBlocks);
|
||||
memcpy(pb->volumeLabel, noName, sizeof(pb->volumeLabel));
|
||||
memcpy(pb->fileSystemType, fat32str, sizeof(pb->fileSystemType));
|
||||
// write partition boot sector and backup
|
||||
if (!writeCache(relSector, card, cache)
|
||||
|| !writeCache(relSector + 6, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
clearCache(true, cache);
|
||||
// write extra boot area and backup
|
||||
if (!writeCache(relSector + 2, card, cache)
|
||||
|| !writeCache(relSector + 8, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
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, card, cache)
|
||||
|| !writeCache(relSector + 7, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
clearFatDir(fatStart, 2 * fatSize + sectorsPerCluster, card, cache, output);
|
||||
clearCache(false, cache);
|
||||
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, card, cache)
|
||||
|| !writeCache(fatStart + fatSize, card, cache)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool eraseCard(Sd2Card & card, cache_t & cache, uint32_t cardSizeBlocks, ESP3DOutput * output)
|
||||
{
|
||||
uint32_t firstBlock = 0;
|
||||
uint32_t lastBlock = 0;
|
||||
//uint16_t n = 0;
|
||||
if (output) {
|
||||
output->printMSG("Erasing ", false);
|
||||
}
|
||||
do {
|
||||
lastBlock = firstBlock + ERASE_SIZE - 1;
|
||||
if (lastBlock >= cardSizeBlocks) {
|
||||
lastBlock = cardSizeBlocks - 1;
|
||||
}
|
||||
if (!card.erase(firstBlock, lastBlock)) {
|
||||
return false;
|
||||
}
|
||||
if (output) {
|
||||
output->print(".");
|
||||
}
|
||||
firstBlock += ERASE_SIZE;
|
||||
} while (firstBlock < cardSizeBlocks);
|
||||
|
||||
if (!card.readBlock(0, cache.data)) {
|
||||
return false;
|
||||
}
|
||||
if (output) {
|
||||
output->printLN("");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool formatCard(uint32_t & dataStart, Sd2Card & card,
|
||||
cache_t & cache, uint8_t numberOfHeads,
|
||||
uint8_t sectorsPerTrack, uint32_t cardSizeBlocks,
|
||||
uint8_t sectorsPerCluster, uint32_t &relSector,
|
||||
uint32_t partSize, uint8_t & partType,
|
||||
uint32_t &fatSize, uint32_t &fatStart,
|
||||
uint32_t cardCapacityMB, uint16_t reservedSectors, ESP3DOutput * output)
|
||||
{
|
||||
initSizes(cardCapacityMB, sectorsPerCluster, numberOfHeads, sectorsPerTrack);
|
||||
if (card.type() != SD_CARD_TYPE_SDHC) {
|
||||
if (output) {
|
||||
output->printMSG("Formating FAT16 ");
|
||||
}
|
||||
if(!makeFat16(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (output) {
|
||||
output->printMSG("Formating FAT32 ", false);
|
||||
}
|
||||
if(!makeFat32(dataStart, card, cache, numberOfHeads, sectorsPerTrack, cardSizeBlocks, sectorsPerCluster, relSector, partSize, partType, fatSize, fatStart, reservedSectors, output)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (output) {
|
||||
output->printLN("");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ESP_SD::format(ESP3DOutput * output)
|
||||
{
|
||||
if (ESP_SD::getState(true) == ESP_SDCARD_IDLE) {
|
||||
Sd2Card card;
|
||||
uint32_t cardSizeBlocks;
|
||||
uint32_t cardCapacityMB;
|
||||
// cache for SD block
|
||||
cache_t cache;
|
||||
|
||||
// MBR information
|
||||
uint8_t partType = 0;
|
||||
uint32_t relSector = 0;
|
||||
uint32_t partSize = 0;
|
||||
|
||||
// Fake disk geometry
|
||||
uint8_t numberOfHeads = 0;
|
||||
uint8_t sectorsPerTrack = 0;
|
||||
|
||||
// FAT parameters
|
||||
uint16_t reservedSectors = 0;
|
||||
uint8_t sectorsPerCluster = 0;
|
||||
uint32_t fatStart = 0;
|
||||
uint32_t fatSize = 0;
|
||||
uint32_t dataStart = 0;
|
||||
if (!card.begin((ESP_SD_CS_PIN == -1)?SS:ESP_SD_CS_PIN, SD_SCK_MHZ(FREQMZ/_spi_speed_divider))) {
|
||||
return false;
|
||||
}
|
||||
cardSizeBlocks = card.cardSize();
|
||||
if (cardSizeBlocks == 0) {
|
||||
return false;
|
||||
}
|
||||
cardCapacityMB = (cardSizeBlocks + 2047)/2048;
|
||||
if (output) {
|
||||
String s = "Capacity detected :" + String((1.048576*cardCapacityMB)/1024) + "GB";
|
||||
output->printMSG(s.c_str());
|
||||
}
|
||||
if (!eraseCard(card, cache, cardSizeBlocks, output)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!formatCard(dataStart, card, cache, numberOfHeads,
|
||||
sectorsPerTrack, cardSizeBlocks,
|
||||
sectorsPerCluster, relSector, partSize, partType,
|
||||
fatSize, fatStart, cardCapacityMB, reservedSectors,output)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
ESP_SDFile ESP_SD::open(const char* path, uint8_t mode)
|
||||
{
|
||||
//do some check
|
||||
if(((strcmp(path,"/") == 0) && ((mode == ESP_FILE_WRITE) || (mode == ESP_FILE_APPEND))) || (strlen(path) == 0)) {
|
||||
_sizechanged = true;
|
||||
return ESP_SDFile();
|
||||
}
|
||||
// path must start by '/'
|
||||
if (path[0] != '/') {
|
||||
return ESP_SDFile();
|
||||
}
|
||||
if (mode != ESP_FILE_READ) {
|
||||
//check container exists
|
||||
String p = path;
|
||||
p.remove(p.lastIndexOf('/') +1);
|
||||
if (!exists(p.c_str())) {
|
||||
log_esp3d("Error opening: %s", path);
|
||||
return ESP_SDFile();
|
||||
}
|
||||
}
|
||||
File tmp = SD.open(path, (mode == ESP_FILE_READ)?FILE_READ:(mode == ESP_FILE_WRITE)?FILE_WRITE:FILE_WRITE);
|
||||
ESP_SDFile esptmp(&tmp, tmp.isDir(),(mode == ESP_FILE_READ)?false:true, path);
|
||||
return esptmp;
|
||||
}
|
||||
|
||||
bool ESP_SD::exists(const char* path)
|
||||
{
|
||||
bool res = false;
|
||||
//root should always be there if started
|
||||
if (strcmp(path, "/") == 0) {
|
||||
return _started;
|
||||
}
|
||||
res = SD.exists(path);
|
||||
if (!res) {
|
||||
ESP_SDFile root = ESP_SD::open(path, ESP_FILE_READ);
|
||||
if (root) {
|
||||
res = root.isDirectory();
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ESP_SD::remove(const char *path)
|
||||
{
|
||||
_sizechanged = true;
|
||||
return SD.remove(path);
|
||||
}
|
||||
|
||||
bool ESP_SD::mkdir(const char *path)
|
||||
{
|
||||
return SD.mkdir(path);
|
||||
}
|
||||
|
||||
bool ESP_SD::rmdir(const char *path)
|
||||
{
|
||||
if (!exists(path)) {
|
||||
return false;
|
||||
}
|
||||
bool res = true;
|
||||
GenLinkedList<String > pathlist;
|
||||
String p = path;
|
||||
pathlist.push(p);
|
||||
while (pathlist.count() > 0) {
|
||||
File dir = SD.open(pathlist.getLast().c_str());
|
||||
dir.rewindDirectory();
|
||||
File f = dir.openNextFile();
|
||||
bool candelete = true;
|
||||
while (f) {
|
||||
if (f.isDir()) {
|
||||
candelete = false;
|
||||
String newdir;
|
||||
char tmp[255];
|
||||
f.getName(tmp,254);
|
||||
newdir = tmp;
|
||||
pathlist.push(newdir);
|
||||
f.close();
|
||||
f = File();
|
||||
} else {
|
||||
char tmp[255];
|
||||
f.getName(tmp,254);
|
||||
_sizechanged = true;
|
||||
SD.remove(tmp);
|
||||
f.close();
|
||||
f = dir.openNextFile();
|
||||
}
|
||||
}
|
||||
if (candelete) {
|
||||
if (pathlist.getLast() !="/") {
|
||||
res = SD.rmdir(pathlist.getLast().c_str());
|
||||
}
|
||||
pathlist.pop();
|
||||
}
|
||||
dir.close();
|
||||
}
|
||||
p = String();
|
||||
log_esp3d("count %d", pathlist.count());
|
||||
return res;
|
||||
}
|
||||
|
||||
void ESP_SD::closeAll()
|
||||
{
|
||||
for (uint8_t i = 0; i < ESP_MAX_SD_OPENHANDLE; i++) {
|
||||
tSDFile_handle[i].close();
|
||||
tSDFile_handle[i] = File();
|
||||
}
|
||||
}
|
||||
|
||||
bool ESP_SDFile::seek(uint32_t pos, uint8_t mode)
|
||||
{
|
||||
if (mode == SeekEnd) {
|
||||
return tSDFile_handle[_index].seek(-pos); //based on SDFS comment
|
||||
}
|
||||
return tSDFile_handle[_index].seek(pos);
|
||||
}
|
||||
|
||||
ESP_SDFile::ESP_SDFile(void* handle, bool isdir, bool iswritemode, const char * path)
|
||||
{
|
||||
_isdir = isdir;
|
||||
_dirlist = "";
|
||||
_index = -1;
|
||||
_filename = "";
|
||||
_name = "";
|
||||
_lastwrite = 0 ;
|
||||
_iswritemode = iswritemode;
|
||||
_size = 0;
|
||||
if (!handle) {
|
||||
return ;
|
||||
}
|
||||
bool set =false;
|
||||
for (uint8_t i=0; (i < ESP_MAX_SD_OPENHANDLE) && !set; i++) {
|
||||
if (!tSDFile_handle[i]) {
|
||||
tSDFile_handle[i] = *((File*)handle);
|
||||
//filename
|
||||
char tmp[255];
|
||||
tSDFile_handle[i].getName(tmp,254);
|
||||
_filename = path;
|
||||
//name
|
||||
_name = tmp;
|
||||
if (_name.endsWith("/")) {
|
||||
_name.remove( _name.length() - 1,1);
|
||||
_isdir = true;
|
||||
}
|
||||
if (_name[0] == '/') {
|
||||
_name.remove( 0, 1);
|
||||
}
|
||||
int pos = _name.lastIndexOf('/');
|
||||
if (pos != -1) {
|
||||
_name.remove( 0, pos+1);
|
||||
}
|
||||
if (_name.length() == 0) {
|
||||
_name = "/";
|
||||
}
|
||||
//size
|
||||
_size = tSDFile_handle[i].size();
|
||||
//time
|
||||
if (!_isdir && !iswritemode) {
|
||||
_lastwrite = getDateTimeFile(tSDFile_handle[i]);
|
||||
|
||||
} else {
|
||||
//no need date time for directory
|
||||
_lastwrite = 0;
|
||||
}
|
||||
_index = i;
|
||||
//log_esp3d("Opening File at index %d",_index);
|
||||
set = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
//todo need also to add short filename
|
||||
const char* ESP_SDFile::shortname() const
|
||||
{
|
||||
static char sname[13];
|
||||
File ftmp = SD.open(_filename.c_str());
|
||||
if (ftmp) {
|
||||
ftmp.getSFN(sname);
|
||||
ftmp.close();
|
||||
return sname;
|
||||
} else {
|
||||
return _name.c_str();
|
||||
}
|
||||
}
|
||||
|
||||
void ESP_SDFile::close()
|
||||
{
|
||||
if (_index != -1) {
|
||||
//log_esp3d("Closing File at index %d", _index);
|
||||
tSDFile_handle[_index].close();
|
||||
//reopen if mode = write
|
||||
//udate size + date
|
||||
if (_iswritemode && !_isdir) {
|
||||
File ftmp = SD.open(_filename.c_str());
|
||||
if (ftmp) {
|
||||
_size = ftmp.size();
|
||||
_lastwrite = getDateTimeFile(ftmp);
|
||||
ftmp.close();
|
||||
}
|
||||
}
|
||||
tSDFile_handle[_index] = File();
|
||||
//log_esp3d("Closing File at index %d",_index);
|
||||
_index = -1;
|
||||
}
|
||||
}
|
||||
|
||||
ESP_SDFile ESP_SDFile::openNextFile()
|
||||
{
|
||||
if ((_index == -1) || !_isdir) {
|
||||
log_esp3d("openNextFile failed");
|
||||
return ESP_SDFile();
|
||||
}
|
||||
File tmp = tSDFile_handle[_index].openNextFile();
|
||||
if (tmp) {
|
||||
char tmps[255];
|
||||
tmp.getName(tmps,254);
|
||||
log_esp3d("tmp name :%s %s", tmps, (tmp.isDir())?"isDir":"isFile");
|
||||
String s = _filename ;
|
||||
if (s!="/") {
|
||||
s+="/";
|
||||
}
|
||||
s += tmps;
|
||||
ESP_SDFile esptmp(&tmp, tmp.isDir(),false, s.c_str());
|
||||
esptmp.close();
|
||||
return esptmp;
|
||||
}
|
||||
return ESP_SDFile();
|
||||
}
|
||||
|
||||
const char * ESP_SD::FilesystemName()
|
||||
{
|
||||
return "SDFat";
|
||||
}
|
||||
|
||||
#endif //SD_DEVICE == ESP_SD_NATIVE
|
||||
#endif //ARCH_ESP32 && SD_DEVICE
|
28
libraries/Ch376msc-1.4.4/.gitignore
vendored
Normal file
28
libraries/Ch376msc-1.4.4/.gitignore
vendored
Normal file
@ -0,0 +1,28 @@
|
||||
# Compiled Object files
|
||||
*.slo
|
||||
*.lo
|
||||
*.o
|
||||
*.obj
|
||||
|
||||
# Precompiled Headers
|
||||
*.gch
|
||||
*.pch
|
||||
|
||||
# Compiled Dynamic libraries
|
||||
*.so
|
||||
*.dylib
|
||||
*.dll
|
||||
|
||||
# Fortran module files
|
||||
*.mod
|
||||
|
||||
# Compiled Static libraries
|
||||
*.lai
|
||||
*.la
|
||||
*.a
|
||||
*.lib
|
||||
|
||||
# Executables
|
||||
*.exe
|
||||
*.out
|
||||
*.app
|
20
libraries/Ch376msc-1.4.4/LICENSE
Normal file
20
libraries/Ch376msc-1.4.4/LICENSE
Normal file
@ -0,0 +1,20 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 György Kovács
|
||||
|
||||
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.
|
332
libraries/Ch376msc-1.4.4/README.md
Normal file
332
libraries/Ch376msc-1.4.4/README.md
Normal file
@ -0,0 +1,332 @@
|
||||
# Arduino library for CH376 / CH375 file manager control chip
|
||||
Supports read/write files to USB flash drive or SD card (CH375 only support USB flash drive).
|
||||
>Why use this chip if there is already a library to handle the SD card and it is easier to just hook up the SD card(with resistors or SD card module) to Arduino?
|
||||
>The SD library is widely used and is reliable, the only problem is the Arduino does't have to much memory and with the SD lib the MCU has to cope with the FAT file system,
|
||||
>and we're just talking about SD card management, the USB storage drive handling is a more complicated and memory consuming procedure and you need a USB-HOST chip.
|
||||
>The CH376 chip easily can write and read files even if they are on SD card or on Usb thumb-drive(CH375 only support USB thumb-drive). The chip supports FAT12, FAT16 and FAT32 file systems, meaning the chip does the hard work,
|
||||
>the MCU does not have to deal with the FAT file system, it only sends instructions to the chip on the communication bus you like (SPI, UART (HW serial, SW serial)), and the magic happens in the chip.
|
||||
>The chip can do more, e.g to handle HID devices(usb keyboard, mouse, joystick ...) but this feature is not yet used in the library, maybe in the future.
|
||||
|
||||
Click [here](https://github.com/djuseeq/Ch376msc#test) to see the difference between libraries about memory usage.
|
||||
|
||||
|
||||
## Getting Started
|
||||
|
||||
Configure the jumpers on the module depending on which communication protocol you are using(see [API reference](https://github.com/djuseeq/Ch376msc#api-reference))
|
||||

|
||||
|
||||
### PCB modding for SD card
|
||||
> If you planning to use the chip for SD card also and you have a pcb like on the photo above, then some soldering skill is required.
|
||||
> First of all with a DMM check the pins of the chip(26,25,23 and 7) are they floating or connected to GND/VCC.
|
||||
> On mine pcb the chip pin 23 (SD_CS) is connected to ground, like you can [see here](extras/schematic.png),
|
||||
> pins or the chip have incorrect marking(looks like CH375 which one doesn't support SD card) . [Link](https://www.mpja.com/download/31813MPSch.pdf) for the module's schematic diagram.
|
||||
> I used soldering iron and tweezer to lift up the pin from the pcb(be careful, you can easily break the chip's leg).
|
||||
> Follow [this schema](extras/modPcb.png) to make the proper connection between the chip and SD card socket.
|
||||
> I used a [SD card adapter](extras/sdAdapter.jpg) and for sake of stability, use the capacitors+1R resistor on Vcc line.
|
||||
> The SD card operate from 3.3V and this board already have a 3.3V voltage regulator so that is fine.
|
||||
> Here are some photos from the ugly modding ;) [Photo1](extras/board1.jpg) [Photo2](extras/board2.jpg).
|
||||
|
||||
## Versions
|
||||
v1.4.4 Sep 29, 2020
|
||||
- error handling improvement
|
||||
- new function, getChipVer()
|
||||
- bug fix, issue #34 Variable Naming conflicts with core ESP32 Variables
|
||||
|
||||
v1.4.3 Feb 06, 2020
|
||||
- bug fix issue #22 unknown partition
|
||||
- new functions as requested in #21 , #23
|
||||
- reorganizing the library
|
||||
- added function-like macros to easy configure the SPI clock rate(see in examples/lcd_menu)
|
||||
|
||||
v1.4.2 Jan 07, 2020
|
||||
> - support SD card manage(API ref. - setSource(),if the SD card socket is not available on the module,
|
||||
> then modification on the module is required, please read [Pcb modding for sd card](https://github.com/djuseeq/Ch376msc#pcb-modding-for-sd-card) section)
|
||||
> - a new example of using an SD card
|
||||
> - the checkDrive function name was misleading, renamed to checkIntMessage
|
||||
> - improvements, bug fixes
|
||||
> - unnecessary examples removed
|
||||
|
||||
v1.4.1 Dec 22, 2019
|
||||
- supports more architectures(see Tested boards table below) - issue #11
|
||||
- constructor update (BUSY pin is not longer used)
|
||||
- improved logic to the mount/unmount flash drive
|
||||
- directory support ( cd(); function )
|
||||
- use advanced file listing with (*) wildcard character(API reference, listDir() function)
|
||||
|
||||
v1.4.0 Sep 26, 2019
|
||||
- new functions
|
||||
- getTotalSectors() - returns a unsigned long number, total sectors on the drive
|
||||
- getFreeSectors() - returns a unsigned long number, free sectors on the drive
|
||||
- getFileSystem() - returns a byte number, 0x01-FAT12, 0x02-FAT16, 0x03-FAT32
|
||||
- updated example files with a new functions
|
||||
- new example file, searching for the oldest/newest file on the flash drive
|
||||
|
||||
v1.3.1 Sep 20, 2019
|
||||
- rearrange the folder structure to be 1.5 library format compatible
|
||||
|
||||
v1.3 Sep 17, 2019
|
||||
- bug fix for moveCursor issue #3 , minor changes
|
||||
|
||||
v1.2.1 Apr 24, 2019
|
||||
- In use of SPI, CS pin on the module must to be pulled to VCC otherwise communication can be instable on a higher clock rate
|
||||
- bug fix for timing issue on a higher clock rate (TSC)
|
||||
|
||||
v1.2 Apr 20, 2019
|
||||
- extended with SPI communication
|
||||
|
||||
v1.1 Feb 25, 2019
|
||||
- initial version with UART communication
|
||||
|
||||
## API Reference
|
||||
```C++
|
||||
//The default SPI communication speed is reduced to 125 kHz because of stability if long cables or breadboard is used.
|
||||
// to change the SPI Clock rate, during instantiation use e.g. SPI_SCK_KHZ(500) - to use 500kHz
|
||||
// or e.g. SPI_SCK_MHZ(8) - to use 8MHz (see in examples/lcd_menu)
|
||||
//CONSTRUCTORS
|
||||
//UART
|
||||
//For hardware serial leave the communication settings on the module at default speed (9600bps)
|
||||
Ch376msc(HardwareSerial, speed);//Select the serial port to which the module is connected and the desired speed(9600, 19200, 57600, 115200)
|
||||
|
||||
//For software serial select the desired communication speed on the module(look on the picture above)
|
||||
Ch376msc(SoftwareSerial);
|
||||
|
||||
//SPI
|
||||
//If no other device is connected to the SPI port it`s possible to save one MCU pin
|
||||
Ch376msc(spiSelect, *optional SPI CLK rate*);// ! Don`t use this if the SPI port is shared with other devices
|
||||
|
||||
//If the SPI port is shared with other devices, use this constructor and one extra MCU pin need to be sacrificed for the INT pin
|
||||
Ch376msc(spiSelect, interruptPin, *optional SPI CLK rate*);
|
||||
////////////////////
|
||||
|
||||
// Must be initialized before any other command are called from this class.
|
||||
init();
|
||||
|
||||
// call frequently to get any interrupt message of the module(attach/detach drive)
|
||||
checkIntMessage(); //return TRUE if an interrupt request has been received, FALSE if not.
|
||||
|
||||
// can call before any file operation
|
||||
driveReady(); //returns FALSE if no drive is present or TRUE if drive is attached and ready.
|
||||
|
||||
// check the communication between MCU and the CH376
|
||||
pingDevice(); //returns FALSE if there is a communication failure, TRUE if communication is ok
|
||||
|
||||
// 8.3 filename, also called a short filename is accepted
|
||||
setFileName(filename);//8 char long name + 3 char long extension
|
||||
|
||||
// open file before any file operation. Use first setFileName() function
|
||||
openFile();
|
||||
|
||||
// always call this after finishing with file operations otherwise data loss or file corruption may occur
|
||||
closeFile();
|
||||
|
||||
// repeatedly call this function to read data to buffer until the return value is TRUE
|
||||
readFile(buffer, length);// buffer - char array, buffer size
|
||||
|
||||
// Read text until reach the terminator character, rest is same as readFile
|
||||
readFileUntil(terminator, buffer, length);//returns boolean true if the given buffer
|
||||
// is full and not reached the terminator character
|
||||
|
||||
//Same as readFile except the buffer type is byte(uint8) array and not added terminating 0 char
|
||||
readRaw(buffer, length);// buffer - byte array, buffer size
|
||||
|
||||
//Read, extract numbers of txt file, read until reach EOF (see getEOF())
|
||||
readLong(terminator);//returns long value,terminator char is optional, default char is '\n'
|
||||
readULong(terminator);//returns unsigned long value,terminator char is optional, default char is '\n'
|
||||
readDouble(terminator);//returns double value,terminator char is optional, default char is '\n'
|
||||
|
||||
//Write, construct string of number and write on the storage(byte, int, u int, long, u long, double)
|
||||
writeNum(number);// write the given number
|
||||
writeNumln(number);// write the given number in new line
|
||||
|
||||
//Write one character on the storage
|
||||
writeChar(char);// e.g. new line character '\n' or comma ',' to
|
||||
|
||||
// repeatedly call this function to write data to the drive until there is no more data for write or the return value is FALSE
|
||||
writeFile(buffer, length);// buffer - char array, string size in the buffer
|
||||
|
||||
// switch between source drive's, 0 = USB(default), 1 = SD card
|
||||
// !!Before calling this function and activate the SD card please do the required modification
|
||||
// on the pcb, please read **PCB modding for SD card** section otherwise you can damage the CH376 chip.
|
||||
setSource(srcDrive);// 0 or 1
|
||||
|
||||
setYear(year); // 1980 - 2099
|
||||
setMonth(month);// 1 - 12
|
||||
setDay(day);// 1 - 31
|
||||
setHour(hour);// 0 - 23
|
||||
setMinute(minute);// 0 - 59
|
||||
setSecond(second);// 0 - 59 saved with 2 second resolution (0, 2, 4 ... 58)
|
||||
|
||||
// when new file is created the defult file creation date/time is (2004-1-1 0.0.0),
|
||||
// it is possible to change date/time with this function, use first set functions above to set the file attributes
|
||||
saveFileAttrb();
|
||||
|
||||
// move the file cursor to specified position
|
||||
moveCursor(position);// 00000000h - FFFFFFFFh
|
||||
|
||||
// delete the specified file, use first setFileName() function
|
||||
deleteFile();
|
||||
|
||||
// repeatedly call this function with getFileName until the return value is TRUE to get the file names from the current directory
|
||||
// limited possibility to use with wildcard character e.g. listDir("AB*") will list files with names starting with AB
|
||||
// listDir("*AB") will not work, wildcard char+string must to be less than 8 character long
|
||||
// if no argument is passed while calling listDir(), all files will be printed from the current directory
|
||||
listDir();// returns FALSE if no more file is in the current directory
|
||||
|
||||
// reset file process state machine to default
|
||||
// useful e.g. to make LCD menu with file's list without using large buffer to store the file names
|
||||
resetFileList();
|
||||
|
||||
//dirPath = e.g. "/DIR1/DIR2/DIR3" , "/" - root dir
|
||||
//CreateDir = 0(open directories if they not exist, don`t create them) or 1(create directories if they do not exist and open them)
|
||||
//if working in subfolders, before file operations ALWAYS call this function with the full directory path
|
||||
//limited to 3 subfolders depth (see /src/Ch376msc.h file. MAXDIRDEPTH) and 8 character long directory names
|
||||
cd(dirPath,CreateDir);// returns byte value,see example .ino
|
||||
|
||||
getFreeSectors();// returns unsigned long value
|
||||
getTotalSectors();// returns unsigned long value
|
||||
getFileSize();// returns unsigned long value (byte)
|
||||
getSource();// returns boolean value, false USB, true SD card
|
||||
|
||||
getYear();// returns int value
|
||||
getMonth();// returns int value
|
||||
getDay();// returns int value
|
||||
getHour();// returns int value
|
||||
getMinute();// returns int value
|
||||
getSecond();// returns int value
|
||||
|
||||
// get the last error code (see datasheet and/or CommDef.h)
|
||||
getError();// returns byte value
|
||||
|
||||
getFileSystem();// returns byte value, 01h-FAT12, 02h-FAT16, 03h-FAT32
|
||||
getFileName();// returns the file name in a 11+1 character long string value
|
||||
getFileSizeStr();// returns file size in a formatted 9+1 character long string value
|
||||
getFileAttrb();// returns byte value, see /src/CommDef.h , (File attributes)
|
||||
getCursorPos();// returns unsigned long value
|
||||
getEOF();// returns boolean value, true EOF is reached
|
||||
getChipVer();// returns byte value, returns the CH chip firmware version number
|
||||
```
|
||||
## Tested boards
|
||||
|Board(arch) | SPI | HW Serial | SW Serial|
|
||||
|:---|:---:|:---:|:---:|
|
||||
|Arduino (AVR)|OK|OK|OK|
|
||||
|DUE (SAM)|OK(with INT pin)|OK|NO|
|
||||
|ZERO (SAMD)|OK|?|NO|
|
||||
|*STM32 cores|OK|!NO|NO|
|
||||
|**STM32duino|OK|OK|NO|
|
||||
|***ESP8266|OK(with INT pin)|NO|OK|
|
||||
|ESP32 ([ref](https://github.com/djuseeq/Ch376msc/issues/18))|OK|?|?|
|
||||
|
||||
Be careful when choosing SoftSerial because it has its own limitations. See [issues#15](https://github.com/djuseeq/Ch376msc/issues/15)
|
||||
|
||||
> `*` Tested on NUCLEO F446RE(no signal at all on UART ports)
|
||||
|
||||
> `**` Tested on Generic STM32F103C alias Blue pill with STM32duino bootloader
|
||||
|
||||
> `***` Tested on NodeMCU,(i'm not familiar with ESP MCUs) it looks they have default enabled WDT so i have to call
|
||||
> `yield()` periodically during file operations, otherwise ESP will restart with a ugly message.
|
||||
> Working SPI configuration (for me)is MISO-12(D6), MOSI-13(D7), SCK-14(D5), CS-4(D2), INT-5(D1)
|
||||
|
||||
### Test
|
||||
|
||||
I compared the two libraries with the same instructions, create file, write some text in it and read back the created file and send it to serial (SPI used)
|
||||
Used Arduino IDE 1.8.10 on x64 linux, ArduinoUno board choosed
|
||||
|
||||
Sketch from SD library(SparkFun 1.2.4) ReadWrite example:
|
||||
|
||||
Program space used: 10704 bytes 33% ,
|
||||
|
||||
SRAM used: 882 bytes 43%
|
||||
|
||||
```C++
|
||||
#include <SPI.h>
|
||||
#include <SD.h>
|
||||
|
||||
File myFile;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
SD.begin(4);
|
||||
myFile = SD.open("TEST.TXT", FILE_WRITE);
|
||||
if (myFile) {
|
||||
myFile.println("testing 1, 2, 3.");
|
||||
myFile.close();
|
||||
}
|
||||
myFile = SD.open("TEST.TXT");
|
||||
while (myFile.available()) {
|
||||
Serial.write(myFile.read());
|
||||
}
|
||||
myFile.close();
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
|
||||
```
|
||||
|
||||
Second sketch is with Ch376msc library(1.4.2)
|
||||
|
||||
1. if i put in comments the setSorce function and use the default USB storage
|
||||
|
||||
Program space used: 6760 bytes 20% ,
|
||||
SRAM used: 315 bytes 15%
|
||||
2. with setSorce function choosed USB storage
|
||||
|
||||
Program space used: 6810 bytes 21% ,
|
||||
SRAM used: 315 bytes 15%
|
||||
3. with setSorce function choosed SD storage
|
||||
|
||||
Program space used: 6824 bytes 21% ,
|
||||
SRAM used: 315 bytes 15%
|
||||
|
||||
```C++
|
||||
#include <Ch376msc.h>
|
||||
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
char adat[]={"testing 1, 2, 3."};
|
||||
boolean readMore = true;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(9600);
|
||||
flashDrive.init();
|
||||
flashDrive.setSource(0);//0 - USB, 1 - SD
|
||||
flashDrive.setFileName("TEST.TXT");
|
||||
flashDrive.openFile();
|
||||
flashDrive.writeFile(adat, strlen(adat));
|
||||
flashDrive.closeFile();
|
||||
flashDrive.setFileName("TEST.TXT");
|
||||
flashDrive.openFile();
|
||||
while(readMore){
|
||||
readMore = flashDrive.readFile(adat, sizeof(adat));
|
||||
Serial.print(adat);
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
}
|
||||
|
||||
void loop() {}
|
||||
```
|
||||
|
||||
### Acknowledgments
|
||||
|
||||
Thanks for the idea to [Scott C](https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html)
|
||||
|
||||
## License
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2019 György Kovács
|
||||
|
||||
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.
|
||||
|
@ -0,0 +1,254 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 28 Mar 2019 |
|
||||
* Description: Basic usage of CH376 with hardware serial |
|
||||
* Thanks for the idea to Scott C , https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
//..............................................................................................................................
|
||||
// Leave the default jumper settings for the baud rate (9600) on the CH376, the library will set it up the chosen speed(HW serial only)
|
||||
Ch376msc flashDrive(Serial1, 115200); // Ch376 object with hardware Serial1 on arduino mega baudrate: 9600, 19200, 57600, 115200
|
||||
//..............................................................................................................................
|
||||
// buffer for reading
|
||||
char adatBuffer[255];// max length 255 = 254 char + 1 NULL character
|
||||
//..............................................................................................................................
|
||||
// strings for writing to file
|
||||
char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n";
|
||||
char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n";
|
||||
//..............................................................................................................................
|
||||
unsigned long totSect = 0;
|
||||
unsigned long freeSect = 0;
|
||||
byte percentg = 0;
|
||||
byte tmpCommand; //used to store data coming from serial port
|
||||
boolean readMore;
|
||||
static char helpString[]= {"h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n"
|
||||
"5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"
|
||||
"\n9:Open/Create folder(s)/subfolder(s)"};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
printInfo(helpString);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(flashDrive.checkIntMessage()){
|
||||
if(flashDrive.getDeviceStatus()){
|
||||
Serial.println(F("Flash drive attached!"));
|
||||
} else {
|
||||
Serial.println(F("Flash drive detached!"));
|
||||
}
|
||||
}
|
||||
if(Serial.available()){
|
||||
tmpCommand = Serial.read(); //read incoming bytes from the serial monitor
|
||||
if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.driveReady()){ // if the data is ASCII 1 - 9 and no flash drive are attached
|
||||
printInfo("Attach flash drive first!");
|
||||
tmpCommand = 10; // change the command byte
|
||||
}
|
||||
switch (tmpCommand) {
|
||||
|
||||
case 49: //1
|
||||
printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
flashDrive.writeFile(adat, strlen(adat)); //string, string length
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 50: //2
|
||||
printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file.
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
if(flashDrive.openFile() == ANSW_USB_INT_SUCCESS){ //open the file
|
||||
flashDrive.moveCursor(CURSOREND); //if the file exist, move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file
|
||||
//flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file
|
||||
}
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
if(flashDrive.getFreeSectors()){ //check the free space on the drive
|
||||
flashDrive.writeFile(adat2, strlen(adat2)); //string, string length
|
||||
} else {
|
||||
printInfo("Disk full");
|
||||
}
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 51: //3
|
||||
printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
readMore = true;
|
||||
//read data from flash drive until we reach EOF
|
||||
while(readMore){ // our temporary buffer where we read data from flash drive and the size of that buffer
|
||||
readMore = flashDrive.readFile(adatBuffer, sizeof(adatBuffer));
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 52: //4
|
||||
printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
//print informations about the file
|
||||
Serial.println(flashDrive.getFileName());
|
||||
Serial.print(flashDrive.getYear());
|
||||
Serial.print("y\t");
|
||||
Serial.print(flashDrive.getMonth());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getDay());
|
||||
Serial.print("d\t");
|
||||
Serial.print(flashDrive.getHour());
|
||||
Serial.print("h\t");
|
||||
Serial.print(flashDrive.getMinute());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getSecond());
|
||||
Serial.println('s');
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 53: //5
|
||||
printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
flashDrive.setYear(2019);
|
||||
flashDrive.setMonth(12);
|
||||
flashDrive.setDay(19);
|
||||
flashDrive.setHour(03);
|
||||
flashDrive.setMinute(38);
|
||||
flashDrive.setSecond(42);
|
||||
|
||||
flashDrive.saveFileAttrb(); //save the changed data
|
||||
flashDrive.closeFile(); //and yes again, close the file after when you don`t use it
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 54: //6
|
||||
printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.deleteFile(); //delete file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 55: //7
|
||||
printInfo("COMMAND7: List directory"); //Print all file names in the current directory
|
||||
while(flashDrive.listDir()){ // reading next file
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){//directory
|
||||
Serial.print('/');
|
||||
Serial.println(flashDrive.getFileName()); // get the actual file name
|
||||
} else {
|
||||
Serial.print(flashDrive.getFileName()); // get the actual file name
|
||||
Serial.print(" : ");
|
||||
Serial.print(flashDrive.getFileSize()); // get the actual file size in bytes
|
||||
Serial.print(" >>>\t");
|
||||
Serial.println(flashDrive.getFileSizeStr()); // get the actual file size in formatted string
|
||||
}
|
||||
}
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 56: //8
|
||||
totSect = flashDrive.getTotalSectors(); // get the total sector number
|
||||
freeSect = flashDrive.getFreeSectors(); // get the available sector number
|
||||
percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100)
|
||||
Serial.print("Disk size in bytes: ");
|
||||
/*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) )
|
||||
e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */
|
||||
if(totSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(totSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print("\tFree space in bytes: ");
|
||||
if(freeSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(freeSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print(F("\tDisk usage :"));
|
||||
Serial.print(percentg);
|
||||
Serial.print(F("%"));
|
||||
switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32
|
||||
case 1:
|
||||
Serial.println(F("\tFAT12 partition"));
|
||||
break;
|
||||
case 2:
|
||||
Serial.println(F("\tFAT16 partition"));
|
||||
break;
|
||||
case 3:
|
||||
Serial.println(F("\tFAT32 partition"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("\tNo valid partition"));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 57: //9
|
||||
switch(flashDrive.cd("/DIR1/DIR2/DIR3",1)){
|
||||
case CH376_ERR_LONGFILENAME: //0x01
|
||||
Serial.println(F("Directory name is too long"));
|
||||
break;
|
||||
|
||||
case ANSW_USB_INT_SUCCESS: //0x14
|
||||
Serial.println(F("Directory created successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_OPEN_DIR: //0x41
|
||||
Serial.println(F("Directory opened successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_MISS_FILE: //0x42
|
||||
Serial.println(F("Directory doesn't exist"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_FOUND_NAME: //0x43
|
||||
Serial.println(F("File exist with the given name"));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 104: //h
|
||||
printInfo(helpString);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
|
||||
}//endif serial available
|
||||
|
||||
}//end loop
|
||||
|
||||
//Print information
|
||||
void printInfo(const char info[]){
|
||||
|
||||
int infoLength = strlen(info);
|
||||
if(infoLength > 40){
|
||||
infoLength = 40;
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(info);
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
}
|
@ -0,0 +1,260 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 22 Apr 2019 |
|
||||
* Description: Basic usage of CH376 with SPI port |
|
||||
* Thanks for the idea to Scott C , https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
//..............................................................................................................................
|
||||
// Connect to SPI port: MISO, MOSI, SCK
|
||||
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
|
||||
//If the SPI port shared with other devices e.g SD card, display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
//..............................................................................................................................
|
||||
// buffer for reading
|
||||
char adatBuffer[255];// max length 255 = 254 char + 1 NULL character
|
||||
//..............................................................................................................................
|
||||
// strings for writing to file
|
||||
char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n";
|
||||
char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n";
|
||||
//..............................................................................................................................
|
||||
unsigned long totSect = 0;
|
||||
unsigned long freeSect = 0;
|
||||
byte percentg = 0;
|
||||
byte tmpCommand; //used to store data coming from serial port
|
||||
boolean readMore;
|
||||
static char helpString[]= {"h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n"
|
||||
"5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"
|
||||
"\n9:Open/Create folder(s)/subfolder(s)"};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
printInfo(helpString);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(flashDrive.checkIntMessage()){
|
||||
if(flashDrive.getDeviceStatus()){
|
||||
Serial.println(F("Flash drive attached!"));
|
||||
} else {
|
||||
Serial.println(F("Flash drive detached!"));
|
||||
}
|
||||
}
|
||||
if(Serial.available()){
|
||||
tmpCommand = Serial.read(); //read incoming bytes from the serial monitor
|
||||
if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.driveReady()){ // if the data is ASCII 1 - 9 and no flash drive are attached
|
||||
printInfo("Attach flash drive first!");
|
||||
tmpCommand = 10; // change the command byte
|
||||
}
|
||||
switch (tmpCommand) {
|
||||
|
||||
case 49: //1
|
||||
printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
flashDrive.writeFile(adat, strlen(adat)); //string, string length
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 50: //2
|
||||
printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file.
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
if(flashDrive.openFile() == ANSW_USB_INT_SUCCESS){ //open the file
|
||||
flashDrive.moveCursor(CURSOREND); //if the file exist, move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file
|
||||
//flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file
|
||||
}
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
if(flashDrive.getFreeSectors()){ //check the free space on the drive
|
||||
flashDrive.writeFile(adat2, strlen(adat2)); //string, string length
|
||||
} else {
|
||||
printInfo("Disk full");
|
||||
}
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 51: //3
|
||||
printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
readMore = true;
|
||||
//read data from flash drive until we reach EOF
|
||||
while(readMore){ // our temporary buffer where we read data from flash drive and the size of that buffer
|
||||
readMore = flashDrive.readFile(adatBuffer, sizeof(adatBuffer));
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 52: //4
|
||||
printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
//print informations about the file
|
||||
Serial.println(flashDrive.getFileName());
|
||||
Serial.print(flashDrive.getYear());
|
||||
Serial.print("y\t");
|
||||
Serial.print(flashDrive.getMonth());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getDay());
|
||||
Serial.print("d\t");
|
||||
Serial.print(flashDrive.getHour());
|
||||
Serial.print("h\t");
|
||||
Serial.print(flashDrive.getMinute());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getSecond());
|
||||
Serial.println('s');
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 53: //5
|
||||
printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
flashDrive.setYear(2019);
|
||||
flashDrive.setMonth(12);
|
||||
flashDrive.setDay(19);
|
||||
flashDrive.setHour(03);
|
||||
flashDrive.setMinute(38);
|
||||
flashDrive.setSecond(42);
|
||||
|
||||
flashDrive.saveFileAttrb(); //save the changed data
|
||||
flashDrive.closeFile(); //and yes again, close the file after when you don`t use it
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 54: //6
|
||||
printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.deleteFile(); //delete file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 55: //7
|
||||
printInfo("COMMAND7: List directory"); //Print all file names in the current directory
|
||||
while(flashDrive.listDir()){ // reading next file
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){//directory
|
||||
Serial.print('/');
|
||||
Serial.println(flashDrive.getFileName()); // get the actual file name
|
||||
} else {
|
||||
Serial.print(flashDrive.getFileName()); // get the actual file name
|
||||
Serial.print(" : ");
|
||||
Serial.print(flashDrive.getFileSize()); // get the actual file size in bytes
|
||||
Serial.print(" >>>\t");
|
||||
Serial.println(flashDrive.getFileSizeStr()); // get the actual file size in formatted string
|
||||
}
|
||||
}
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 56: //8
|
||||
totSect = flashDrive.getTotalSectors(); // get the total sector number
|
||||
freeSect = flashDrive.getFreeSectors(); // get the available sector number
|
||||
percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100)
|
||||
Serial.print("Disk size in bytes: ");
|
||||
/*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) )
|
||||
e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */
|
||||
if(totSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(totSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print("\tFree space in bytes: ");
|
||||
if(freeSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(freeSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print(F("\tDisk usage :"));
|
||||
Serial.print(percentg);
|
||||
Serial.print(F("%"));
|
||||
switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32
|
||||
case 1:
|
||||
Serial.println(F("\tFAT12 partition"));
|
||||
break;
|
||||
case 2:
|
||||
Serial.println(F("\tFAT16 partition"));
|
||||
break;
|
||||
case 3:
|
||||
Serial.println(F("\tFAT32 partition"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("\tNo valid partition"));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 57: //9
|
||||
switch(flashDrive.cd("/DIR1/DIR2/DIR3",1)){
|
||||
case CH376_ERR_LONGFILENAME: //0x01
|
||||
Serial.println(F("Directory name is too long"));
|
||||
break;
|
||||
|
||||
case ANSW_USB_INT_SUCCESS: //0x14
|
||||
Serial.println(F("Directory created successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_OPEN_DIR: //0x41
|
||||
Serial.println(F("Directory opened successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_MISS_FILE: //0x42
|
||||
Serial.println(F("Directory doesn't exist"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_FOUND_NAME: //0x43
|
||||
Serial.println(F("File exist with the given name"));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 104: //h
|
||||
printInfo(helpString);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
|
||||
}//endif serial available
|
||||
|
||||
}//end loop
|
||||
|
||||
//Print information
|
||||
void printInfo(const char info[]){
|
||||
|
||||
int infoLength = strlen(info);
|
||||
if(infoLength > 40){
|
||||
infoLength = 40;
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(info);
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
}
|
@ -0,0 +1,268 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 07 Jan 2020 |
|
||||
* Description: Basic usage of CH376 with SPI port, switching between SD card and USB drive |
|
||||
* ! WARNING ! Before you upload and test this sketch, read https://github.com/djuseeq/Ch376msc#getting-started, |
|
||||
* PCB modding for SD card section, otherwise you can DAMAGE the CH376 module with switching source to SD card |
|
||||
* if your module is ready to SD card mode, remove from comment the SD card enable line in beginning of loop fnc.|
|
||||
* Thanks for the idea to Scott C , https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
//..............................................................................................................................
|
||||
// Connect to SPI port: MISO, MOSI, SCK
|
||||
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
|
||||
//If the SPI port shared with other devices e.g TFT display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
//..............................................................................................................................
|
||||
// buffer for reading
|
||||
char adatBuffer[255];// max length 255 = 254 char + 1 NULL character
|
||||
//..............................................................................................................................
|
||||
// strings for writing to file
|
||||
char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n";
|
||||
char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n";
|
||||
//..............................................................................................................................
|
||||
unsigned long totSect = 0;
|
||||
unsigned long freeSect = 0;
|
||||
byte percentg = 0;
|
||||
byte tmpCommand; //used to store data coming from serial port
|
||||
boolean readMore;
|
||||
static char helpString[]= {"h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n"
|
||||
"5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"
|
||||
"\n9:Open/Create folder(s)/subfolder(s)\nu:Source USB\ns:Source SD card"};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
printInfo(helpString);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(flashDrive.checkIntMessage()){
|
||||
if(flashDrive.getDeviceStatus()){
|
||||
Serial.println(F("Flash drive attached!"));
|
||||
} else {
|
||||
Serial.println(F("Flash drive detached!"));
|
||||
}
|
||||
}
|
||||
if(Serial.available()){
|
||||
tmpCommand = Serial.read(); //read incoming bytes from the serial monitor
|
||||
//Enable SD card below this comment, remove it from comment only after reading warning message in sketch header
|
||||
//and delete(put in comment) the Serial print message line
|
||||
//if(tmpCommand == 115) flashDrive.setSource(1);//SD card enable
|
||||
if(tmpCommand == 115) Serial.println(F("Please first read the Warning message in sketch header before you change source to SD card!"));
|
||||
if(tmpCommand == 117) flashDrive.setSource(0);//USB enable
|
||||
if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.driveReady()){ // if the data is ASCII 1 - 9 and no flash drive are attached
|
||||
printInfo("Attach flash/SD drive first!");
|
||||
tmpCommand = 10; // change the command byte
|
||||
}
|
||||
switch (tmpCommand) {
|
||||
|
||||
case 49: //1
|
||||
printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
flashDrive.writeFile(adat, strlen(adat)); //string, string length
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 50: //2
|
||||
printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file.
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
if(flashDrive.openFile() == ANSW_USB_INT_SUCCESS){ //open the file
|
||||
flashDrive.moveCursor(CURSOREND); //if the file exist, move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file
|
||||
//flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file
|
||||
}
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
if(flashDrive.getFreeSectors()){ //check the free space on the drive
|
||||
flashDrive.writeFile(adat2, strlen(adat2)); //string, string length
|
||||
} else {
|
||||
printInfo("Disk full");
|
||||
}
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 51: //3
|
||||
printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
readMore = true;
|
||||
//read data from flash drive until we reach EOF
|
||||
while(readMore){ // our temporary buffer where we read data from flash drive and the size of that buffer
|
||||
readMore = flashDrive.readFile(adatBuffer, sizeof(adatBuffer));
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 52: //4
|
||||
printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
//print informations about the file
|
||||
Serial.println(flashDrive.getFileName());
|
||||
Serial.print(flashDrive.getYear());
|
||||
Serial.print("y\t");
|
||||
Serial.print(flashDrive.getMonth());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getDay());
|
||||
Serial.print("d\t");
|
||||
Serial.print(flashDrive.getHour());
|
||||
Serial.print("h\t");
|
||||
Serial.print(flashDrive.getMinute());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getSecond());
|
||||
Serial.println('s');
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 53: //5
|
||||
printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
flashDrive.setYear(2019);
|
||||
flashDrive.setMonth(12);
|
||||
flashDrive.setDay(19);
|
||||
flashDrive.setHour(03);
|
||||
flashDrive.setMinute(38);
|
||||
flashDrive.setSecond(42);
|
||||
|
||||
flashDrive.saveFileAttrb(); //save the changed data
|
||||
flashDrive.closeFile(); //and yes again, close the file after when you don`t use it
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 54: //6
|
||||
printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.deleteFile(); //delete file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 55: //7
|
||||
printInfo("COMMAND7: List directory"); //Print all file names in the current directory
|
||||
while(flashDrive.listDir()){ // reading next file
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){//directory
|
||||
Serial.print('/');
|
||||
Serial.println(flashDrive.getFileName()); // get the actual file name
|
||||
} else {
|
||||
Serial.print(flashDrive.getFileName()); // get the actual file name
|
||||
Serial.print(" : ");
|
||||
Serial.print(flashDrive.getFileSize()); // get the actual file size in bytes
|
||||
Serial.print(" >>>\t");
|
||||
Serial.println(flashDrive.getFileSizeStr()); // get the actual file size in formatted string
|
||||
}
|
||||
}
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 56: //8
|
||||
totSect = flashDrive.getTotalSectors(); // get the total sector number
|
||||
freeSect = flashDrive.getFreeSectors(); // get the available sector number
|
||||
percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100)
|
||||
Serial.print("Disk size in bytes: ");
|
||||
/*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) )
|
||||
e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */
|
||||
if(totSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(totSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print("\tFree space in bytes: ");
|
||||
if(freeSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(freeSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print(F("\tDisk usage :"));
|
||||
Serial.print(percentg);
|
||||
Serial.print(F("%"));
|
||||
switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32
|
||||
case 1:
|
||||
Serial.println(F("\tFAT12 partition"));
|
||||
break;
|
||||
case 2:
|
||||
Serial.println(F("\tFAT16 partition"));
|
||||
break;
|
||||
case 3:
|
||||
Serial.println(F("\tFAT32 partition"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("\tNo valid partition"));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 57: //9
|
||||
switch(flashDrive.cd("/DIR1/DIR2/DIR3",1)){
|
||||
case CH376_ERR_LONGFILENAME: //0x01
|
||||
Serial.println(F("Directory name is too long"));
|
||||
break;
|
||||
|
||||
case ANSW_USB_INT_SUCCESS: //0x14
|
||||
Serial.println(F("Directory created successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_OPEN_DIR: //0x41
|
||||
Serial.println(F("Directory opened successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_MISS_FILE: //0x42
|
||||
Serial.println(F("Directory doesn't exist"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_FOUND_NAME: //0x43
|
||||
Serial.println(F("File exist with the given name"));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 104: //h
|
||||
printInfo(helpString);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
|
||||
}//endif serial available
|
||||
|
||||
}//end loop
|
||||
|
||||
//Print information
|
||||
void printInfo(const char info[]){
|
||||
|
||||
int infoLength = strlen(info);
|
||||
if(infoLength > 40){
|
||||
infoLength = 40;
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(info);
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
}
|
@ -0,0 +1,257 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 28 Mar 2019 |
|
||||
* Description: Basic usage of CH376 with software serial |
|
||||
* Thanks for the idea to Scott C , https://arduinobasics.blogspot.com/2015/05/ch376s-usb-readwrite-module.html |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
#include <SoftwareSerial.h>
|
||||
|
||||
//Important! First create a soft serial object, after create a Ch376 object
|
||||
SoftwareSerial mySerial(7, 6); // RX, TX pins on arduino
|
||||
//..............................................................................................................................
|
||||
Ch376msc flashDrive(mySerial); // Ch376 object with software serial
|
||||
//..............................................................................................................................
|
||||
// buffer for reading
|
||||
char adatBuffer[255];// max length 255 = 254 char + 1 NULL character
|
||||
//..............................................................................................................................
|
||||
// strings for writing to file
|
||||
char adat[]="Vivamus nec nisl molestie, blandit diam vel, varius mi. Fusce luctus cursus sapien in vulputate.\n";
|
||||
char adat2[] = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Duis efficitur ac est eu pharetra. \n";
|
||||
//..............................................................................................................................
|
||||
unsigned long totSect = 0;
|
||||
unsigned long freeSect = 0;
|
||||
byte percentg = 0;
|
||||
byte tmpCommand; //used to store data coming from serial port
|
||||
boolean readMore;
|
||||
static char helpString[]= {"h:Print this help\n\n1:Create\n2:Append\n3:Read\n4:Read date/time\n"
|
||||
"5:Modify date/time\n6:Delete\n7:List dir\n8:Print free space"
|
||||
"\n9:Open/Create folder(s)/subfolder(s)"};
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
mySerial.begin(9600);// Important! First initialize soft serial object and after Ch376
|
||||
flashDrive.init();
|
||||
printInfo(helpString);
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(flashDrive.checkIntMessage()){
|
||||
if(flashDrive.getDeviceStatus()){
|
||||
Serial.println(F("Flash drive attached!"));
|
||||
} else {
|
||||
Serial.println(F("Flash drive detached!"));
|
||||
}
|
||||
}
|
||||
if(Serial.available()){
|
||||
tmpCommand = Serial.read(); //read incoming bytes from the serial monitor
|
||||
if(((tmpCommand > 48)&&(tmpCommand < 58)) && !flashDrive.driveReady()){ // if the data is ASCII 1 - 9 and no flash drive are attached
|
||||
printInfo("Attach flash drive first!");
|
||||
tmpCommand = 10; // change the command byte
|
||||
}
|
||||
switch (tmpCommand) {
|
||||
|
||||
case 49: //1
|
||||
printInfo("COMMAND1: Create and write data to file : TEST1.TXT"); // Create a file called TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
flashDrive.writeFile(adat, strlen(adat)); //string, string length
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 50: //2
|
||||
printInfo("COMMAND2: Append data to file: TEST1.TXT"); // Append data to the end of the file.
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
if(flashDrive.openFile() == ANSW_USB_INT_SUCCESS){ //open the file
|
||||
flashDrive.moveCursor(CURSOREND); //if the file exist, move the "virtual" cursor at end of the file, with CURSORBEGIN we actually rewrite our old file
|
||||
//flashDrive.moveCursor(flashDrive.getFileSize()); // is almost the same as CURSOREND, because we put our cursor at end of the file
|
||||
}
|
||||
for(int a = 0; a < 20; a++){ //write text from string(adat) to flash drive 20 times
|
||||
if(flashDrive.getFreeSectors()){ //check the free space on the drive
|
||||
flashDrive.writeFile(adat2, strlen(adat2)); //string, string length
|
||||
} else {
|
||||
printInfo("Disk full");
|
||||
}
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 51: //3
|
||||
printInfo("COMMAND3: Read File: TEST1.TXT"); // Read the contents of this file on the USB disk, and display contents in the Serial Monitor
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
readMore = true;
|
||||
//read data from flash drive until we reach EOF
|
||||
while(readMore){ // our temporary buffer where we read data from flash drive and the size of that buffer
|
||||
readMore = flashDrive.readFile(adatBuffer, sizeof(adatBuffer));
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 52: //4
|
||||
printInfo("COMMAND4: Read File date/time: TEST1.TXT"); // Read the date and time of file, default 2004.01.01 - 00:00:00
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
//print informations about the file
|
||||
Serial.println(flashDrive.getFileName());
|
||||
Serial.print(flashDrive.getYear());
|
||||
Serial.print("y\t");
|
||||
Serial.print(flashDrive.getMonth());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getDay());
|
||||
Serial.print("d\t");
|
||||
Serial.print(flashDrive.getHour());
|
||||
Serial.print("h\t");
|
||||
Serial.print(flashDrive.getMinute());
|
||||
Serial.print("m\t");
|
||||
Serial.print(flashDrive.getSecond());
|
||||
Serial.println('s');
|
||||
flashDrive.closeFile(); //at the end, close the file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 53: //5
|
||||
printInfo("COMMAND5: Modify File date/time: TEST1.TXT"); // Modify the file date/time and save
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
|
||||
flashDrive.setYear(2019);
|
||||
flashDrive.setMonth(12);
|
||||
flashDrive.setDay(19);
|
||||
flashDrive.setHour(03);
|
||||
flashDrive.setMinute(38);
|
||||
flashDrive.setSecond(42);
|
||||
|
||||
flashDrive.saveFileAttrb(); //save the changed data
|
||||
flashDrive.closeFile(); //and yes again, close the file after when you don`t use it
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 54: //6
|
||||
printInfo("COMMAND6: Delete File: TEST1.TXT"); // Delete the file named TEST1.TXT
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.deleteFile(); //delete file
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 55: //7
|
||||
printInfo("COMMAND7: List directory"); //Print all file names in the current directory
|
||||
while(flashDrive.listDir()){ // reading next file
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){//directory
|
||||
Serial.print('/');
|
||||
Serial.println(flashDrive.getFileName()); // get the actual file name
|
||||
} else {
|
||||
Serial.print(flashDrive.getFileName()); // get the actual file name
|
||||
Serial.print(" : ");
|
||||
Serial.print(flashDrive.getFileSize()); // get the actual file size in bytes
|
||||
Serial.print(" >>>\t");
|
||||
Serial.println(flashDrive.getFileSizeStr()); // get the actual file size in formatted string
|
||||
}
|
||||
}
|
||||
printInfo("Done!");
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 56: //8
|
||||
totSect = flashDrive.getTotalSectors(); // get the total sector number
|
||||
freeSect = flashDrive.getFreeSectors(); // get the available sector number
|
||||
percentg = map(freeSect,totSect,0,0,100); // convert it to percentage (0-100)
|
||||
Serial.print("Disk size in bytes: ");
|
||||
/*if the sector number is more than 8388607 (8388607 * 512 = 4294966784 byte = 4Gb (fits in a 32bit variable) )
|
||||
e.g. 8388608 * 512 = 4294967296 byte (32bit variable overflows) */
|
||||
if(totSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(totSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print("\tFree space in bytes: ");
|
||||
if(freeSect > 8388607){
|
||||
Serial.print(">4Gb");
|
||||
} else {
|
||||
Serial.print(freeSect * SECTORSIZE);
|
||||
}
|
||||
Serial.print(F("\tDisk usage :"));
|
||||
Serial.print(percentg);
|
||||
Serial.print(F("%"));
|
||||
switch (flashDrive.getFileSystem()) { //1-FAT12, 2-FAT16, 3-FAT32
|
||||
case 1:
|
||||
Serial.println(F("\tFAT12 partition"));
|
||||
break;
|
||||
case 2:
|
||||
Serial.println(F("\tFAT16 partition"));
|
||||
break;
|
||||
case 3:
|
||||
Serial.println(F("\tFAT32 partition"));
|
||||
break;
|
||||
default:
|
||||
Serial.println(F("\tNo valid partition"));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 57: //9
|
||||
switch(flashDrive.cd("/DIR1/DIR2/DIR3",1)){
|
||||
case CH376_ERR_LONGFILENAME: //0x01
|
||||
Serial.println(F("Directory name is too long"));
|
||||
break;
|
||||
|
||||
case ANSW_USB_INT_SUCCESS: //0x14
|
||||
Serial.println(F("Directory created successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_OPEN_DIR: //0x41
|
||||
Serial.println(F("Directory opened successfully"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_MISS_FILE: //0x42
|
||||
Serial.println(F("Directory doesn't exist"));
|
||||
break;
|
||||
|
||||
case ANSW_ERR_FOUND_NAME: //0x43
|
||||
Serial.println(F("File exist with the given name"));
|
||||
break;
|
||||
|
||||
default:
|
||||
|
||||
break;
|
||||
}
|
||||
break;
|
||||
//*****************************************************************************************************************************************************
|
||||
case 104: //h
|
||||
printInfo(helpString);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
|
||||
}//endif serial available
|
||||
|
||||
}//end loop
|
||||
|
||||
//Print information
|
||||
void printInfo(const char info[]){
|
||||
|
||||
int infoLength = strlen(info);
|
||||
if(infoLength > 40){
|
||||
infoLength = 40;
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.println();
|
||||
Serial.println(info);
|
||||
for(int a = 0; a < infoLength; a++){
|
||||
Serial.print('*');
|
||||
}
|
||||
Serial.print(F("\n\n"));
|
||||
}
|
152
libraries/Ch376msc-1.4.4/examples/lcd_menu/lcd_menu.ino
Normal file
152
libraries/Ch376msc-1.4.4/examples/lcd_menu/lcd_menu.ino
Normal file
@ -0,0 +1,152 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 05 Feb 2020 |
|
||||
* Description: One variation of the LCD menu without using a large buffer to store filenames |
|
||||
* In fact, we select the current file based on the file number (Folder handling is not implemented) |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
#include <LiquidCrystal.h>
|
||||
//..............................................................................................................................
|
||||
// Connect to SPI port: MISO, MOSI, SCK
|
||||
|
||||
// These function-like macros are optionally used when creating an object
|
||||
//e.g. SPI_SCK_KHZ(500) - set the clock speed to 500 kHz
|
||||
//e.g. SPI_SCK_MHZ(1) - set the clock speed to 1 MHz
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10,SPI_SCK_KHZ(500)); // chipSelect
|
||||
//If the SPI port shared with other devices e.g TFT display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
//LCD in 4bit mode (RS,E,D4,D5,D6,D7)
|
||||
LiquidCrystal lcd(3, 2, 7, 6, 5, 4);
|
||||
|
||||
#define BTN_UP A0 // Button UP
|
||||
#define BTN_DOWN A1 // Button DOWN
|
||||
#define BTN_OK A2 // Button OK
|
||||
#define LCD_ROW 2 // Lcd Row count
|
||||
#define LCD_CLMN 16 // Lcd Column count
|
||||
//..............................................................................................................................
|
||||
|
||||
void setup() {
|
||||
pinMode(BTN_UP, INPUT_PULLUP);
|
||||
pinMode(BTN_DOWN, INPUT_PULLUP);
|
||||
pinMode(BTN_OK, INPUT_PULLUP);
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
lcd.begin(LCD_CLMN,LCD_ROW);
|
||||
lcd.print(F("Press OK"));
|
||||
}
|
||||
|
||||
void loop() {
|
||||
if(digitalRead(BTN_OK) == LOW){ // Press OK to show files
|
||||
delay(100);// debounce
|
||||
int fileCnt = 0;// variable to store the total file count
|
||||
if(flashDrive.driveReady()){// if drive is attached
|
||||
flashDrive.resetFileList();
|
||||
while(flashDrive.listDir()){
|
||||
fileCnt++; // count all the files + directories
|
||||
}
|
||||
menu(fileCnt);// start menu
|
||||
lcd.clear();
|
||||
lcd.print(F("Press OK"));
|
||||
} //end if drive attached
|
||||
}//end if button OK pressed
|
||||
}//end loop
|
||||
|
||||
void menu(int fileCount){
|
||||
boolean b_exit = false;
|
||||
int cursorPos = 0;//cursor position
|
||||
int filePos = 0;//file position
|
||||
int oldFilePos = 0;//old file position
|
||||
char adatBuffer[25];// max length 255 = 254 char + 1 NULL character
|
||||
fileListToLCD(filePos);//lcd print first files
|
||||
|
||||
while(!b_exit){ // stay in while loop as long as b_exit value is false
|
||||
if(digitalRead(BTN_DOWN) == LOW && filePos < (fileCount-1)){
|
||||
delay(200);
|
||||
filePos++;
|
||||
}
|
||||
|
||||
if(digitalRead(BTN_UP) == LOW && filePos > 0){
|
||||
delay(200);
|
||||
filePos--;
|
||||
}
|
||||
|
||||
if(filePos != oldFilePos) { // when button pressed
|
||||
lcd.setCursor(0,cursorPos);// delete the old cursor
|
||||
lcd.print(" ");
|
||||
if(filePos > oldFilePos){ //move forward or backward depending on the button press
|
||||
cursorPos++;
|
||||
} else {
|
||||
cursorPos--;
|
||||
}
|
||||
oldFilePos = filePos;
|
||||
|
||||
if(cursorPos>(LCD_ROW-1) ){// if moved forward and reached the last row
|
||||
fileListToLCD(filePos);//get the next files
|
||||
cursorPos = 0;// put the cursor on the first line
|
||||
} else if(cursorPos < 0){//if moved backward and reached the first row
|
||||
flashDrive.resetFileList();//reset the state machine
|
||||
searchFileName(filePos);// find the previous file by its number
|
||||
fileListToLCD(filePos);//print them on to lcd
|
||||
cursorPos = 0;//put the cursor on the first line
|
||||
filePos -= (LCD_ROW-1);
|
||||
oldFilePos = filePos;
|
||||
}
|
||||
|
||||
lcd.setCursor(0,cursorPos);// print cursor to lcd
|
||||
lcd.print(">");
|
||||
}
|
||||
|
||||
if(digitalRead(BTN_OK) == LOW) {// choose a file and press ok to print content to serial
|
||||
flashDrive.resetFileList();//reset the state machine
|
||||
while(flashDrive.listDir()){ // find the selected file name by its number
|
||||
if(!filePos) break;
|
||||
filePos--;
|
||||
}
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){// if the selected item is directory the do nothing
|
||||
b_exit = true;// done with menu function
|
||||
} else {// if the selected item is a valid file then print it to serial
|
||||
flashDrive.setFileName();
|
||||
flashDrive.openFile();
|
||||
while(!flashDrive.getEOF()){ //read until EOF
|
||||
flashDrive.readFile(adatBuffer, sizeof(adatBuffer));
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
b_exit = true;// done with menu function
|
||||
}//end if directory
|
||||
}//end if OK pressed
|
||||
}//end if while
|
||||
delay(500);
|
||||
}
|
||||
|
||||
void fileListToLCD(byte a) {
|
||||
lcd.clear();
|
||||
for (byte i=0; i<LCD_ROW; i++){
|
||||
lcd.setCursor(1, i);
|
||||
if(flashDrive.listDir()){
|
||||
if(flashDrive.getFileAttrb() == CH376_ATTR_DIRECTORY){
|
||||
lcd.print('/');
|
||||
}
|
||||
lcd.print(flashDrive.getFileName());
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(!a){
|
||||
lcd.setCursor(0,0);
|
||||
lcd.print(">");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void searchFileName(int fileNum){
|
||||
fileNum-=(LCD_ROW-1);
|
||||
while(fileNum && flashDrive.listDir()){
|
||||
fileNum--;
|
||||
}
|
||||
}
|
49
libraries/Ch376msc-1.4.4/examples/readUntil/readUntil.ino
Normal file
49
libraries/Ch376msc-1.4.4/examples/readUntil/readUntil.ino
Normal file
@ -0,0 +1,49 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 27 Jan 2020 |
|
||||
* Description: Basic usage of function readFileUntil(); |
|
||||
* Create TEST1.TXT file with e.g. basicUsageSPI.ino |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
|
||||
//If the SPI port shared with other devices e.g TFT display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
// buffer for reading
|
||||
char adatBuffer[25];// max length 255 = 254 char + 1 NULL character
|
||||
boolean readMore = true;
|
||||
int trmCharCounter = 0;
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
|
||||
if(flashDrive.driveReady()){
|
||||
flashDrive.setFileName("TEST1.TXT"); //set the file name
|
||||
flashDrive.openFile(); //open the file
|
||||
//read data from flash drive until we reach EOF
|
||||
while(!flashDrive.getEOF()){
|
||||
readMore = true;
|
||||
while(readMore){
|
||||
// terminator character, temporary buffer where we read data from flash drive and the size of that buffer
|
||||
// returns boolean true if the given buffer is full and didn't found the terminator character
|
||||
readMore = flashDrive.readFileUntil('\n', adatBuffer, sizeof(adatBuffer));//new line character
|
||||
Serial.print(adatBuffer); //print the contents of the temporary buffer
|
||||
}//end while readMore
|
||||
trmCharCounter++;
|
||||
}//end while not EOF
|
||||
Serial.print(F("Total trm. character found: "));
|
||||
Serial.println(trmCharCounter);
|
||||
} else {
|
||||
Serial.println(F("Drive not initialized"));
|
||||
}//end if driveReady
|
||||
}//end setup
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
@ -0,0 +1,76 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 03 Feb 2020 |
|
||||
* Description: Basic usage of functions read/write numbers |
|
||||
* |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
|
||||
//If the SPI port shared with other devices e.g TFT display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
// buffer for reading
|
||||
char adatBuffer[25];// max length 255 = 254 char + 1 NULL character
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
flashDrive.init();
|
||||
|
||||
if(flashDrive.driveReady()){
|
||||
flashDrive.setFileName("INTEGER.TXT");
|
||||
flashDrive.openFile();
|
||||
Serial.println(F("Writing integer numbers :"));
|
||||
for(int a = 0; a < 20; a++){
|
||||
int dd = random(-4000, 4000);
|
||||
Serial.println(dd);
|
||||
flashDrive.writeNumln(dd);
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
Serial.println(F("Writing done"));
|
||||
Serial.println();
|
||||
////////////////////////////////////////
|
||||
flashDrive.setFileName("INTEGER.TXT");
|
||||
flashDrive.openFile();
|
||||
Serial.println(F("Reading integer numbers :"));
|
||||
while(!flashDrive.getEOF()){
|
||||
Serial.println(flashDrive.readLong());
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
Serial.println(F("Reading done"));
|
||||
Serial.println();
|
||||
|
||||
/////////////////////////////////////////////
|
||||
flashDrive.setFileName("FLOAT.TXT");
|
||||
flashDrive.openFile();
|
||||
Serial.println(F("Writing float numbers :"));
|
||||
for(int a = 0; a < 20; a++){
|
||||
float dd = random(-40, 40) * 3.14;
|
||||
Serial.println(dd);
|
||||
flashDrive.writeNumln(dd);
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
Serial.println(F("Writing done"));
|
||||
Serial.println();
|
||||
////////////////////////////////////////
|
||||
flashDrive.setFileName("FLOAT.TXT");
|
||||
flashDrive.openFile();
|
||||
Serial.println(F("Reading float numbers :"));
|
||||
while(!flashDrive.getEOF()){
|
||||
Serial.println(flashDrive.readDouble());
|
||||
}
|
||||
flashDrive.closeFile();
|
||||
Serial.println(F("Reading done"));
|
||||
Serial.println();
|
||||
} else {
|
||||
Serial.println(F("Drive error"));
|
||||
}//end drive ready
|
||||
}//end setup
|
||||
|
||||
void loop() {
|
||||
|
||||
}
|
123
libraries/Ch376msc-1.4.4/examples/sortDate/sortDate.ino
Normal file
123
libraries/Ch376msc-1.4.4/examples/sortDate/sortDate.ino
Normal file
@ -0,0 +1,123 @@
|
||||
/*------------------------------------------------------------------------------------------------------------------
|
||||
* Author: György Kovács |
|
||||
* Created: 26 Sep 2019 |
|
||||
* Description: Finding the oldest file, it can be useful e.g. writing log files to drive and |
|
||||
* if the flash drive becomes full then we can delete the oldest. |
|
||||
*------------------------------------------------------------------------------------------------------------------
|
||||
*/
|
||||
|
||||
|
||||
#include <Ch376msc.h>
|
||||
|
||||
//..............................................................................................................................
|
||||
// Connect to SPI port: MISO, MOSI, SCK
|
||||
|
||||
// use this if no other device are attached to SPI port(MISO pin used as interrupt)
|
||||
Ch376msc flashDrive(10); // chipSelect
|
||||
|
||||
//If the SPI port shared with other devices e.g SD card, display, etc. remove from comment the code below and put the code above in a comment
|
||||
//Ch376msc flashDrive(10, 9); // chipSelect, interrupt pin
|
||||
|
||||
//..............................................................................................................................
|
||||
|
||||
//..............................................................................................................................
|
||||
char fname[12] = "TEST1.TXT";
|
||||
char adat[] = "Lorem ipsum dolor sit amet";
|
||||
|
||||
int fyear = 0;
|
||||
int fmonth = 0;
|
||||
int fday = 0;
|
||||
int fhour = 0;
|
||||
int fminute = 0;
|
||||
int fsecond = 0;
|
||||
unsigned long oldUnTime = 0;
|
||||
|
||||
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
//Read more about randomSeed at https://www.arduino.cc/reference/en/language/functions/random-numbers/randomseed/
|
||||
randomSeed(analogRead(0));
|
||||
flashDrive.init();
|
||||
makeFiles(); // create 10 files on the flash drive
|
||||
|
||||
while(flashDrive.listDir()){ // read root directory
|
||||
if((convUnixTime() < oldUnTime) || !oldUnTime){ //looking for the oldest file or change the '<' symbol to '>'
|
||||
updateOldestFile(); // if you looking for the newest file
|
||||
}//end if file is older
|
||||
}//end while
|
||||
printFileData(); // print the oldest file name in to serial terminal
|
||||
}//end setup
|
||||
|
||||
void loop() {
|
||||
// do nothing
|
||||
} //end loop
|
||||
|
||||
unsigned long convUnixTime(){ // calculate "quasi" Unix time without taking into account leap years
|
||||
// Unix time is the number of seconds that have elapsed since 1970.01.01 00:00:00
|
||||
// for the multipliers check the link https://www.epochconverter.com/
|
||||
unsigned long unxTime;
|
||||
int yyr = flashDrive.getYear();
|
||||
yyr -= 1970; //elapsed years since 1970
|
||||
unxTime = (yyr * 31556926UL);
|
||||
unxTime += (flashDrive.getMonth() * 2629743UL);
|
||||
unxTime += (flashDrive.getDay() * 86400UL);
|
||||
unxTime += (flashDrive.getHour() * 3600UL);
|
||||
unxTime += (flashDrive.getMinute() * 60UL);
|
||||
unxTime += flashDrive.getSecond();
|
||||
return unxTime;
|
||||
}
|
||||
|
||||
void updateOldestFile(){
|
||||
fyear = flashDrive.getYear();
|
||||
fmonth = flashDrive.getMonth();
|
||||
fday = flashDrive.getDay();
|
||||
fhour = flashDrive.getHour();
|
||||
fminute = flashDrive.getMinute();
|
||||
fsecond = flashDrive.getSecond();
|
||||
strcpy(fname,flashDrive.getFileName()); //copy file name to fname variable
|
||||
oldUnTime = convUnixTime(); // update the oldest time variable
|
||||
}
|
||||
|
||||
void printFileData(){ // Print data to the serial terminal
|
||||
Serial.print("The oldest file is:\t");
|
||||
Serial.print(fname);
|
||||
Serial.print(' ');
|
||||
Serial.print(fyear);
|
||||
Serial.print('.');
|
||||
Serial.print(fmonth);
|
||||
Serial.print('.');
|
||||
Serial.print(fday);
|
||||
Serial.print(' ');
|
||||
Serial.print(fhour);
|
||||
Serial.print(':');
|
||||
Serial.print(fminute);
|
||||
Serial.print(':');
|
||||
Serial.println(fsecond);
|
||||
}
|
||||
|
||||
void makeFiles(){
|
||||
for(byte a = 0; a < 10; a++){
|
||||
fname[4] = (char)(a+0x30);//change the number in the file name(a + ASCII hex number(0))
|
||||
Serial.println(fname);
|
||||
flashDrive.setFileName(fname);
|
||||
flashDrive.openFile();
|
||||
flashDrive.writeFile(adat, strlen(adat));
|
||||
flashDrive.closeFile();
|
||||
|
||||
flashDrive.setFileName(fname);
|
||||
flashDrive.openFile();
|
||||
|
||||
flashDrive.setYear(random(1990, 2020)); // generate and set random year
|
||||
flashDrive.setMonth(random(1, 12)); // generate and set random month
|
||||
flashDrive.setDay(random(1, 30)); // generate and set random day
|
||||
flashDrive.setHour(random(0, 23)); // generate and set random hour
|
||||
flashDrive.setMinute(random(0, 59)); // generate and set random minute
|
||||
flashDrive.setSecond(random(0, 59)); // generate and set random second
|
||||
|
||||
flashDrive.saveFileAttrb(); //save the changed data
|
||||
flashDrive.closeFile();
|
||||
|
||||
}
|
||||
|
||||
}
|
BIN
libraries/Ch376msc-1.4.4/extras/JumperSelect.png
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/JumperSelect.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 156 KiB |
BIN
libraries/Ch376msc-1.4.4/extras/board1.jpg
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/board1.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 432 KiB |
BIN
libraries/Ch376msc-1.4.4/extras/board2.jpg
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/board2.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 426 KiB |
BIN
libraries/Ch376msc-1.4.4/extras/modPcb.png
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/modPcb.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 120 KiB |
BIN
libraries/Ch376msc-1.4.4/extras/schematic.png
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/schematic.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 74 KiB |
BIN
libraries/Ch376msc-1.4.4/extras/sdAdapter.jpg
Normal file
BIN
libraries/Ch376msc-1.4.4/extras/sdAdapter.jpg
Normal file
Binary file not shown.
After Width: | Height: | Size: 477 KiB |
75
libraries/Ch376msc-1.4.4/keywords.txt
Normal file
75
libraries/Ch376msc-1.4.4/keywords.txt
Normal file
@ -0,0 +1,75 @@
|
||||
#######################################
|
||||
# Syntax Coloring Map For Ch376
|
||||
#######################################
|
||||
# Class
|
||||
#######################################
|
||||
|
||||
Ch376msc KEYWORD1
|
||||
|
||||
#######################################
|
||||
# Methods and Functions
|
||||
#######################################
|
||||
|
||||
init KEYWORD2
|
||||
driveReady KEYWORD2
|
||||
saveFileAttrb KEYWORD2
|
||||
openFile KEYWORD2
|
||||
closeFile KEYWORD2
|
||||
moveCursor KEYWORD2
|
||||
deleteFile KEYWORD2
|
||||
pingDevice KEYWORD2
|
||||
listDir KEYWORD2
|
||||
readFile KEYWORD2
|
||||
readFileUntil KEYWORD2
|
||||
readRaw KEYWORD2
|
||||
readLong KEYWORD2
|
||||
readULong KEYWORD2
|
||||
readDouble KEYWORD2
|
||||
writeNum KEYWORD2
|
||||
writeNumln KEYWORD2
|
||||
writeFile KEYWORD2
|
||||
writeRaw KEYWORD2
|
||||
writeChar KEYWORD2
|
||||
checkIntMessage KEYWORD2
|
||||
cd KEYWORD2
|
||||
resetFileList KEYWORD2
|
||||
|
||||
getFreeSectors KEYWORD2
|
||||
getTotalSectors KEYWORD2
|
||||
getFileSize KEYWORD2
|
||||
getFileAttrb KEYWORD2
|
||||
getYear KEYWORD2
|
||||
getMonth KEYWORD2
|
||||
getDay KEYWORD2
|
||||
getHour KEYWORD2
|
||||
getMinute KEYWORD2
|
||||
getSecond KEYWORD2
|
||||
getStatus KEYWORD2
|
||||
getFileSystem KEYWORD2
|
||||
getFileName KEYWORD2
|
||||
getFileSizeStr KEYWORD2
|
||||
getDeviceStatus KEYWORD2
|
||||
getCHpresence KEYWORD2
|
||||
getSource KEYWORD2
|
||||
getError KEYWORD2
|
||||
getCursorPos KEYWORD2
|
||||
getEOF KEYWORD2
|
||||
getChipVer KEYWORD2
|
||||
|
||||
setFileName KEYWORD2
|
||||
setYear KEYWORD2
|
||||
setMonth KEYWORD2
|
||||
setDay KEYWORD2
|
||||
setHour KEYWORD2
|
||||
setMinute KEYWORD2
|
||||
setSecond KEYWORD2
|
||||
setSource KEYWORD2
|
||||
|
||||
#######################################
|
||||
# Constants
|
||||
#######################################
|
||||
CURSORBEGIN LITERAL1
|
||||
CURSOREND LITERAL1
|
||||
SECTORSIZE LITERAL1
|
||||
SPI_SCK_KHZ LITERAL1
|
||||
SPI_SCK_MHZ LITERAL1
|
9
libraries/Ch376msc-1.4.4/library.properties
Normal file
9
libraries/Ch376msc-1.4.4/library.properties
Normal file
@ -0,0 +1,9 @@
|
||||
name=Ch376msc
|
||||
version=1.4.4
|
||||
author=György Kovács
|
||||
maintainer=György Kovács <djusee@gmail.com>
|
||||
sentence=A library for CH376 file manager control chip.
|
||||
paragraph=Supports UART and SPI communication with the chip, read/write text files to USB flash drive and SD card.
|
||||
category=Data Storage
|
||||
url=https://github.com/djuseeq/Ch376msc/
|
||||
architectures=avr,sam,samd,stm32,STM32F1,esp8266,esp32
|
302
libraries/Ch376msc-1.4.4/src/API.cpp
Normal file
302
libraries/Ch376msc-1.4.4/src/API.cpp
Normal file
@ -0,0 +1,302 @@
|
||||
/*
|
||||
* API.cpp
|
||||
*
|
||||
* Created on: Jan 29, 2020
|
||||
* Author: György Kovács
|
||||
*/
|
||||
#include "Ch376msc.h"
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::dirInfoRead(){
|
||||
uint8_t tmpReturn;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_DIR_INFO_READ);// max 16 files 0x00 - 0x0f
|
||||
write(0xff);// current file is 0xff
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {//spi
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DIR_INFO_READ);// max 16 files 0x00 - 0x0f
|
||||
write(0xff);// current file is 0xff
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
rdFatInfo();
|
||||
return tmpReturn;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void Ch376msc::writeFatData(){// see fat info table under next filename
|
||||
uint8_t fatInfBuffer[32]; //temporary buffer for raw file FAT info
|
||||
memcpy ( &fatInfBuffer, &_fileData, sizeof(fatInfBuffer) ); //copy raw data to temporary buffer
|
||||
if(_interface == SPII) spiBeginTransfer();
|
||||
sendCommand(CMD_WR_OFS_DATA);
|
||||
write((uint8_t)0x00);
|
||||
write(32);
|
||||
for(uint8_t d = 0;d < 32; d++){
|
||||
write(fatInfBuffer[d]);
|
||||
}
|
||||
if(_interface == SPII) spiEndTransfer();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::mount(){ // return ANSWSUCCESS or ANSW DISK DISCON
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_DISK_MOUNT);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DISK_MOUNT);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}//end if interface
|
||||
if(!_errorCode && tmpReturn != ANSW_USB_INT_SUCCESS){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::fileEnumGo(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_FILE_ENUM_GO);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_FILE_ENUM_GO);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
if(!_errorCode && (tmpReturn != ANSW_USB_INT_DISK_READ) && (tmpReturn != ANSW_ERR_MISS_FILE)){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::byteRdGo(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_BYTE_RD_GO);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_BYTE_RD_GO);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
if(!_errorCode && (tmpReturn != ANSW_USB_INT_DISK_READ) && (tmpReturn != ANSW_USB_INT_SUCCESS)){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::fileCreate(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_FILE_CREATE);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_FILE_CREATE);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
void Ch376msc::rdFatInfo(){
|
||||
uint8_t fatInfBuffer[32]; //temporary buffer for raw file FAT info
|
||||
uint8_t dataLength;
|
||||
bool owrflow = false;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = readSerDataUSB();
|
||||
if(dataLength > sizeof(fatInfBuffer)){
|
||||
owrflow = true;
|
||||
dataLength = sizeof(fatInfBuffer);
|
||||
}
|
||||
for(uint8_t s =0;s < dataLength;s++){
|
||||
fatInfBuffer[s] = readSerDataUSB();// fill up temporary buffer
|
||||
}//end for
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = spiReadData();
|
||||
if(dataLength > sizeof(fatInfBuffer)){
|
||||
owrflow = true;
|
||||
dataLength = sizeof(fatInfBuffer);
|
||||
}
|
||||
for(uint8_t s =0;s < dataLength;s++){
|
||||
fatInfBuffer[s] = spiReadData();// fill up temporary buffer
|
||||
}//end for
|
||||
spiEndTransfer();
|
||||
}
|
||||
if(owrflow){
|
||||
setError(CH376_ERR_OVERFLOW);
|
||||
} else {
|
||||
memcpy ( &_fileData, &fatInfBuffer, sizeof(fatInfBuffer) ); //copy raw data to structured variable
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::byteWrGo(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_BYTE_WR_GO);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_BYTE_WR_GO);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
if(!_errorCode && (tmpReturn != ANSW_USB_INT_DISK_WRITE) && (tmpReturn != ANSW_USB_INT_SUCCESS)){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::reqByteRead(uint8_t a){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_BYTE_READ);
|
||||
write(a); // request data stream length for reading, 00 - FF
|
||||
write((uint8_t)0x00);
|
||||
tmpReturn= readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_BYTE_READ);
|
||||
write(a); // request data stream length for reading, 00 - FF
|
||||
write((uint8_t)0x00);
|
||||
spiEndTransfer();
|
||||
tmpReturn= spiWaitInterrupt();
|
||||
}
|
||||
if(!_errorCode && (tmpReturn != ANSW_USB_INT_SUCCESS) && (tmpReturn != ANSW_USB_INT_DISK_READ)){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::reqByteWrite(uint8_t a){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_BYTE_WRITE);
|
||||
write(a); // request data stream length for writing, 00 - FF
|
||||
write((uint8_t)0x00);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_BYTE_WRITE);
|
||||
write(a); // request data stream length for writing, 00 - FF
|
||||
write((uint8_t)0x00);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
if(!_errorCode && (tmpReturn != ANSW_USB_INT_SUCCESS) && (tmpReturn != ANSW_USB_INT_DISK_WRITE)){
|
||||
setError(tmpReturn);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void Ch376msc::sendFilename(){
|
||||
if(_interface == SPII) spiBeginTransfer();
|
||||
sendCommand(CMD_SET_FILE_NAME);
|
||||
//write(0x2f); // "/" root directory
|
||||
print(_filename); // filename
|
||||
//write(0x5C); // ez a "\" jel
|
||||
write((uint8_t)0x00); // terminating null character
|
||||
if(_interface == SPII) spiEndTransfer();
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void Ch376msc::rdDiskInfo(){
|
||||
uint8_t dataLength;
|
||||
uint8_t tmpReturn;
|
||||
uint8_t tmpdata[9];
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_DISK_QUERY);
|
||||
tmpReturn= readSerDataUSB();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = readSerDataUSB();
|
||||
for(uint8_t s =0;s < dataLength;s++){
|
||||
tmpdata[s] = readSerDataUSB();// fill up temporary buffer
|
||||
}//end for
|
||||
}//end if success
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DISK_QUERY);
|
||||
spiEndTransfer();
|
||||
tmpReturn= spiWaitInterrupt();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = spiReadData();
|
||||
for(uint8_t s =0;s < dataLength;s++){
|
||||
tmpdata[s] = spiReadData();// fill up temporary buffer
|
||||
}//end for
|
||||
spiEndTransfer();
|
||||
}//end if success
|
||||
}//end if UART
|
||||
if(tmpReturn != ANSW_USB_INT_SUCCESS){// unknown partition issue #22
|
||||
if(!_errorCode){
|
||||
setError(tmpReturn);
|
||||
}//end if error
|
||||
} else {
|
||||
clearError();
|
||||
_deviceAttached = true;
|
||||
memcpy ( &_diskData, &tmpdata, sizeof(tmpdata) ); //copy raw data to structured variable
|
||||
}
|
||||
}
|
||||
///////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::dirCreate(){
|
||||
uint8_t tmpReturn;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_DIR_CREATE);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DIR_CREATE);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void Ch376msc::driveAttach(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_driveSource == 0){//if USB
|
||||
setMode(MODE_HOST_1);//TODO:if 5F failure
|
||||
setMode(MODE_HOST_2);
|
||||
if(_interface == UARTT){
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}//end if interface
|
||||
}//end if usb
|
||||
if(tmpReturn == ANSW_USB_INT_CONNECT){// TODO: itt figyelni
|
||||
for(uint8_t a = 0;a < 5;a++){//try to mount, delay in worst case ~(number of attempts * ANSWTIMEOUT ms)
|
||||
tmpReturn = mount();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){
|
||||
clearError();
|
||||
_deviceAttached = true;
|
||||
break;
|
||||
} else if(_errorCode != CH376_ERR_TIMEOUT){
|
||||
break;
|
||||
}//end if Success
|
||||
}//end for
|
||||
} else driveDetach();
|
||||
if(_deviceAttached) rdDiskInfo();
|
||||
}
|
||||
///////////////
|
||||
void Ch376msc::driveDetach(){
|
||||
if(_driveSource == 0){//if USB
|
||||
setMode(MODE_HOST_0);
|
||||
}
|
||||
_deviceAttached = false;
|
||||
rstDriveContainer();
|
||||
rstFileContainer();
|
||||
}
|
||||
|
368
libraries/Ch376msc-1.4.4/src/Ch376msc.cpp
Normal file
368
libraries/Ch376msc-1.4.4/src/Ch376msc.cpp
Normal file
@ -0,0 +1,368 @@
|
||||
/*
|
||||
* Ch376msc.cpp
|
||||
*
|
||||
* Created on: Feb 25, 2019
|
||||
* Author: György Kovács
|
||||
*/
|
||||
|
||||
#include "Ch376msc.h"
|
||||
|
||||
//with HW serial
|
||||
Ch376msc::Ch376msc(HardwareSerial &usb, uint32_t speed) { // @suppress("Class members should be properly initialized")
|
||||
_interface = UARTT;
|
||||
_comPortHW = &usb;
|
||||
_comPort = &usb;
|
||||
_speed = speed;
|
||||
_hwSerial = true;
|
||||
}
|
||||
//with soft serial
|
||||
Ch376msc::Ch376msc(Stream &sUsb) { // @suppress("Class members should be properly initialized")
|
||||
_interface = UARTT;
|
||||
_comPort = &sUsb;
|
||||
_speed = 9600;
|
||||
_hwSerial = false;
|
||||
}
|
||||
|
||||
Ch376msc::Ch376msc(uint8_t spiSelect, uint8_t intPin, SPISettings speed){ // @suppress("Class members should be properly initialized")
|
||||
_interface = SPII;
|
||||
_intPin = intPin;
|
||||
_spiChipSelect = spiSelect;
|
||||
//_speed = speed;
|
||||
_spiSpeed = speed;
|
||||
}
|
||||
|
||||
//with SPI, MISO as INT pin(the SPI bus is only available for CH376, SPI bus can`t be shared with other SPI devices)
|
||||
Ch376msc::Ch376msc(uint8_t spiSelect, SPISettings speed){ // @suppress("Class members should be properly initialized")
|
||||
_interface = SPII;
|
||||
_intPin = MISO; // use the SPI MISO for interrupt JUST if no other device is using the SPI bus!!
|
||||
_spiChipSelect = spiSelect;
|
||||
//_speed = speed;
|
||||
_spiSpeed = speed;
|
||||
}
|
||||
Ch376msc::~Ch376msc() {
|
||||
// Auto-generated destructor stub
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
void Ch376msc::init(){
|
||||
delay(60);//wait for VCC to normalize
|
||||
if(_interface == SPII){
|
||||
if(_intPin != MISO){
|
||||
pinMode(_intPin, INPUT_PULLUP);
|
||||
}
|
||||
pinMode(_spiChipSelect, OUTPUT);
|
||||
digitalWrite(_spiChipSelect, HIGH);
|
||||
SPI.begin();
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_RESET_ALL);
|
||||
spiEndTransfer();
|
||||
delay(100);// wait after reset command
|
||||
if(_intPin == MISO){ // if we use MISO as interrupt pin, then tell it to the device ;)
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_SET_SD0_INT);
|
||||
write(0x16);
|
||||
write(0x90);
|
||||
spiEndTransfer();
|
||||
}//end if
|
||||
} else {//UART
|
||||
if(_hwSerial) _comPortHW->begin(9600);// start with default speed
|
||||
sendCommand(CMD_RESET_ALL);
|
||||
delay(100);// wait after reset command, according to the datasheet 35ms is required, but that was too short
|
||||
if(_hwSerial){ // if Hardware serial is initialized
|
||||
setSpeed(); // Dynamically configure the com speed
|
||||
}
|
||||
}//end if UART
|
||||
_controllerReady = pingDevice();// check the communication
|
||||
if(_controllerReady) clearError();// reinit clear last error code
|
||||
setMode(MODE_HOST_0);
|
||||
checkIntMessage();
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::pingDevice(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_CHECK_EXIST);
|
||||
write(0x01); // ez ertek negaltjat adja vissza
|
||||
if(readSerDataUSB() == 0xFE){
|
||||
tmpReturn = 1;//true
|
||||
}
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_CHECK_EXIST);
|
||||
write(0x01); // ez ertek negaltjat adja vissza
|
||||
if(spiReadData() == 0xFE){
|
||||
tmpReturn = 1;//true
|
||||
}
|
||||
spiEndTransfer();
|
||||
}
|
||||
if(!tmpReturn){
|
||||
setError(CH376_ERR_NO_RESPONSE);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool Ch376msc::driveReady(){//returns TRUE if the drive ready
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_driveSource == 1){//if SD
|
||||
if(!_dirDepth){// just check SD card if it's in root dir
|
||||
setMode(MODE_DEFAULT);//reinit otherwise is not possible to detect if the SD card is removed
|
||||
setMode(MODE_HOST_SD);
|
||||
tmpReturn = mount();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){
|
||||
rdDiskInfo();
|
||||
} else {
|
||||
driveDetach(); // do reinit otherwise mount will return always "drive is present"
|
||||
}//end if INT_SUCCESS
|
||||
} else tmpReturn = ANSW_USB_INT_SUCCESS;//end if not ROOT
|
||||
} else {//if USB
|
||||
tmpReturn = mount();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){
|
||||
rdDiskInfo();
|
||||
}//end if not INT SUCCESS
|
||||
}//end if interface
|
||||
return _deviceAttached;
|
||||
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
bool Ch376msc::checkIntMessage(){ //always call this function to get INT# message if thumb drive are attached/detached
|
||||
uint8_t tmpReturn = 0;
|
||||
bool intRequest = false;
|
||||
if(_interface == UARTT){
|
||||
while(_comPort->available()){ // while is needed, after connecting media, the ch376 send 3 message(connect, disconnect, connect)
|
||||
tmpReturn = readSerDataUSB();
|
||||
}//end while
|
||||
} else {//spi
|
||||
while(!digitalRead(_intPin)){
|
||||
tmpReturn = getInterrupt(); // get int message
|
||||
delay(10);//sadly but it required for stability, sometime prior attaching drive the CH376 produce more interrupts
|
||||
}// end while
|
||||
}//end if interface
|
||||
switch(tmpReturn){ // 0x15 device attached, 0x16 device disconnect
|
||||
case ANSW_USB_INT_CONNECT:
|
||||
intRequest = true;
|
||||
driveAttach();//device attached
|
||||
break;
|
||||
case ANSW_USB_INT_DISCONNECT:
|
||||
intRequest = true;
|
||||
driveDetach();//device detached
|
||||
break;
|
||||
}//end switch
|
||||
return intRequest;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::openFile(){
|
||||
if(!_deviceAttached) return 0x00;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_FILE_OPEN);
|
||||
_answer = readSerDataUSB();
|
||||
} else {//spi
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_FILE_OPEN);
|
||||
spiEndTransfer();
|
||||
_answer = spiWaitInterrupt();
|
||||
}
|
||||
if(_answer == ANSW_USB_INT_SUCCESS){ // get the file size
|
||||
dirInfoRead();
|
||||
}
|
||||
return _answer;
|
||||
}
|
||||
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::saveFileAttrb(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(!_deviceAttached) return 0x00;
|
||||
_fileWrite = 1;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_DIR_INFO_READ);
|
||||
write(0xff);// current file is 0xff
|
||||
readSerDataUSB();
|
||||
writeFatData();//send fat data
|
||||
sendCommand(CMD_DIR_INFO_SAVE);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {//spi
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DIR_INFO_READ);
|
||||
write(0xff);// current file is 0xff
|
||||
spiEndTransfer();
|
||||
spiWaitInterrupt();
|
||||
writeFatData();//send fat data
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_DIR_INFO_SAVE);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::closeFile(){ // 0x00 - w/o filesize update, 0x01 with filesize update
|
||||
uint8_t tmpReturn = 0;
|
||||
uint8_t d = 0x00;
|
||||
if(!_deviceAttached) return 0x00;
|
||||
|
||||
if(_fileWrite == 1){ // if closing file after write procedure
|
||||
d = 0x01; // close with 0x01 (to update file length)
|
||||
}
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_FILE_CLOSE);
|
||||
write(d);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_FILE_CLOSE);
|
||||
write(d);
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
|
||||
cd("/", 0);//back to the root directory if any file operation has occurred
|
||||
rstFileContainer();
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::deleteFile(){
|
||||
if(!_deviceAttached) return 0x00;
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_FILE_ERASE);
|
||||
_answer = readSerDataUSB();
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_FILE_ERASE);
|
||||
spiEndTransfer();
|
||||
_answer = spiWaitInterrupt();
|
||||
}
|
||||
cd("/",0);
|
||||
return _answer;
|
||||
}
|
||||
|
||||
///////////////////Listing files////////////////////////////
|
||||
uint8_t Ch376msc::listDir(const char* filename){
|
||||
/* __________________________________________________________________________________________________________
|
||||
* | 00 - 07 | 08 - 0A | 0B | 0C | 0D | 0E - 0F | 10 - 11 | 12 - 13| 14 - 15 |
|
||||
* |Filename |Extension|File attrib|User attrib|First ch del|Create time|Create date|Owner ID|Acc rights|
|
||||
* ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
||||
* | 16 - 17 | 18 - 19 | 1A - 1B | 1C - 1F |
|
||||
* |Mod. time|Mod. date|Start cluster| File size |
|
||||
*
|
||||
* https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system
|
||||
* http://www.tavi.co.uk/phobos/fat.html
|
||||
*/
|
||||
bool moreFiles = true; // more files waiting for read out
|
||||
bool doneFiles = false; // done with reading a file
|
||||
uint32_t tmOutCnt = millis();
|
||||
|
||||
while(!doneFiles){
|
||||
if(millis() - tmOutCnt >= ANSWTIMEOUT) setError(CH376_ERR_TIMEOUT);
|
||||
if(!_deviceAttached){
|
||||
moreFiles = false;
|
||||
break;
|
||||
}
|
||||
switch (fileProcesSTM) {
|
||||
case REQUEST:
|
||||
setFileName(filename);
|
||||
_answer = openFile();
|
||||
//_fileWrite = 2; // if in subdir
|
||||
fileProcesSTM = READWRITE;
|
||||
break;
|
||||
case READWRITE:
|
||||
if(_answer == ANSW_ERR_MISS_FILE){
|
||||
fileProcesSTM =DONE;
|
||||
moreFiles = false;// no more files in the directory
|
||||
}//end if
|
||||
if(_answer == ANSW_USB_INT_DISK_READ){
|
||||
rdFatInfo(); // read data to fatInfo buffer
|
||||
fileProcesSTM = NEXT;
|
||||
}
|
||||
break;
|
||||
case NEXT:
|
||||
_answer = fileEnumGo(); // go for the next filename
|
||||
fileProcesSTM = DONE;
|
||||
break;
|
||||
case DONE:
|
||||
if(!moreFiles){
|
||||
//closeFile(); // if no more files in the directory, close the file
|
||||
//closing file is not required after print dir (return value was always 0xB4 File is closed)
|
||||
fileProcesSTM = REQUEST;
|
||||
} else {
|
||||
fileProcesSTM = READWRITE;
|
||||
}
|
||||
doneFiles = true;
|
||||
break;
|
||||
}// end switch
|
||||
}//end while
|
||||
return moreFiles;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::moveCursor(uint32_t position){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(!_deviceAttached) return 0x00;
|
||||
|
||||
if(position > _fileData.size){ //fix for moveCursor issue #3 Sep 17, 2019
|
||||
_sectorCounter = _fileData.size % SECTORSIZE;
|
||||
} else {
|
||||
_sectorCounter = position % SECTORSIZE;
|
||||
}
|
||||
_cursorPos.value = position;//temporary
|
||||
if(_interface == SPII) spiBeginTransfer();
|
||||
sendCommand(CMD_BYTE_LOCATE);
|
||||
write(_cursorPos.b[0]);
|
||||
write(_cursorPos.b[1]);
|
||||
write(_cursorPos.b[2]);
|
||||
write(_cursorPos.b[3]);
|
||||
if(_interface == UARTT){
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {
|
||||
spiEndTransfer();
|
||||
tmpReturn = spiWaitInterrupt();
|
||||
}
|
||||
if(_cursorPos.value > _fileData.size){
|
||||
_cursorPos.value = _fileData.size;//set the valid position
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::cd(const char* dirPath, bool mkDir){
|
||||
uint8_t tmpReturn = 0;
|
||||
uint8_t pathLen = strlen(dirPath);
|
||||
if(!_deviceAttached) return 0x00;
|
||||
|
||||
_dirDepth = 0;
|
||||
if(pathLen < ((MAXDIRDEPTH*8)+(MAXDIRDEPTH+1)) ){//depth*(8char filename)+(directory separators)
|
||||
char input[pathLen + 1];
|
||||
strcpy(input,dirPath);
|
||||
setFileName("/");
|
||||
tmpReturn = openFile();
|
||||
char* command = strtok(input, "/");//split path into tokens
|
||||
while (command != NULL && !_errorCode){
|
||||
if(strlen(command) > 8){//if a dir name is longer than 8 char
|
||||
tmpReturn = CH376_ERR_LONGFILENAME;
|
||||
break;
|
||||
}
|
||||
setFileName(command);
|
||||
tmpReturn = openFile();
|
||||
if(tmpReturn == ANSW_USB_INT_SUCCESS){//if file already exist with this name
|
||||
tmpReturn = ANSW_ERR_FOUND_NAME;
|
||||
closeFile();
|
||||
break;
|
||||
} else if(mkDir && (tmpReturn == ANSW_ERR_MISS_FILE)){
|
||||
tmpReturn = dirCreate();
|
||||
if(tmpReturn != ANSW_USB_INT_SUCCESS) break;
|
||||
}//end if file exist
|
||||
_dirDepth++;
|
||||
command = strtok (NULL, "/");
|
||||
}
|
||||
} else {
|
||||
tmpReturn = CH376_ERR_LONGFILENAME;
|
||||
}//end if path is to long
|
||||
return tmpReturn;
|
||||
}
|
||||
|
||||
|
257
libraries/Ch376msc-1.4.4/src/Ch376msc.h
Normal file
257
libraries/Ch376msc-1.4.4/src/Ch376msc.h
Normal file
@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Ch376msc.h
|
||||
*
|
||||
* Created on: Feb 25, 2019
|
||||
* Author: György Kovács
|
||||
* Copyright (c) 2019, György Kovács
|
||||
* The MIT License (MIT)
|
||||
*
|
||||
* 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.
|
||||
*
|
||||
*
|
||||
******************************************************
|
||||
* Versions: *
|
||||
* ****************************************************
|
||||
* v1.4.4 Sep 29, 2020
|
||||
* - error handling improvement
|
||||
* - new function, getChipVer()
|
||||
* - bug fix, issue #34 Variable Naming conflicts with core ESP32 Variables
|
||||
*
|
||||
* v1.4.3 Feb 06, 2020
|
||||
* - bug fix issue #22 unknown partition
|
||||
* - new functions as requested in #21 , #23
|
||||
* - reorganizing the library
|
||||
* - added function-like macros to easy configure the SPI clock rate
|
||||
*
|
||||
* v1.4.2 Jan 07, 2020
|
||||
* - support SD card manage(API ref. - setSource())
|
||||
* - a new example of using an SD card
|
||||
* - the checkDrive function name was misleading, renamed to checkIntMessage
|
||||
* - improvements, bug fixes
|
||||
* - unnecessary examples removed
|
||||
* ****************************************************
|
||||
* v1.4.1 Dec 22, 2019
|
||||
* - supports other architectures
|
||||
* - constructor update (skip use BUSY pin)
|
||||
* - improved logic to the mount/unmount flash drive
|
||||
* - directory support ( cd(); function )
|
||||
* - advanced file listing with (*) wildcard character(API reference, listDir() function)
|
||||
*
|
||||
******************************************************
|
||||
* v1.4.0 Sep 26, 2019
|
||||
* - new functions
|
||||
* getTotalSectors() - returns a unsigned long number, total sectors on the drive
|
||||
* getFreeSectors() - returns a unsigned long number, free sectors on the drive
|
||||
* getFileSystem() - returns a byte number, 0x01-FAT12, 0x02-FAT16, 0x03-FAT32
|
||||
* - updated example files with a new functions
|
||||
* - new example file, searching the oldest/newest file on the flash drive
|
||||
* ****************************************************
|
||||
* v1.3 Sep 17, 2019
|
||||
* -bug fix for moveCursor issue #3
|
||||
* https://github.com/djuseeq/Ch376msc/issues/3
|
||||
* ****************************************************
|
||||
* v1.2 Apr 24, 2019
|
||||
* -bug fix for timing issue on higher SPI clock
|
||||
* datasheet 7.3 Time Sequence table (TSC)
|
||||
******************************************************
|
||||
* v1.2 Apr 20, 2019
|
||||
* -extended with SPI communication
|
||||
******************************************************
|
||||
* v1.1 Feb 25, 2019
|
||||
* -initial version with UART communication
|
||||
******************************************************
|
||||
*/
|
||||
|
||||
#ifndef Ch376msc_H_
|
||||
#define Ch376msc_H_
|
||||
|
||||
#include <Arduino.h>
|
||||
#include "CommDef.h"
|
||||
#include <Stream.h>
|
||||
#include <SPI.h>
|
||||
|
||||
#if defined(__STM32F1__)
|
||||
#include "itoa.h"
|
||||
#endif
|
||||
#if defined(ARDUINO_ARCH_SAM) || defined(ARDUINO_ARCH_SAMD)
|
||||
#include "avr/dtostrf.h"
|
||||
#endif
|
||||
|
||||
#define ANSWTIMEOUT 1000 // waiting for data from CH
|
||||
#define MAXDIRDEPTH 3 // 3 = /subdir1/subdir2/subdir3
|
||||
|
||||
class Ch376msc {
|
||||
public:
|
||||
/////////////Constructors////////////////////////
|
||||
Ch376msc(HardwareSerial &usb, uint32_t speed);//HW serial
|
||||
Ch376msc(Stream &sUsb);// SW serial
|
||||
|
||||
//Ch376msc(uint8_t spiSelect, uint8_t intPin, uint32_t speed = SPI_SCK_KHZ(125));
|
||||
//Ch376msc(uint8_t spiSelect, uint32_t speed = SPI_SCK_KHZ(125));//SPI with MISO as Interrupt pin
|
||||
Ch376msc(uint8_t spiSelect, uint8_t intPin, SPISettings speed = SPI_SCK_KHZ(125));
|
||||
Ch376msc(uint8_t spiSelect, SPISettings speed = SPI_SCK_KHZ(125));//SPI with MISO as Interrupt pin
|
||||
|
||||
virtual ~Ch376msc();//destructor
|
||||
////////////////////////////////////////////////
|
||||
void init();
|
||||
|
||||
uint8_t saveFileAttrb();
|
||||
uint8_t openFile();
|
||||
uint8_t closeFile();
|
||||
uint8_t moveCursor(uint32_t position);
|
||||
uint8_t deleteFile();
|
||||
uint8_t pingDevice();
|
||||
uint8_t listDir(const char* filename = "*");
|
||||
uint8_t readFile(char* buffer, uint8_t b_size);
|
||||
uint8_t readRaw(uint8_t* buffer, uint8_t b_size);
|
||||
int32_t readLong(char trmChar = '\n');
|
||||
uint32_t readULong(char trmChar = '\n');
|
||||
double readDouble(char trmChar = '\n');
|
||||
uint8_t writeChar(char trmChar);
|
||||
uint8_t writeFile(char* buffer, uint8_t b_size);
|
||||
uint8_t writeRaw(uint8_t* buffer, uint8_t b_size);
|
||||
uint8_t writeNum(uint8_t buffer);
|
||||
uint8_t writeNum(int8_t buffer);
|
||||
uint8_t writeNum(uint16_t buffer);
|
||||
uint8_t writeNum(int16_t buffer);
|
||||
uint8_t writeNum(uint32_t buffer);
|
||||
uint8_t writeNum(int32_t buffer);
|
||||
uint8_t writeNum(double buffer);
|
||||
|
||||
uint8_t writeNumln(uint8_t buffer);
|
||||
uint8_t writeNumln(int8_t buffer);
|
||||
uint8_t writeNumln(uint16_t buffer);
|
||||
uint8_t writeNumln(int16_t buffer);
|
||||
uint8_t writeNumln(uint32_t buffer);
|
||||
uint8_t writeNumln(int32_t buffer);
|
||||
uint8_t writeNumln(double buffer);
|
||||
uint8_t cd(const char* dirPath, bool mkDir);
|
||||
bool readFileUntil(char trmChar, char* buffer, uint8_t b_size);
|
||||
bool checkIntMessage(); // check is it any interrupt message came from CH(drive attach/detach)
|
||||
bool driveReady(); // call before file operation to check thumb drive or SD card are present
|
||||
void resetFileList();
|
||||
|
||||
//set/get
|
||||
|
||||
uint32_t getFreeSectors();
|
||||
uint32_t getTotalSectors();
|
||||
uint32_t getFileSize();
|
||||
uint32_t getCursorPos();
|
||||
uint16_t getYear();
|
||||
uint16_t getMonth();
|
||||
uint16_t getDay();
|
||||
uint16_t getHour();
|
||||
uint16_t getMinute();
|
||||
uint16_t getSecond();
|
||||
uint8_t getStatus();
|
||||
uint8_t getFileSystem();
|
||||
uint8_t getFileAttrb();
|
||||
uint8_t getSource();
|
||||
uint8_t getError();
|
||||
uint8_t getChipVer();
|
||||
char* getFileName();
|
||||
char* getFileSizeStr();
|
||||
bool getDeviceStatus(); // usb device mounted, unmounted
|
||||
bool getCHpresence();
|
||||
bool getEOF();
|
||||
|
||||
void setFileName(const char* filename = "");
|
||||
void setYear(uint16_t year);
|
||||
void setMonth(uint16_t month);
|
||||
void setDay(uint16_t day);
|
||||
void setHour(uint16_t hour);
|
||||
void setMinute(uint16_t minute);
|
||||
void setSecond(uint16_t second);
|
||||
void setSource(uint8_t inpSource);
|
||||
|
||||
private:
|
||||
|
||||
void write(uint8_t data);
|
||||
void print(const char str[]);
|
||||
void spiBeginTransfer();
|
||||
void spiEndTransfer();
|
||||
void driveAttach();
|
||||
void driveDetach();
|
||||
|
||||
uint8_t spiWaitInterrupt();
|
||||
uint8_t spiReadData();
|
||||
uint8_t mount();
|
||||
uint8_t getInterrupt();
|
||||
uint8_t fileEnumGo();
|
||||
uint8_t byteRdGo();
|
||||
uint8_t fileCreate();
|
||||
uint8_t byteWrGo();
|
||||
uint8_t reqByteRead(uint8_t a);
|
||||
uint8_t reqByteWrite(uint8_t a);
|
||||
uint8_t readSerDataUSB();
|
||||
uint8_t writeMachine(uint8_t* buffer, uint8_t b_size);
|
||||
uint8_t writeDataFromBuff(uint8_t* buffer);
|
||||
uint8_t readDataToBuff(uint8_t* buffer, uint8_t siz);
|
||||
uint8_t readMachine(uint8_t* buffer, uint8_t b_size);
|
||||
uint8_t dirInfoRead();
|
||||
uint8_t setMode(uint8_t mode);
|
||||
uint8_t dirCreate();
|
||||
|
||||
void rdFatInfo();
|
||||
void setSpeed();
|
||||
void setError(uint8_t errCode);
|
||||
void clearError();
|
||||
void sendCommand(uint8_t b_parancs);
|
||||
void sendFilename();
|
||||
void writeFatData();
|
||||
void constructDate(uint16_t value, uint8_t ymd);
|
||||
void constructTime(uint16_t value, uint8_t hms);
|
||||
void rdDiskInfo();
|
||||
void rstFileContainer();
|
||||
void rstDriveContainer();
|
||||
|
||||
///////Global Variables///////////////////////////////
|
||||
bool _deviceAttached = false; //false USB detached, true attached
|
||||
bool _controllerReady = false; // ha sikeres a kommunikacio
|
||||
bool _hwSerial;
|
||||
uint8_t _fileWrite = 0; // read or write mode, needed for close operation
|
||||
uint8_t _dirDepth = 0;// Don't check SD card if it's in subdir
|
||||
uint8_t _byteCounter = 0; //vital variable for proper reading,writing
|
||||
uint8_t _answer = 0; //a CH jelenlegi statusza INTERRUPT
|
||||
uint8_t _driveSource = 0;//0 = USB, 1 = SD
|
||||
uint8_t _spiChipSelect; // chip select pin SPI
|
||||
uint8_t _intPin; // interrupt pin
|
||||
uint8_t _errorCode = 0; // Store the last error code(see datasheet or CommDef.h)
|
||||
uint16_t _sectorCounter = 0;// variable for proper reading
|
||||
uint32_t _speed ; // Serial communication speed
|
||||
|
||||
fSizeContainer _cursorPos; //unsigned long union
|
||||
|
||||
char _filename[12];
|
||||
|
||||
HardwareSerial* _comPortHW; // Serial interface
|
||||
Stream* _comPort;
|
||||
SPISettings _spiSpeed;
|
||||
|
||||
commInterface _interface;
|
||||
fileProcessENUM fileProcesSTM = REQUEST;
|
||||
|
||||
fatFileInfo _fileData;
|
||||
diskInfo _diskData;
|
||||
|
||||
|
||||
};//end class
|
||||
|
||||
#endif /* Ch376msc_H_ */
|
||||
|
||||
|
93
libraries/Ch376msc-1.4.4/src/Comm.cpp
Normal file
93
libraries/Ch376msc-1.4.4/src/Comm.cpp
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
* Comm.cpp
|
||||
*
|
||||
* Created on: Apr 6, 2019
|
||||
* Author: György Kovács
|
||||
*/
|
||||
|
||||
|
||||
#include "Ch376msc.h"
|
||||
|
||||
/////////////////Alap parancs kuldes az USB fele/////////////////
|
||||
void Ch376msc::sendCommand(uint8_t b_parancs){
|
||||
if(_interface == UARTT){
|
||||
write(0x57);// UART first sync command
|
||||
write(0xAB);// UART second sync command
|
||||
}//end if
|
||||
write(b_parancs);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::readSerDataUSB(){
|
||||
uint32_t oldMillis = millis();
|
||||
while (!_comPort->available()){ // wait until data is arrive
|
||||
if ((millis()- oldMillis) > ANSWTIMEOUT){
|
||||
setError(CH376_ERR_TIMEOUT);
|
||||
return 0x00; // Timeout valasz
|
||||
}//end if
|
||||
}//end while
|
||||
return _comPort->read();
|
||||
}
|
||||
|
||||
void Ch376msc::write(uint8_t data){
|
||||
if(_interface == UARTT){
|
||||
_comPort->write(data);
|
||||
} else { // SPI
|
||||
delayMicroseconds(2);//datasheet TSC min 1.5uSec
|
||||
SPI.transfer(data);
|
||||
}
|
||||
}//end SPI
|
||||
|
||||
uint8_t Ch376msc::spiReadData(){
|
||||
delayMicroseconds(2);//datasheet TSC min 1.5uSec
|
||||
return SPI.transfer(0x00);
|
||||
}
|
||||
|
||||
void Ch376msc::print(const char str[]){
|
||||
uint8_t stringCounter = 0;
|
||||
if(_interface == UARTT){
|
||||
_comPort->print(str);
|
||||
} else { // SPI
|
||||
while(str[stringCounter]){ ///while not NULL
|
||||
write(str[stringCounter]);
|
||||
stringCounter++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Ch376msc::spiWaitInterrupt(){
|
||||
uint8_t answ = 0xFF;
|
||||
uint32_t oldMillis = millis();
|
||||
while(digitalRead(_intPin)){
|
||||
if ((millis()- oldMillis) > ANSWTIMEOUT){
|
||||
setError(CH376_ERR_TIMEOUT);
|
||||
return 0x00;
|
||||
}//end if
|
||||
}//end while
|
||||
|
||||
answ = getInterrupt();
|
||||
|
||||
return answ;
|
||||
}
|
||||
|
||||
uint8_t Ch376msc::getInterrupt(){
|
||||
uint8_t _tmpReturn = 0;
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_GET_STATUS);
|
||||
_tmpReturn = spiReadData();
|
||||
spiEndTransfer();
|
||||
return _tmpReturn;
|
||||
}
|
||||
|
||||
void Ch376msc::spiBeginTransfer(){
|
||||
delayMicroseconds(2);
|
||||
//SPI.beginTransaction(SPISettings(_speed, MSBFIRST, SPI_MODE0));
|
||||
SPI.beginTransaction(_spiSpeed);
|
||||
digitalWrite(_spiChipSelect, LOW);
|
||||
}
|
||||
|
||||
void Ch376msc::spiEndTransfer(){
|
||||
digitalWrite(_spiChipSelect, HIGH);
|
||||
SPI.endTransaction();
|
||||
}
|
||||
|
315
libraries/Ch376msc-1.4.4/src/CommDef.h
Normal file
315
libraries/Ch376msc-1.4.4/src/CommDef.h
Normal file
@ -0,0 +1,315 @@
|
||||
const uint32_t CURSORBEGIN = 0x00000000;
|
||||
const uint32_t CURSOREND = 0xFFFFFFFF;
|
||||
const uint16_t SECTORSIZE = 512;
|
||||
|
||||
//#define SPI_SCK_KHZ(speedKhz) (1000UL * speedKhz) //get the speed in Hz
|
||||
//#define SPI_SCK_MHZ(speedMhz) (1000000UL * speedMhz) //get the speed in Hz
|
||||
#define SPI_SCK_KHZ(speedKhz) SPISettings(1000UL * speedKhz, MSBFIRST, SPI_MODE0) //with this macro i save ~100byte program space
|
||||
#define SPI_SCK_MHZ(speedMhz) SPISettings(1000000UL * speedMhz, MSBFIRST, SPI_MODE0)
|
||||
////////////Commands/////////
|
||||
const uint8_t CMD_GET_IC_VER = 0x01;
|
||||
//Result: 1 byte in data register, version number & 0x3F
|
||||
const uint8_t CMD_SET_BAUDRATE = 0x02;
|
||||
//Serial port speed
|
||||
//const uint8_t CMD_ENTER_SLEEP = 0x03;
|
||||
//Put device into sleep mode.
|
||||
//const uint8_t CMD_SET_USB_SPEED = 0x04;
|
||||
/* The command sets the USB bus speed. The command requires a data input for selecting USB bus speed, corresponding to 00H
|
||||
* 12Mbps full mode, 01H at full speed corresponding to 1.5Mbps mode (non-standard mode),
|
||||
* 02H 1.5Mbps corresponding to the low speed mode. CH376 USB bus speed of 12Mbps full-speed mode by default,
|
||||
* and execution will be automatically restored to full speed 12Mbps mode after CMD_SET_USB_MODE command sets USB mode.
|
||||
*/
|
||||
const uint8_t CMD_RESET_ALL = 0x05;
|
||||
//Need to wait 35ms before device is ready again
|
||||
const uint8_t CMD_CHECK_EXIST = 0x06;
|
||||
//Test that the interface exists and works.
|
||||
//Input: one data byte
|
||||
//Output: !input
|
||||
const uint8_t CMD_SET_SD0_INT = 0x0b; // use SPI MISO pin as INT input
|
||||
//const uint8_t CMD_SET_RETRY = 0x0b;
|
||||
// Input: 0x25, setup retry times
|
||||
// bit7=1 for infinite retry, bit3~0 retry times
|
||||
const uint8_t CMD_GET_FILE_SIZE = 0x0c;
|
||||
//Input: 0x68
|
||||
//Output: file length on 4 bytes
|
||||
//const uint8_t CMD_SET_USB_ADDRESS = 0x13;
|
||||
/* This command sets the USB device address.
|
||||
* The command requires a data input for selecting the USB device address is operated. After a reset or a USB device is
|
||||
* connected or disconnected, the USB device address is always 00H, 00H and the
|
||||
* microcontroller through a USB device Default address communication. If the microcontroller through a
|
||||
* standard USB requests an address set up USB device, then you must also set the same USB device address by this command,
|
||||
* in order to address the new CH376 USB device communication. //Chinese doc
|
||||
*/
|
||||
const uint8_t CMD_SET_USB_MODE = 0x15;
|
||||
/* Switch between different USB modes.
|
||||
Input:
|
||||
00: invalid device mode (reset default)
|
||||
01: usb device, "peripheral firmware"
|
||||
02: usb device, "inner firmware"
|
||||
03: SD host, manage SD cards
|
||||
04: invalid usb host
|
||||
05: usb host, don't generate SOF
|
||||
06: usb host, generate SOF
|
||||
07: usb host, bus reset
|
||||
Output:
|
||||
0x51: success
|
||||
0x5F: failure
|
||||
*/
|
||||
const uint8_t MODE_HOST_0 = 0x05;
|
||||
const uint8_t MODE_HOST_1 = 0x07;
|
||||
const uint8_t MODE_HOST_2 = 0x06;
|
||||
const uint8_t MODE_HOST_SD = 0x03;
|
||||
const uint8_t MODE_DEFAULT = 0x00;
|
||||
|
||||
const uint8_t CMD_GET_STATUS = 0x22;
|
||||
//Get interrupt status after an interrupt was triggered.
|
||||
//Output: interrupt status (see below)
|
||||
const uint8_t CMD_RD_USB_DATA0 = 0x27;
|
||||
/* Read data from interrupt port, or USB receive buffer.
|
||||
Output: length + data
|
||||
*/
|
||||
const uint8_t CMD_WR_USB_DATA = 0x2c;
|
||||
//Write data to transfer buffer
|
||||
//Input: length + data
|
||||
const uint8_t CMD_WR_REQ_DATA = 0x2d;
|
||||
/* Write requested data
|
||||
Used when writing to files
|
||||
Output (before input!): length of chunk to write
|
||||
Input: data to fill the requested length
|
||||
*/
|
||||
const uint8_t CMD_WR_OFS_DATA = 0x2e;
|
||||
//Write data to buffer with offset
|
||||
//Input: offset, length, data
|
||||
const uint8_t CMD_SET_FILE_NAME = 0x2f;
|
||||
/* Set file or directory name for filesystem operations
|
||||
Input: null-terminated string
|
||||
The command accepts at most 14 characters. File name must start with '/'.
|
||||
Special values:
|
||||
"": do not open anything
|
||||
"*": list every files
|
||||
"/": open root directory
|
||||
"/FOO.TXT": file in root directory
|
||||
"FOO.TXT": file in current directory
|
||||
*/
|
||||
//These commands have no direct output, instead they trigger an interrupt when done running.
|
||||
|
||||
const uint8_t CMD_DISK_CONNECT = 0x30;
|
||||
//Wait for USB mass storage to be connected
|
||||
//Interrupt with USB_INT_SUCCESS if drive is ready.
|
||||
const uint8_t CMD_DISK_MOUNT = 0x31;
|
||||
//Mount detected USB drive.
|
||||
//Triggers USB_INT_SUCCESS and returns 36 byte drive identifier in interrupt buffer.
|
||||
const uint8_t CMD_FILE_OPEN = 0x32;
|
||||
/* Open a file or directory.
|
||||
Can also return ERR_MISS_FILE if the file is not found.
|
||||
*/
|
||||
const uint8_t CMD_FILE_ENUM_GO = 0x33;
|
||||
/* Enumerate next file
|
||||
Used for reading directory catalog, get next FAT32 entry
|
||||
Use CMD_SET_FILE_NAME with a pattern (eg. "/ *" to list all files in root dir).
|
||||
Then use FILE_OPEN to get the first matching file.
|
||||
Interrupt status will be USB_INT_DISK_READ, data will be the FAT32 directory entry
|
||||
Then use this command to move on to the next matching file until the interrupt is ERR_MISS_FILE.
|
||||
*/
|
||||
const uint8_t CMD_FILE_CREATE = 0x34;
|
||||
/* Create a file (or truncate an existing file).
|
||||
The file must be open (you will get ERR_MISS_FILE) before creating.
|
||||
The default date is 2004/1/1 and length is 1 byte.
|
||||
USe DIR_INFO_READ and DIR_INFO_SAVE to edit the directory entry.
|
||||
*/
|
||||
const uint8_t CMD_FILE_ERASE = 0x35;
|
||||
/* Delete a file.
|
||||
Make sure the current file is closed first or it will also be deleted!
|
||||
Use SET_FILE_NAME then CMD_FILE_ERASE
|
||||
*/
|
||||
const uint8_t CMD_FILE_CLOSE = 0x36;
|
||||
/* Close an open file.
|
||||
* Input: 1 to update file length, 0 to leave it unchanged
|
||||
*/
|
||||
const uint8_t CMD_DIR_INFO_READ = 0x37;
|
||||
/* Read directory info
|
||||
* Input one byte which is the id of the file to get info from (in the current dir). Only the first
|
||||
* 16 entries can be accessed this way!
|
||||
* Otherwise, first open the file then query for entry 0xFF. The FAT entry for the currently open
|
||||
* file will be returned.
|
||||
* The data is returned in the interrupt stream.
|
||||
*/
|
||||
const uint8_t CMD_DIR_INFO_SAVE = 0x38;
|
||||
/* Update directory info
|
||||
* You can modify the directory entry using WR_OFS_DATA and then write it again using this command.
|
||||
*/
|
||||
const uint8_t CMD_BYTE_LOCATE = 0x39;
|
||||
/* Seek to position in file
|
||||
* Input: 4 byte file offset
|
||||
* Returns USB_INT_SUCCESS with new (absolute) offset or FFFFFFFF if reached end of file.
|
||||
* Moving to FFFFFFFF actually seeks to the end of the file (to write in append mode)
|
||||
*/
|
||||
const uint8_t CMD_BYTE_READ = 0x3a;
|
||||
/* Read from file
|
||||
* Data is returned in chunks of 255 bytes max at a time as interrupt data, then BYTE_RD_GO must be
|
||||
* used to get next chunk (as long as the interrupt status is USB_INT_DISK_READ).
|
||||
* If the pointer becomes USB_INT_SUCCESS before the requested number of bytes has been read, it
|
||||
* means the EOF was reached.
|
||||
* Input: number of bytes to read (16 bit)
|
||||
*/
|
||||
const uint8_t CMD_BYTE_RD_GO = 0x3b;
|
||||
//Get next chunk of data after BYTE_READ
|
||||
const uint8_t CMD_BYTE_WRITE = 0x3c;
|
||||
/* Write to file
|
||||
* Triggers interrupt USB_INT_DISK_WRITE. MCU should ask how much bytes to write using WR_REQ_DATA
|
||||
* and send the bytes. Operation is finished when the interrupt is USB_INT_SUCCESS.
|
||||
* Size in FAT will be updated when closing the file.
|
||||
*/
|
||||
const uint8_t CMD_BYTE_WR_GO = 0x3d;
|
||||
//Continue write operation, after a WR_REQ_DATA if the interrupt is not INT_SUCCESS yet.
|
||||
const uint8_t CMD_DISK_CAPACITY = 0x3e;
|
||||
//Get the number of sectors on disk (interrupt return, 4 bytes).
|
||||
const uint8_t CMD_DISK_QUERY = 0x3f;
|
||||
/* Get the info about the FAT partition via interrupt data:
|
||||
* 4 bytes: total number of sectors
|
||||
* 4 bytes: number of free sectors
|
||||
* 1 byte: partition type
|
||||
*/
|
||||
const uint8_t CMD_DIR_CREATE = 0x40;
|
||||
/* Create and open a directory (name must be set using SET_FILE_NAME).
|
||||
* Open an already existing directory (does not truncate)
|
||||
* Returns ERR_FOUND_NAME if the name exists but is a file
|
||||
* As with FILE_CREATE, the FAT entry can be edited (default values are the same except size is 0 and
|
||||
* directory attribute is set)
|
||||
*/
|
||||
//const uint8_t CMD_SET_ADDRESS = 0x45;
|
||||
/* The command is to set the USB control transfer command address. The command requires a data input,
|
||||
* a new USB device address is specified, the effective address is 00H ~ 7FH.
|
||||
* This command is used to simplify the standard USB requests SET_ADDRESS,
|
||||
* CH376 interrupt request to the MCU after the command is completed,
|
||||
* if the interrupt status is USB_INT_SUCCESS, then the command is executed successfully.//Chinese doc
|
||||
*/
|
||||
//const uint8_t CMD_GET_DESCR = 0x46;
|
||||
/* This command is to obtain a control transfer command descriptor. This command needs to input data specifying
|
||||
* the type of the descriptor to be acquired, effective type is 1 or 2, corresponding respectively to DEVICE device descriptors
|
||||
* and CONFIGURATION configuration descriptor, wherein the configuration descriptor further includes an interface descriptor,
|
||||
* and endpoint descriptor symbol. This command is used to simplify USB request GET_DESCRIPTOR,
|
||||
* CH376 interrupt request to the microcontroller upon completion of the command, if the interrupt status is USB_INT_SUCCESS,
|
||||
* then the command is executed successfully, the device can be acquired by CMD_RD_USB_DATA0 command descriptor data.
|
||||
* Since the control of the transmission buffer CH376 only 64 bytes, when the descriptor is longer than 64 bytes,
|
||||
* the returning operation state CH376 USB_INT_BUF_OVER, for the USB device, the device can be controlled by CMD_ISSUE_TKN_X command transmission process itself.
|
||||
*/
|
||||
//const uint8_t CMD_SET_CONFIG = 0x49;
|
||||
/* The command set is a control transfer instruction USB configuration. The command requires a data input,
|
||||
* to specify a new USB configuration values, configuration 0,configuration is canceled, or should the configuration descriptor from the USB device.
|
||||
* This command is used to simplify the standard USB requests SET_CONFIGURATION,CH376 interrupt request to the MCU after the command is completed,
|
||||
* if the interrupt status is USB_INT_SUCCESS, then the command is executed successfully.//Chinese doc
|
||||
*/
|
||||
//const uint8_t CMD_AUTO_CONFIG = 0x4D;
|
||||
/* This command is used to automatically configure the USB device does not support SD card.
|
||||
* This command is used to simplify the initialization step ordinary USB device corresponds GET_DESCR, SET_ADDRESS,
|
||||
* SET_CONFIGURATION like plurality of command sequences. CH376 After completion of the command request interrupt
|
||||
* to the microcontroller, if the interrupt status is USB_INT_SUCCESS, then the command is executed successfully.
|
||||
*/
|
||||
//const uint8_t CMD_ISSUE_TKN_X = 0x4E;
|
||||
/* The command used to trigger data transfers with the USB devices.
|
||||
* The second parameter tells we are performing a control transfer (0x80), on endpoint 0 (the 4 high bits).
|
||||
* An USB device has several endpoints, which are like independent communication channels.
|
||||
* Endpoint 0 is used for control transfers, specific commands to configure the device.
|
||||
*/
|
||||
|
||||
|
||||
/* /////////Answers from CH376///////
|
||||
*
|
||||
* Interrupt status
|
||||
* ================
|
||||
*
|
||||
* Bit 6 of the status port is 0 when an interrupt is pending.
|
||||
* As read from command 0x22, status of interrupts (also clears the interrupt)
|
||||
* 00 to 0F is for USB device mode (see CH372 docs)
|
||||
*
|
||||
* 0x2*, 0x3*: usb device error
|
||||
* bit 4: parity valid (if the bit is 0 data may be corrupt)
|
||||
* Low nibble:
|
||||
* 0xA: NAK
|
||||
* 0xE: stalled transfer
|
||||
* xx00: timeout
|
||||
* other: PID of device
|
||||
*/
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////
|
||||
const uint8_t ANSW_RET_SUCCESS = 0x51; //Operation successful
|
||||
|
||||
const uint8_t ANSW_USB_INT_SUCCESS = 0x14; //Operation successful, no further data
|
||||
const uint8_t ANSW_USB_INT_CONNECT = 0x15; //New USB device connected
|
||||
const uint8_t ANSW_USB_INT_DISCONNECT = 0x16;//USB device unplugged!
|
||||
|
||||
const uint8_t ANSW_USB_INT_USB_READY = 0x18; //Device is ready
|
||||
const uint8_t ANSW_USB_INT_DISK_READ = 0x1d; //Disk read operation
|
||||
const uint8_t ANSW_USB_INT_DISK_WRITE = 0x1e;//Disk write operation
|
||||
|
||||
|
||||
const uint8_t ANSW_RET_ABORT = 0x5F; //Operation failure
|
||||
const uint8_t ANSW_USB_INT_DISK_ERR = 0x1f; //USB storage device error
|
||||
const uint8_t ANSW_USB_INT_BUF_OVER = 0x17; //Buffer overflow
|
||||
const uint8_t ANSW_ERR_OPEN_DIR = 0x41; //Tried to open a directory with FILE_OPEN
|
||||
const uint8_t ANSW_ERR_MISS_FILE = 0x42; //File not found
|
||||
const uint8_t ANSW_ERR_FOUND_NAME = 0x43;
|
||||
const uint8_t ANSW_ERR_DISK_DISCON = 0x82; //Disk disconnected
|
||||
const uint8_t ANSW_ERR_LARGE_SECTOR = 0x84; //Sector size is not 512 bytes
|
||||
const uint8_t ANSW_ERR_TYPE_ERROR = 0x92; //Invalid partition type, reformat drive
|
||||
const uint8_t ANSW_ERR_BPB_ERROR = 0xa1; //Partition not formatted
|
||||
const uint8_t ANSW_ERR_DISK_FULL = 0xb1; //Disk full
|
||||
const uint8_t ANSW_ERR_FDT_OVER = 0xb2; //Directory full
|
||||
const uint8_t ANSW_ERR_FILE_CLOSE = 0xb4; //Attempted operation on closed file
|
||||
////////////////////////////////////////////
|
||||
const uint8_t CH376_ERR_OVERFLOW = 0x03;
|
||||
const uint8_t CH376_ERR_TIMEOUT = 0x02;
|
||||
const uint8_t CH376_ERR_NO_RESPONSE = 0x01;
|
||||
const uint8_t CH376_ERR_LONGFILENAME = 0x04;
|
||||
//File attributes
|
||||
const uint8_t CH376_ATTR_READ_ONLY = 0x01; //read-only file
|
||||
const uint8_t CH376_ATTR_HIDDEN = 0x02; //hidden file
|
||||
const uint8_t CH376_ATTR_SYSTEM = 0x04; //system file
|
||||
const uint8_t CH376_ATTR_VOLUME_ID = 0x08; //Volume label
|
||||
const uint8_t CH376_ATTR_DIRECTORY = 0x10; //subdirectory (folder)
|
||||
const uint8_t CH376_ATTR_ARCHIVE = 0x20; //archive (normal) file
|
||||
////////////////////////////////////////////
|
||||
enum commInterface{
|
||||
UARTT,
|
||||
SPII
|
||||
};
|
||||
|
||||
enum fileProcessENUM { // for file read/write state machine
|
||||
REQUEST,
|
||||
NEXT,
|
||||
READWRITE,
|
||||
DONE
|
||||
};
|
||||
|
||||
///////////************/////////////
|
||||
union fSizeContainer
|
||||
{
|
||||
uint8_t b[4]; //byte
|
||||
uint32_t value; //unsigned long
|
||||
};
|
||||
|
||||
////////////////
|
||||
///https://en.wikipedia.org/wiki/Design_of_the_FAT_file_system
|
||||
|
||||
struct fatFileInfo{
|
||||
char name[11];//11
|
||||
uint8_t fattr;//1
|
||||
uint8_t uattr;//1
|
||||
uint8_t del; //1
|
||||
uint16_t crTime;//2
|
||||
uint16_t crDate;//2
|
||||
uint16_t ownId;//2
|
||||
uint16_t accRight;//2
|
||||
uint16_t modTime;//2
|
||||
uint16_t modDate;//2
|
||||
uint16_t startCl;//2
|
||||
uint32_t size;//4
|
||||
};
|
||||
///////////////
|
||||
struct diskInfo{ //disk information
|
||||
uint32_t totalSector; //the number of total sectors (low byte first)
|
||||
uint32_t freeSector; //the number of free sectors (low byte first)
|
||||
uint8_t diskFat; //FAT type: 0x01-FAT12, 0x02-FAT16, 0x03-FAT32
|
||||
};
|
||||
|
162
libraries/Ch376msc-1.4.4/src/Read.cpp
Normal file
162
libraries/Ch376msc-1.4.4/src/Read.cpp
Normal file
@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Read.cpp
|
||||
*
|
||||
* Created on: Jan 30, 2020
|
||||
* Author: György Kovács
|
||||
*/
|
||||
|
||||
|
||||
#include "Ch376msc.h"
|
||||
|
||||
bool Ch376msc::readFileUntil(char trmChar, char* buffer, uint8_t b_size){//buffer for reading, buffer size
|
||||
char tmpBuff[2];//temporary buffer to read string and analyze
|
||||
bool readMore = true;
|
||||
uint8_t charCnt = 0;
|
||||
b_size --;// last byte is reserved for NULL terminating character
|
||||
if(!_deviceAttached) return false;
|
||||
for(; charCnt < b_size; charCnt ++){
|
||||
readMore = readFile(tmpBuff, sizeof(tmpBuff));
|
||||
buffer[charCnt] = tmpBuff[0];
|
||||
if((tmpBuff[0] == trmChar) || !readMore){// reach terminate character or EOF
|
||||
readMore = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
buffer[charCnt+1] = 0x00;//string terminate
|
||||
return readMore;
|
||||
}
|
||||
///////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::readFile(char* buffer, uint8_t b_size){
|
||||
uint8_t tmpReturn;
|
||||
b_size--;// last byte is reserved for NULL terminating character
|
||||
tmpReturn = readMachine((uint8_t*) buffer,b_size);
|
||||
buffer[_byteCounter] = '\0';// NULL terminating char
|
||||
_cursorPos.value += _byteCounter;
|
||||
_byteCounter = 0;
|
||||
return tmpReturn;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::readRaw(uint8_t* buffer, uint8_t b_size){
|
||||
uint8_t tmpReturn;
|
||||
tmpReturn = readMachine(buffer,b_size);
|
||||
_cursorPos.value += _byteCounter;
|
||||
_byteCounter = 0; // make it 0 when the buffer is full
|
||||
return tmpReturn;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
int32_t Ch376msc::readLong(char trmChar){
|
||||
char workBuffer[18];
|
||||
int32_t retval;
|
||||
readFileUntil(trmChar,workBuffer,14);
|
||||
retval = atol(workBuffer);
|
||||
return retval;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
uint32_t Ch376msc::readULong(char trmChar){
|
||||
char workBuffer[18];
|
||||
uint32_t retval;
|
||||
readFileUntil(trmChar,workBuffer,14);
|
||||
retval = atol(workBuffer);
|
||||
return retval;
|
||||
}
|
||||
//////////////////////////////////////////////////////////////////
|
||||
double Ch376msc::readDouble(char trmChar){
|
||||
double retval;
|
||||
char workBuffer[18];
|
||||
readFileUntil(trmChar,workBuffer,14);
|
||||
retval = atof(workBuffer);
|
||||
return retval;
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::readDataToBuff(uint8_t* buffer, uint8_t siz){
|
||||
uint8_t oldCounter = _byteCounter; //old buffer counter
|
||||
uint8_t dataLength; // data stream size
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = readSerDataUSB(); // data stream size
|
||||
if(dataLength > siz){
|
||||
setError(CH376_ERR_OVERFLOW);//overflow
|
||||
return 0;
|
||||
}
|
||||
while(_byteCounter < (dataLength + oldCounter)){
|
||||
buffer[_byteCounter]=readSerDataUSB(); // incoming data add to buffer
|
||||
_byteCounter ++;
|
||||
}//end while
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_RD_USB_DATA0);
|
||||
dataLength = spiReadData(); // data stream size
|
||||
if(dataLength > siz){
|
||||
setError(CH376_ERR_OVERFLOW);//overflow
|
||||
return 0;
|
||||
}
|
||||
while(_byteCounter < (dataLength + oldCounter)){
|
||||
buffer[_byteCounter]=spiReadData(); // incoming data add to buffer
|
||||
_byteCounter ++;
|
||||
}//end while
|
||||
spiEndTransfer();
|
||||
}
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::readMachine(uint8_t* buffer, uint8_t b_size){ //buffer for reading, buffer size
|
||||
uint8_t tmpReturn = 0;// more data
|
||||
uint8_t byteForRequest = 0 ;
|
||||
bool bufferFull = false;
|
||||
uint32_t tmOutCnt = 0;
|
||||
_fileWrite = 0; // read mode, required for close procedure
|
||||
if(_answer == ANSW_ERR_FILE_CLOSE || _answer == ANSW_ERR_MISS_FILE){
|
||||
bufferFull = true;
|
||||
tmpReturn = 0;// we have reached the EOF
|
||||
}
|
||||
tmOutCnt = millis();
|
||||
|
||||
while(!bufferFull){
|
||||
if(millis() - tmOutCnt >= ANSWTIMEOUT) setError(CH376_ERR_TIMEOUT);
|
||||
if(!_deviceAttached){
|
||||
tmpReturn = 0;
|
||||
break;
|
||||
}
|
||||
switch (fileProcesSTM) {
|
||||
case REQUEST:
|
||||
byteForRequest = b_size - _byteCounter;
|
||||
if(_sectorCounter == SECTORSIZE){ //if one sector has read out
|
||||
_sectorCounter = 0;
|
||||
fileProcesSTM = NEXT;
|
||||
break;
|
||||
} else if((_sectorCounter + byteForRequest) > SECTORSIZE){
|
||||
byteForRequest = SECTORSIZE - _sectorCounter;
|
||||
}
|
||||
////////////////
|
||||
_answer = reqByteRead(byteForRequest);
|
||||
if(_answer == ANSW_USB_INT_DISK_READ){
|
||||
fileProcesSTM = READWRITE;
|
||||
tmpReturn = 1; //we have not reached the EOF
|
||||
} else if(_answer == ANSW_USB_INT_SUCCESS){ // no more data, EOF
|
||||
fileProcesSTM = DONE;
|
||||
tmpReturn = 0;
|
||||
}
|
||||
break;
|
||||
case READWRITE:
|
||||
_sectorCounter += readDataToBuff(buffer, byteForRequest); //fillup the buffer
|
||||
if(_byteCounter != b_size) {
|
||||
fileProcesSTM = REQUEST;
|
||||
} else {
|
||||
fileProcesSTM = DONE;
|
||||
}
|
||||
break;
|
||||
case NEXT:
|
||||
_answer = byteRdGo();
|
||||
fileProcesSTM = REQUEST;
|
||||
break;
|
||||
case DONE:
|
||||
fileProcesSTM = REQUEST;
|
||||
bufferFull = true;
|
||||
break;
|
||||
}//end switch
|
||||
}//end while
|
||||
return tmpReturn;
|
||||
}
|
||||
|
363
libraries/Ch376msc-1.4.4/src/SetGet.cpp
Normal file
363
libraries/Ch376msc-1.4.4/src/SetGet.cpp
Normal file
@ -0,0 +1,363 @@
|
||||
/*
|
||||
* SetGet.cpp
|
||||
*
|
||||
* Created on: Mar 27, 2019
|
||||
* Author: György Kovács
|
||||
*/
|
||||
|
||||
#include "Ch376msc.h"
|
||||
|
||||
//////////////////SetGet////////////////////////////
|
||||
|
||||
void Ch376msc::setSpeed(){ //set communication speed for HardwareSerial and device
|
||||
if(_speed == 9600){ // default speed for CH
|
||||
// do nothing
|
||||
} else {
|
||||
sendCommand(CMD_SET_BAUDRATE);
|
||||
switch (_speed) {
|
||||
case 19200:
|
||||
_comPortHW->write(uint8_t(0x02));//detach freq. coef
|
||||
_comPortHW->write(uint8_t(0xD9));//detach freq. constant
|
||||
break;
|
||||
case 57600:
|
||||
_comPortHW->write(uint8_t(0x03));
|
||||
_comPortHW->write(uint8_t(0x98));
|
||||
break;
|
||||
case 115200:
|
||||
_comPortHW->write(uint8_t(0x03));
|
||||
_comPortHW->write(uint8_t(0xCC));
|
||||
break;
|
||||
default:
|
||||
_speed = 9600;
|
||||
break;
|
||||
}//end switch
|
||||
_comPortHW->end();
|
||||
_comPortHW->begin(_speed);
|
||||
delay(2);// according to datasheet 2ms
|
||||
}// end if
|
||||
|
||||
}
|
||||
//////////////////////////////////////////////////////////
|
||||
void Ch376msc::setSource(uint8_t inpSource){
|
||||
if(_driveSource != inpSource){
|
||||
_driveSource = inpSource;
|
||||
if(_driveSource == 1){// SD mode
|
||||
driveDetach();
|
||||
setMode(MODE_DEFAULT);
|
||||
setMode(MODE_HOST_SD);
|
||||
driveAttach();
|
||||
} else {// USB mode
|
||||
driveDetach();
|
||||
driveAttach();
|
||||
}//end if SD
|
||||
}//end if not
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::setMode(uint8_t mode){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_SET_USB_MODE);
|
||||
write(mode);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {//spi
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_SET_USB_MODE);
|
||||
write(mode);
|
||||
delayMicroseconds(10);
|
||||
tmpReturn = spiReadData();
|
||||
spiEndTransfer();
|
||||
delayMicroseconds(40);
|
||||
}
|
||||
return tmpReturn; // success or fail
|
||||
}
|
||||
/////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::getSource(){
|
||||
return _driveSource;
|
||||
}
|
||||
|
||||
bool Ch376msc::getDeviceStatus(){
|
||||
return _deviceAttached;
|
||||
}
|
||||
bool Ch376msc::getCHpresence(){
|
||||
return _controllerReady;
|
||||
}
|
||||
|
||||
uint8_t Ch376msc::getFileAttrb(){
|
||||
return _fileData.fattr;
|
||||
}
|
||||
|
||||
char* Ch376msc::getFileName(){
|
||||
strncpy(_filename,_fileData.name,11);
|
||||
_filename[11] = '\0';
|
||||
return _filename;
|
||||
}
|
||||
void Ch376msc::setFileName(const char* filename){
|
||||
if(_deviceAttached){
|
||||
if(strlen(filename)){//copy if file name is given
|
||||
strncpy(_filename,filename,12);//copy the filename string to internal filename variable
|
||||
} else {
|
||||
getFileName();
|
||||
}
|
||||
sendFilename(); // send to the CH376
|
||||
}
|
||||
}
|
||||
uint8_t Ch376msc::getStatus(){
|
||||
return _answer;
|
||||
}
|
||||
|
||||
uint32_t Ch376msc::getFileSize(){
|
||||
return _fileData.size;
|
||||
}
|
||||
|
||||
uint32_t Ch376msc::getCursorPos(){
|
||||
return _cursorPos.value;
|
||||
}
|
||||
|
||||
char* Ch376msc::getFileSizeStr(){ // make formatted file size string from unsigned long
|
||||
// final string is declared as static, return value
|
||||
static char fsizeString[10];// e.g 1023 byte\0 , 9 char long + NULL terminating char
|
||||
fsizeString[0] = 0; // or 1023,9 Kb\0
|
||||
uint32_t ul_size = _fileData.size;
|
||||
float fl_size;
|
||||
char strNumber[7]; // e.g 1023,9\0 , temporary buffer
|
||||
if(_deviceAttached){
|
||||
if(ul_size >= 1048576){ // if the filesize is 1Mb or bigger
|
||||
fl_size = ul_size / 1048576.0;
|
||||
dtostrf(fl_size, 1, 1, fsizeString);//convert float to string
|
||||
strcat(fsizeString," Mb"); // concatenate unit symbol
|
||||
} else if(ul_size >= 1024){ // if the filesize is in Kb range
|
||||
fl_size = ul_size / 1024.0;
|
||||
dtostrf(fl_size, 1, 1, fsizeString);//convert float to string
|
||||
strcat(fsizeString," Kb");
|
||||
} else { // if the filesize is in byte range
|
||||
ltoa(ul_size, strNumber, 10);// convert long to string
|
||||
strcpy(fsizeString,strNumber);// copy to the final string
|
||||
strcat(fsizeString," byte");// concatenate unit symbol
|
||||
}//end size
|
||||
}//end if attached
|
||||
|
||||
return fsizeString; //return the final string
|
||||
}
|
||||
|
||||
void Ch376msc::setYear(uint16_t year){ //Year(0 = 1980, 119 = 2099 supported under DOS/Windows, theoretically up to 127 = 2107)
|
||||
if(year > 2099) year = 2099;
|
||||
if(year < 1980) year = 1980;
|
||||
year -= 1980;
|
||||
constructDate(year, 0);
|
||||
}
|
||||
|
||||
uint16_t Ch376msc::getYear(){
|
||||
uint16_t year = _fileData.modDate;
|
||||
year = year>> 9;
|
||||
year += 1980;
|
||||
return year;
|
||||
}
|
||||
void Ch376msc::setMonth(uint16_t month){
|
||||
if(month > 12) month = 12;
|
||||
if(month < 1) month = 1;
|
||||
constructDate(month, 1);
|
||||
}
|
||||
uint16_t Ch376msc::getMonth(){
|
||||
uint16_t month = _fileData.modDate;
|
||||
month = month << 7;
|
||||
month = month >> 12;
|
||||
return month;
|
||||
}
|
||||
void Ch376msc::setDay(uint16_t day){
|
||||
if(day > 31) day = 31;
|
||||
if(day < 1) day = 1;
|
||||
constructDate(day, 2);
|
||||
}
|
||||
uint16_t Ch376msc::getDay(){
|
||||
uint16_t day = _fileData.modDate;
|
||||
day = day << 11;
|
||||
day = day >> 11;
|
||||
return day;
|
||||
}
|
||||
//
|
||||
void Ch376msc::setHour(uint16_t hour){ //Coordinated Universal Time (UTC)
|
||||
if(hour > 23) hour = 23;
|
||||
constructTime(hour, 0);
|
||||
}
|
||||
|
||||
uint16_t Ch376msc::getHour(){
|
||||
uint16_t hour = _fileData.modTime;
|
||||
hour = hour >> 11;
|
||||
return hour;
|
||||
}
|
||||
void Ch376msc::setMinute(uint16_t minute){
|
||||
if(minute > 59) minute = 59;
|
||||
constructTime(minute, 1);
|
||||
}
|
||||
uint16_t Ch376msc::getMinute(){
|
||||
uint16_t minute = _fileData.modTime;
|
||||
minute = minute << 5;
|
||||
minute = minute >> 10;
|
||||
return minute;
|
||||
}
|
||||
void Ch376msc::setSecond(uint16_t second){ //! 0-58 2sec steps
|
||||
if(second > 59) second = 59;
|
||||
second /= 2;
|
||||
constructTime(second, 2);
|
||||
}
|
||||
uint16_t Ch376msc::getSecond(){
|
||||
uint16_t second = _fileData.modTime;
|
||||
second = second << 11;
|
||||
second = second >> 11;
|
||||
second *= 2;
|
||||
return second;
|
||||
}
|
||||
///////////////////////////////////
|
||||
|
||||
void Ch376msc::constructDate(uint16_t value, uint8_t ymd){ // 0-year, 1-month, 2-day
|
||||
uint16_t tmpInt = _fileData.modDate;
|
||||
uint16_t year;
|
||||
uint16_t month;
|
||||
uint16_t day;
|
||||
/*<------- 0x19 --------> <------- 0x18 -------->
|
||||
*15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
*y y y y y y y m m m m d d d d d
|
||||
*/
|
||||
if(_deviceAttached){
|
||||
year = tmpInt >> 9;
|
||||
year = year << 9;
|
||||
|
||||
month = tmpInt << 7;
|
||||
month = month >> 12;
|
||||
month = month << 5;
|
||||
|
||||
day = tmpInt << 11;
|
||||
day = day >> 11;
|
||||
|
||||
switch (ymd) {
|
||||
case 0://year
|
||||
year = value;
|
||||
year = year << 9;
|
||||
break;
|
||||
case 1://month
|
||||
month = value;
|
||||
month = month << 5;
|
||||
break;
|
||||
case 2://day
|
||||
day = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
_fileData.modDate = year + month + day;
|
||||
}//end if attached
|
||||
}
|
||||
|
||||
void Ch376msc::constructTime(uint16_t value, uint8_t hms){
|
||||
uint16_t tmpInt = _fileData.modTime;
|
||||
uint16_t hour;
|
||||
uint16_t minute;
|
||||
uint16_t second;
|
||||
/*<------- 0x17 --------> <------- 0x16 -------->
|
||||
*15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
|
||||
*h h h h h m m m m m m s s s s s
|
||||
*/
|
||||
if(_deviceAttached){
|
||||
hour = tmpInt >> 11; //cut minute and second
|
||||
hour = hour << 11; // set hour
|
||||
|
||||
minute = tmpInt << 5; // cut hour
|
||||
minute = minute >> 10;// cut seconds
|
||||
minute = minute << 5; // set minute
|
||||
|
||||
second = tmpInt << 11; // cut hour and minute
|
||||
second = second >> 11; // set second
|
||||
|
||||
switch (hms) {
|
||||
case 0://hour
|
||||
hour = value;
|
||||
hour = hour << 11;
|
||||
break;
|
||||
case 1://minute
|
||||
minute = value;
|
||||
minute = minute << 5;
|
||||
break;
|
||||
case 2://second
|
||||
second = value;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}//end switch
|
||||
_fileData.modTime = hour + minute + second;
|
||||
}//end if attached
|
||||
}
|
||||
//////////////////////////////////////////////////////
|
||||
uint32_t Ch376msc::getTotalSectors(){ // disk(partition?) size in bytes = totalSector * SECTORSIZE
|
||||
return _diskData.totalSector;
|
||||
}
|
||||
//////////////////////////////////////////////////////
|
||||
uint32_t Ch376msc::getFreeSectors(){ // total free bytes = freeSector * SECTORSIZE
|
||||
return _diskData.freeSector;
|
||||
}
|
||||
//////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::getFileSystem(){ //0x01-FAT12, 0x02-FAT16, 0x03-FAT32
|
||||
return _diskData.diskFat;
|
||||
}
|
||||
//////////////////////////////////////////////////////
|
||||
void Ch376msc::clearError(){
|
||||
_errorCode = 0;
|
||||
}
|
||||
|
||||
void Ch376msc::setError(uint8_t errCode){
|
||||
_errorCode = errCode;
|
||||
_deviceAttached = false;
|
||||
_dirDepth = 0;
|
||||
_byteCounter = 0;
|
||||
_answer = 0;
|
||||
resetFileList();
|
||||
rstDriveContainer();
|
||||
rstFileContainer();
|
||||
|
||||
}
|
||||
|
||||
void Ch376msc::rstDriveContainer(){
|
||||
memset(&_diskData, 0, sizeof(_diskData));// fill up with NULL disk data container
|
||||
}
|
||||
|
||||
void Ch376msc::rstFileContainer(){
|
||||
memset(&_fileData, 0, sizeof(_fileData));// fill up with NULL file data container
|
||||
_filename[0] = '\0'; // put NULL char at the first place in a name string
|
||||
_fileWrite = 0;
|
||||
_sectorCounter = 0;
|
||||
_cursorPos.value = 0;
|
||||
}
|
||||
|
||||
uint8_t Ch376msc::getError(){
|
||||
return _errorCode;
|
||||
}
|
||||
|
||||
void Ch376msc::resetFileList(){
|
||||
fileProcesSTM = REQUEST;
|
||||
}
|
||||
|
||||
bool Ch376msc::getEOF(){
|
||||
if(_cursorPos.value < _fileData.size){
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t Ch376msc::getChipVer(){
|
||||
uint8_t tmpReturn = 0;
|
||||
if(_interface == UARTT){
|
||||
sendCommand(CMD_GET_IC_VER);
|
||||
//write(mode);
|
||||
tmpReturn = readSerDataUSB();
|
||||
} else {//spi
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_GET_IC_VER);
|
||||
//write(mode);
|
||||
delayMicroseconds(10);
|
||||
tmpReturn = spiReadData();
|
||||
spiEndTransfer();
|
||||
//delayMicroseconds(40);
|
||||
}
|
||||
return tmpReturn;
|
||||
}
|
228
libraries/Ch376msc-1.4.4/src/Write.cpp
Normal file
228
libraries/Ch376msc-1.4.4/src/Write.cpp
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
* Write.cpp
|
||||
*
|
||||
* Created on: Jan 30, 2020
|
||||
* Author: György Kovács
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "Ch376msc.h"
|
||||
|
||||
uint8_t Ch376msc::writeFile(char* buffer, uint8_t b_size){
|
||||
return writeMachine((uint8_t*)buffer,b_size);
|
||||
}
|
||||
////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::writeRaw(uint8_t* buffer, uint8_t b_size){
|
||||
return writeMachine(buffer,b_size);
|
||||
}
|
||||
////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::writeChar(char trmChar){
|
||||
return writeMachine((uint8_t*)&trmChar,1);
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
// Numbers
|
||||
///////////////////////////8////////////////////////////////
|
||||
uint8_t Ch376msc::writeNum(uint8_t buffer){
|
||||
char strBuffer[4];//max 255 = 3+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNum(int8_t buffer){
|
||||
char strBuffer[5];//max -128 = 4+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
///////////////////////////ln8/////////////////////////////////
|
||||
uint8_t Ch376msc::writeNumln(uint8_t buffer){
|
||||
char strBuffer[6];//max 255 = 3+2+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNumln(int8_t buffer){
|
||||
char strBuffer[7];//max -128 = 4+2+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////16////////////////////////////////
|
||||
uint8_t Ch376msc::writeNum(uint16_t buffer){
|
||||
char strBuffer[6];//max 65535 = 5+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNum(int16_t buffer){
|
||||
char strBuffer[7];//max -32768 = 6+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
///////////////////////////ln16/////////////////////////////////
|
||||
uint8_t Ch376msc::writeNumln(uint16_t buffer){
|
||||
char strBuffer[8];//max 65535 = 5+2+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNumln(int16_t buffer){
|
||||
char strBuffer[9];//max -32768 = 6+2+1 char
|
||||
itoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
/////////////////////////////////////////////////////////////
|
||||
|
||||
///////////////////////////32////////////////////////////////
|
||||
uint8_t Ch376msc::writeNum(uint32_t buffer){
|
||||
char strBuffer[11];//max 4 294 967 295 = 10+1 char
|
||||
ltoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNum(int32_t buffer){
|
||||
char strBuffer[12];//max -2147483648 = 11+1 char
|
||||
ltoa(buffer, strBuffer, 10);
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
|
||||
///////////////////////////ln32/////////////////////////////////
|
||||
uint8_t Ch376msc::writeNumln(uint32_t buffer){
|
||||
char strBuffer[13];//max 4 294 967 295 = 10+2+1 char
|
||||
ltoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNumln(int32_t buffer){
|
||||
char strBuffer[14];//max -2147483648 = 11+2+1 char
|
||||
ltoa(buffer, strBuffer, 10);
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
////////////////////////////////////////////////////////////////
|
||||
|
||||
////////////////////////double//////////////////////////////////
|
||||
uint8_t Ch376msc::writeNum(double buffer){
|
||||
char strBuffer[15];
|
||||
if(buffer > 4100000.00 || buffer < -4100000.00){//beyond these values, the accuracy decreases rapidly
|
||||
strcpy(strBuffer,"ovf"); //constant determined by trial and error
|
||||
} else {
|
||||
dtostrf(buffer, 1, 2, strBuffer);
|
||||
}
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
// // // // //
|
||||
uint8_t Ch376msc::writeNumln(double buffer){
|
||||
char strBuffer[15];
|
||||
if(buffer > 4100000.00 || buffer < -4100000.00){
|
||||
strcpy(strBuffer,"ovf");
|
||||
} else {
|
||||
dtostrf(buffer, 1, 2, strBuffer);
|
||||
}
|
||||
strcat(strBuffer,"\r\n");
|
||||
return writeMachine((uint8_t*)strBuffer,strlen(strBuffer));
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////
|
||||
|
||||
uint8_t Ch376msc::writeDataFromBuff(uint8_t* buffer){//====================
|
||||
uint8_t oldCounter = _byteCounter; //old buffer counter
|
||||
uint8_t dataLength; // data stream size
|
||||
if(_interface == UARTT) {
|
||||
sendCommand(CMD_WR_REQ_DATA);
|
||||
dataLength = readSerDataUSB(); // data stream size
|
||||
} else {
|
||||
spiBeginTransfer();
|
||||
sendCommand(CMD_WR_REQ_DATA);
|
||||
dataLength = spiReadData(); // data stream size
|
||||
}
|
||||
while(_byteCounter < (dataLength + oldCounter)){
|
||||
write(buffer[_byteCounter]); // read data from buffer and write to serial port
|
||||
_byteCounter ++;
|
||||
}//end while
|
||||
if(_interface == SPII) spiEndTransfer();
|
||||
return dataLength;
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////
|
||||
uint8_t Ch376msc::writeMachine(uint8_t* buffer, uint8_t b_size){
|
||||
bool diskFree = true; //free space on a disk
|
||||
bool bufferFull = true; //continue to write while there is data in the temporary buffer
|
||||
uint32_t tmOutCnt = 0;
|
||||
if(!_deviceAttached) return 0x00;
|
||||
_fileWrite = 1; // read mode, required for close procedure
|
||||
_byteCounter = 0;
|
||||
|
||||
if(_diskData.freeSector == 0){
|
||||
diskFree = false;
|
||||
return diskFree;
|
||||
}
|
||||
if(_answer == ANSW_ERR_MISS_FILE){ // no file with given name
|
||||
_answer = fileCreate();
|
||||
}//end if CREATED
|
||||
|
||||
if(_answer == ANSW_ERR_FILE_CLOSE){
|
||||
_answer = openFile();
|
||||
}
|
||||
|
||||
if(_answer == ANSW_USB_INT_SUCCESS){ // file created succesfully
|
||||
tmOutCnt = millis();
|
||||
while(bufferFull){
|
||||
if(millis() - tmOutCnt >= ANSWTIMEOUT) setError(CH376_ERR_TIMEOUT);
|
||||
if(!_deviceAttached){
|
||||
diskFree = false;
|
||||
break;
|
||||
}
|
||||
switch (fileProcesSTM) {
|
||||
case REQUEST:
|
||||
_answer = reqByteWrite(b_size - _byteCounter);
|
||||
|
||||
if(_answer == ANSW_USB_INT_SUCCESS){
|
||||
fileProcesSTM = NEXT;
|
||||
|
||||
} else if(_answer == ANSW_USB_INT_DISK_WRITE){
|
||||
fileProcesSTM = READWRITE;
|
||||
}
|
||||
break;
|
||||
case READWRITE:
|
||||
writeDataFromBuff(buffer);
|
||||
if(_byteCounter != b_size) {
|
||||
fileProcesSTM = NEXT;
|
||||
} else {
|
||||
fileProcesSTM = DONE;
|
||||
}
|
||||
break;
|
||||
case NEXT:
|
||||
if(_diskData.freeSector > 0){
|
||||
_diskData.freeSector --;
|
||||
_answer = byteWrGo();
|
||||
if(_answer == ANSW_USB_INT_SUCCESS){
|
||||
fileProcesSTM = REQUEST;
|
||||
} else if(_byteCounter != b_size ){
|
||||
fileProcesSTM = READWRITE;
|
||||
}
|
||||
} else { // if disk is full
|
||||
fileProcesSTM = DONE;
|
||||
diskFree = false;
|
||||
}
|
||||
break;
|
||||
case DONE:
|
||||
fileProcesSTM = REQUEST;
|
||||
_cursorPos.value += _byteCounter;
|
||||
_byteCounter = 0;
|
||||
_answer = byteWrGo();
|
||||
bufferFull = false;
|
||||
break;
|
||||
}//end switch
|
||||
}//end while
|
||||
}// end file created
|
||||
|
||||
return diskFree;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user