Skip to content

Instantly share code, notes, and snippets.

@joric

joric/msc.ino Secret

Created November 4, 2020 19:50
Show Gist options
  • Save joric/d04f43a42ad788fde368b36181be3977 to your computer and use it in GitHub Desktop.
Save joric/d04f43a42ad788fde368b36181be3977 to your computer and use it in GitHub Desktop.
msc.ino
// see https://github.com/joric/nrfmicro/wiki/Bluemicro
// use ramdisk.h from msc arduino sample
#define GPIO(port, pin) ((port << 5) | pin)
#define RGB_ENABLED 0
#define MSC_ENABLED 1
#define ADAFRUIT_GFX_ENABLED 1
#include "Adafruit_TinyUSB.h"
#include <Adafruit_LittleFS.h>
#include <InternalFileSystem.h>
using namespace Adafruit_LittleFS_Namespace;
#define FILENAME "/image.img"
#define CONTENTS "Adafruit Little File System test file contents"
File file(InternalFS);
#define LED_PIN GPIO(1,10)
#define RGB_PIN GPIO(0,6)
#define POWER_PIN GPIO(1,9)
#define PROG_PIN GPIO(0,5)
#define STAT_PIN GPIO(0,7)
#if (ADAFRUIT_GFX_ENABLED)
#include <Wire.h>
TwoWire nRFWire(NRF_TWIM0, NRF_TWIS0, SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQn, 15, 17);
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#define OLED_I2C_ADDR 0x3C
#define OLED_WIDTH 128
#define OLED_HEIGHT 32
#define OLED_RESET -1
Adafruit_SSD1306 display(OLED_WIDTH, OLED_HEIGHT, &Wire, OLED_RESET);
#endif
// 8KB is the smallest size that windows allow to mount
#define DISK_BLOCK_NUM 16
#define DISK_BLOCK_SIZE 512
#include "ramdisk.h"
bool dirty = false;
// HID report descriptor using TinyUSB's template
// Generic In Out with 64 bytes report (max)
uint8_t const desc_hid_report[] =
{
TUD_HID_REPORT_DESC_GENERIC_INOUT(64)
};
Adafruit_USBD_HID usb_hid;
Adafruit_USBD_MSC usb_msc;
#if (RGB_ENABLED)
#include <Adafruit_NeoPixel.h>
#define NUMPIXELS 6
#define DELAYVAL 50
Adafruit_NeoPixel pixels(NUMPIXELS, RGB_PIN, NEO_GRB + NEO_KHZ800);
#endif
const int LINES = 4;
int lnum = 0;
String lbuf[LINES];
void update(char * s) {
String line = String(lnum) + String(".") + String(s);
Serial.println(line);
#if (ADAFRUIT_GFX_ENABLED)
display.clearDisplay();
lbuf[lnum%LINES] = line;
int ofs = lnum<LINES ? 0 : (lnum + 1) % LINES;
for (int i=0; i<LINES; i++) {
display.setCursor(0, i*8);
display.print(lbuf[ (ofs+i) % LINES ].substring(0,21));
}
display.display();
#endif
lnum++;
}
// the setup function runs once when you press reset or power the board
void setup()
{
#if (ADAFRUIT_GFX_ENABLED)
Wire = nRFWire;
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
display.setTextSize(0);
display.setTextColor(WHITE);
update("USB Mass Class");
#endif
// Initialize Internal File System
InternalFS.begin();
bool exists = false;
file.open(FILENAME, FILE_O_READ);
if ( file ) {
exists = true;
for (int i = 0; i < DISK_BLOCK_NUM; i++) {
file.read(&msc_disk[i], DISK_BLOCK_SIZE);
}
file.close();
}
if (!exists)
InternalFS.format();
#if (MSC_ENABLED)
usb_msc.setID("Adafruit", "Mass Storage", "1.0");
// Set disk size
usb_msc.setCapacity(DISK_BLOCK_NUM, DISK_BLOCK_SIZE);
// Set callback
usb_msc.setReadWriteCallback(msc_read_cb, msc_write_cb, msc_flush_cb);
// Set Lun ready (RAM disk is always ready)
usb_msc.setUnitReady(true);
usb_msc.begin();
usb_hid.enableOutEndpoint(true);
usb_hid.setPollInterval(2);
usb_hid.setReportDescriptor(desc_hid_report, sizeof(desc_hid_report));
usb_hid.setReportCallback(get_report_callback, set_report_callback);
usb_hid.begin();
#endif
Serial.begin(115200);
Serial.println("Waiting for USBDevice mount");
// wait until device mounted
while ( !USBDevice.mounted() ) delay(1);
delay(1000);
Serial.println("Adafruit TinyUSB HID Generic In Out example");
if (exists) {
update("FILE EXISTS!");
}
char buf[128];
sprintf(buf, "%s", msc_disk[3]);
update(buf);
// this somehow messes msc up, should be run after msc
pinMode(LED_PIN, OUTPUT); for (int i = 0; i < 4; i++) {
digitalWrite(LED_PIN, i % 2 ? LOW : HIGH );
delay(200);
}
// enable charger
//pinMode(STAT_PIN, OUTPUT); digitalWrite(STAT_PIN, 0); pinMode(PROG_PIN, OUTPUT); digitalWrite(PROG_PIN, 0);
pinMode(POWER_PIN, OUTPUT);
digitalWrite(POWER_PIN, 0);
#if (RGB_ENABLED)
pixels.begin();
pixels.clear();
for (int j = 0; j < 4; j++)
for (int i = 0; i < NUMPIXELS; i++) { // For each pixel...
pixels.setPixelColor(i, pixels.Color(0, 0, ((j + 1) % 2) * 32));
pixels.show(); // Send the updated pixel colors to the hardware.
delay(DELAYVAL); // Pause before next pass through loop
}
#endif
}
// only flush in 1-sec cycles
int counter = 0;
void loop()
{
delay(1);
if (counter>=1000 && dirty) {
counter = 0;
if ( file.open(FILENAME, FILE_O_WRITE) )
{
file.seek(0);
for (int i = 0; i < DISK_BLOCK_NUM; i++) {
file.write(msc_disk[i], DISK_BLOCK_SIZE);
}
file.close();
update("updated file");
} else
{
update("can't update");
}
char buf[128];
sprintf(buf, "%s", msc_disk[3]);
update(buf);
dirty = false;
}
counter++;
}
// Invoked when received GET_REPORT control request
// Application must fill buffer report's content and return its length.
// Return zero will cause the stack to STALL request
uint16_t get_report_callback (uint8_t report_id, hid_report_type_t report_type, uint8_t* buffer, uint16_t reqlen)
{
// not used in this example
return 0;
}
// Invoked when received SET_REPORT control request or
// received data on OUT endpoint ( Report ID = 0, Type = 0 )
void set_report_callback(uint8_t report_id, hid_report_type_t report_type, uint8_t const* buffer, uint16_t bufsize)
{
// This example doesn't use multiple report and report ID
(void) report_id;
(void) report_type;
//char buf[128];
//sprintf(buf, "id: %d type: %d", report_id, report_type);
//update(buf);
// echo back anything we received from host
usb_hid.sendReport(0, buffer, bufsize);
}
// Callback invoked when received READ10 command.
// Copy disk's data to buffer (up to bufsize) and
// return number of copied bytes (must be multiple of block size)
int32_t msc_read_cb (uint32_t lba, void* buffer, uint32_t bufsize)
{
uint8_t const* addr = msc_disk[lba];
memcpy(buffer, addr, bufsize);
//update("msc_read_cb");
return bufsize;
}
// Callback invoked when received WRITE10 command.
// Process data in buffer to disk's storage and
// return number of written bytes (must be multiple of block size)
int32_t msc_write_cb (uint32_t lba, uint8_t* buffer, uint32_t bufsize)
{
uint8_t* addr = msc_disk[lba];
memcpy(addr, buffer, bufsize);
//update("msc_write_cb");
dirty = true;
return bufsize;
}
// Callback invoked when WRITE10 command is completed (status received and accepted by host).
// used to flush any pending cache.
void msc_flush_cb (void)
{
//update("msc_flush_cb");
// nothing to do
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment