# Teensy 3.2 + Propshield lightsaberbuild

**URL:** <https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998>\
**Category:** ProffieOS\
**Created:** [November 18, 2021, 12:48am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998 "2021-11-18T00:48:37Z")\
**Posts on this page:** 20\
**Page:** 1

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 12:48am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/1 "2021-11-18T00:48:37Z")

</div>

hello there!  
im currently try to build my lightsaber but in the guide it says you need a sd card but the Teensy 3.2 has no slot for one and the prop shield too. so im a bloody beginner with this all and my question may be stupid but I found no answer to this. I tought the code is playing and storing the sounds in the teensy or the prop shield?

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 12:52am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/2 "2021-11-18T00:52:00Z")

</div>

and I forgot one thing I use a WS2812B Led strip is this supported? and where do I need to make changes in case it is supported

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 12:56am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/3 "2021-11-18T00:56:07Z")

</div>

You can store your sound font on the prop shield flash, but there isn’t a lot of space there, so it’s very limited. Also, nobody has done that in a while, so it’s possible that it won’t work “out of the box”, but if so I can help with fixing that.

It’s possible to use an external SD card reader, like I did:  
[https://fredrik.hubbe.net/lightsaber/electronics.html](https://fredrik.hubbe.net/lightsaber/electronics.html)

It’s also possible to use a Teensy 3.5 which has an SD card reader on it.

And yes, WS2812B strips are absolutely supported.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 1:00am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/4 "2021-11-18T01:00:38Z")

</div>

thanks for the fast reply!  
ok good so I will try to get it work. I don’t need much sound files but how do I change them when not using a sd card? has the prop shield be connected while uploading the code to the teensy?  
and im not finding a link to the style generator  
ah ok good so I just have too change the led name to WS2812B?  
and thanks for your help!

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 1:04am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/5 "2021-11-18T01:04:48Z")

</div>

If you select MTP in Arduino-\>Tools-\>USB type, then ProffieOS will add an mtp server that lets you upload/download files to the flash memory on the prop shield. The prop shield doesn’t have to be connected to upload code, but obviously the code won’t work well if it expects a prop shield that isn’t there. You don’t need to change the LED name. (Where would you even do that?)

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 1:10am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/6 "2021-11-18T01:10:57Z")

</div>

ah ok so I need to change that and re upload the code.  
good so this was stupid 😃 I thought I need to change this in WS2812B  
BladeConfig blades[] = {  
{ 0, WS2811BladePtr\<144, WS2811\_ACTUALLY\_800kHz | WS2811\_GRB\>(), CONFIGARRAY(presets) },  
};

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 11:49am UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/7 "2021-11-18T11:49:47Z")

</div>

also where do I change the sounds that will be used like humming turn off and on swings etc.?

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 3:26pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/8 "2021-11-18T15:26:31Z")

</div>

That’s the font that you would upload to the prop shield flash through MTP.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 8:34pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/9 "2021-11-18T20:34:38Z")

</div>

that would be this file I guess right?

#ifndef MTP\_MTP\_STORAGE\_SD\_H  
#define MTP\_MTP\_STORAGE\_SD\_H

// Storage implementation for SD. SD needs to be already initialized.  
class MTPStorage\_SD : public MTPStorageInterface {  
public:  
explicit MTPStorage\_SD(MTPD\* mtpd) { mtpd-\>AddStorage(this); }  
private:  
File index\_;

uint8\_t mode\_ = 0;  
uint32\_t open\_file\_ = 0xFFFFFFFEUL;  
File f\_;  
uint32\_t index\_entries\_ = 0;

struct Record {  
uint32\_t parent;  
uint32\_t child; // size stored here for files  
uint32\_t sibling;  
uint8\_t isdir;  
uint8\_t scanned;  
char name[14];  
};

bool readonly() override { return false; }  
bool has\_directories() override { return true; }  
uint64\_t size() override { return 1 \<\< 30; }  
uint64\_t free() override { return 1 \<\< 29; }  
uint32\_t free\_objects() override { return 0xFFFFFFFEUL; }

const char\* GetName() override {  
return “SD Card”;  
}

void OpenIndex() {  
if (index\_) return;  
mtp\_lock\_storage(true);  
index\_ = SD.open(“mtpindex.dat”, FILE\_WRITE);  
mtp\_lock\_storage(false);  
}

void WriteIndexRecord(uint32\_t i, const Record& r) {  
OpenIndex();  
mtp\_lock\_storage(true);  
index\_.seek(sizeof(r) \* i);  
index\_.write((char\*)&r, sizeof(r));  
mtp\_lock\_storage(false);  
}

uint32\_t AppendIndexRecord(const Record& r) {  
uint32\_t new\_record = index\_entries\_++;  
WriteIndexRecord(new\_record, r);  
return new\_record;  
}

// TODO(hubbe): Cache a few records for speed.  
Record ReadIndexRecord(uint32\_t i) {  
Record ret;  
if (i \> index\_entries\_) {  
memset(&ret, 0, sizeof(ret));  
return ret;  
}  
OpenIndex();  
mtp\_lock\_storage(true);  
index\_.seek(sizeof(ret) \* i);  
index\_.read(&ret, sizeof(ret));  
mtp\_lock\_storage(false);  
return ret;  
}

void ConstructFilename(int i, char\* out) {  
if (i == 0) {  
strcpy(out, “/”);  
} else {  
Record tmp = ReadIndexRecord(i);  
ConstructFilename(tmp.parent, out);  
if (out[strlen(out)-1] != ‘/’)  
strcat(out, “/”);  
strcat(out, tmp.name);  
}  
}

void OpenFileByIndex(uint32\_t i, uint8\_t mode = O\_RDONLY) {  
if (open\_file\_ == i && mode\_ == mode)  
return;  
char filename[256];  
ConstructFilename(i, filename);  
mtp\_lock\_storage(true);  
f\_.close();  
f\_ = SD.open(filename, mode);  
open\_file\_ = i;  
mode\_ = mode;  
mtp\_lock\_storage(false);  
}

// MTP object handles should not change or be re-used during a session.  
// This would be easy if we could just have a list of all files in memory.  
// Since our RAM is limited, we’ll keep the index in a file instead.  
bool index\_generated = false;  
void GenerateIndex() {  
if (index\_generated) return;  
index\_generated = true;

```
mtp_lock_storage(true);
SD.remove("mtpindex.dat");
mtp_lock_storage(false);
index_entries_ = 0;

Record r;
r.parent = 0;
r.sibling = 0;
r.child = 0;
r.isdir = true;
r.scanned = false;
strcpy(r.name, "/");
AppendIndexRecord(r);

```

}

void ScanDir(uint32\_t i) {  
Record record = ReadIndexRecord(i);  
if (record.isdir && !record.scanned) {  
OpenFileByIndex(i);  
if (!f\_) return;  
int sibling = 0;  
while (true) {  
mtp\_lock\_storage(true);  
File child = f\_.openNextFile();  
mtp\_lock\_storage(false);  
if (!child) break;  
Record r;  
r.parent = i;  
r.sibling = sibling;  
r.isdir = child.isDirectory();  
r.child = r.isdir ? 0 : child.size();  
r.scanned = false;  
strcpy(r.name, child.name());  
sibling = AppendIndexRecord(r);  
child.close();  
}  
record.scanned = true;  
record.child = sibling;  
WriteIndexRecord(i, record);  
}  
}

bool all\_scanned\_ = false;  
void ScanAll() {  
if (all\_scanned\_) return;  
all\_scanned\_ = true;

```
GenerateIndex();
for (uint32_t i = 0; i < index_entries_; i++) {
  ScanDir(i);
}

```

}

uint32\_t next\_;  
bool follow\_sibling\_;  
void StartGetObjectHandles(uint32\_t parent) override {  
GenerateIndex();  
if (parent) {  
if (parent == 0xFFFFFFFF) parent = 0;  
ScanDir(parent);  
follow\_sibling\_ = true;  
// Root folder?  
next\_ = ReadIndexRecord(parent).child;  
} else {  
ScanAll();  
follow\_sibling\_ = false;  
next\_ = 1;  
}  
}

uint32\_t GetNextObjectHandle() override {  
while (true) {  
if (next\_ == 0)  
return 0;  
int ret = next\_;  
Record r = ReadIndexRecord(ret);  
if (follow\_sibling\_) {  
next\_ = r.sibling;  
} else {  
next\_++;  
if (next\_ \>= index\_entries\_)  
next\_ = 0;  
}  
if (r.name[0]) return ret;  
}  
}

void GetObjectInfo(uint32\_t handle,  
char\* name,  
uint32\_t\* size,  
uint32\_t\* parent) override {  
Record r = ReadIndexRecord(handle);  
strcpy(name, r.name);  
\*parent = r.parent;  
\*size = r.isdir ? 0xFFFFFFFFUL : r.child;  
}

uint32\_t GetSize(uint32\_t handle) {  
return ReadIndexRecord(handle).child;  
}

void read(uint32\_t handle,  
uint32\_t pos,  
char\* out,  
uint32\_t bytes) override {  
OpenFileByIndex(handle);  
mtp\_lock\_storage(true);  
f\_.seek(pos);  
f\_.read(out, bytes);  
mtp\_lock\_storage(false);  
}

bool DeleteObject(uint32\_t object) override {  
char filename[256];  
Record r;  
while (true) {  
r = ReadIndexRecord(object == 0xFFFFFFFFUL ? 0 : object);  
if (!r.isdir) break;  
if (!r.child) break;  
if (!DeleteObject(r.child))  
return false;  
}

```
// We can't actually delete the root folder,
// but if we deleted everything else, return true.
if (object == 0xFFFFFFFFUL) return true;

ConstructFilename(object, filename);
bool success;
mtp_lock_storage(true);
if (r.isdir) {
  success = SD.rmdir(filename);
} else {
  success = SD.remove(filename);
}
mtp_lock_storage(false);
if (!success) return false;
r.name[0] = 0;
int p = r.parent;
WriteIndexRecord(object, r);
Record tmp = ReadIndexRecord(p);
if (tmp.child == object) {
  tmp.child = r.sibling;
  WriteIndexRecord(p, tmp);
} else {
  int c = tmp.child;
  while (c) {
    tmp = ReadIndexRecord(c);
    if (tmp.sibling == object) {
      tmp.sibling = r.sibling;
      WriteIndexRecord(c, tmp);
      break;
    } else {
      c = tmp.sibling;
    }
  }
}
return true;

```

}

uint32\_t Create(uint32\_t parent,  
bool folder,  
const char\* filename) override {  
uint32\_t ret;  
if (parent == 0xFFFFFFFFUL) parent = 0;  
Record p = ReadIndexRecord(parent);  
Record r;  
if (strlen(filename) \> 12) return 0;  
strcpy(r.name, filename);  
r.parent = parent;  
r.child = 0;  
r.sibling = p.child;  
r.isdir = folder;  
// New folder is empty, scanned = true.  
r.scanned = 1;  
ret = p.child = AppendIndexRecord(r);  
WriteIndexRecord(parent, p);  
if (folder) {  
char filename[256];  
ConstructFilename(ret, filename);  
mtp\_lock\_storage(true);  
SD.mkdir(filename);  
mtp\_lock\_storage(false);  
} else {  
OpenFileByIndex(ret, FILE\_WRITE);  
}  
return ret;  
}

void write(const char\* data, uint32\_t bytes) override {  
mtp\_lock\_storage(true);  
f\_.write(data, bytes);  
mtp\_lock\_storage(false);  
}

void close() override {  
mtp\_lock\_storage(true);  
uint32\_t size = f\_.size();  
f\_.close();  
mtp\_lock\_storage(false);  
Record r = ReadIndexRecord(open\_file\_);  
r.child = size;  
WriteIndexRecord(open\_file\_, r);  
open\_file\_ = 0xFFFFFFFEUL;  
}  
};

#endif

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 8:54pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/10 "2021-11-18T20:54:01Z")

</div>

No, that file is for using MTP with SD cards.  
This is the file that implement support for MTP on serialflash:

> <https://github.com/profezzorn/ProffieOS/blob/743624ab8cdaefb95728b89d19e575325cd549f0/mtp/mtp_storage_serialflash.h>

Note that the serialflash doesn’t actually support directories, so you probably can only have one font. Not that it matters, since you will probably not have room for more than one font anyways.

You don’t really need to know which file implements what though. All you should need to worry about is what defines to put (and not put) in your config file. For instance, you should NOT have this in your config file:

```auto
#define ENABLE_SD

```

Instead, you should have:

```auto
#define ENABLE_SERIALFLASH

```

If you have `ENABLE_SERIALFLASH` and select MTP in arduino-\>tools-\>usb type, the ProffieOS should automatically use the file I linked above to make the serialflash storage available through MTP. Note that if you’re on a mac, you might need some android tools installed to get MTP support.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 9:04pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/11 "2021-11-18T21:04:55Z")

</div>

ok good then I will change this to enable serialfalsh! and the Arduino I already changed to mtp storage so I got no notification that there was a problem.  
so I need to select the fond I want and put it in the serial flash code?

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 9:09pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/12 "2021-11-18T21:09:12Z")

</div>

thank you for the help Im a total beginner in this code stuff

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 9:24pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/13 "2021-11-18T21:24:27Z")

</div>

You’ll need to upload the font files to the serialflash. Since there are no directories, all the files will just be in the top level directory. In the config file, you’ll make a preset that uses “” for the font path.  
If everything work, proffieos will find the files and play them from there.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 9:27pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/14 "2021-11-18T21:27:25Z")

</div>

ok could you show me how it should look or can look? does it know wich sound to play?

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 10:21pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/15 "2021-11-18T22:21:12Z")

</div>

Yes, it knows which sounds to play.  
This page explains most about how the file structure works for fonts:

[Sound Font Configuration · profezzorn/ProffieOS Wiki · GitHub](https://github.com/profezzorn/ProffieOS/wiki/Sound-Font-Configuration)

On a serialflash, there wouldn’t be a directory though, just files.  
Most fonts you can find/buy/download already have the files named correctly, so you would just upload them to the serialflash and call it a day. (Assuming they fit, which they probably won’t…)

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 10:37pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/16 "2021-11-18T22:37:20Z")

</div>

ok i will try it but can’t I just use the sound files from the teensy saber site?

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 10:51pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/17 "2021-11-18T22:51:34Z")

</div>

Yes you can, but you will need to pick one font, and even then you probably will need to remove some of the files to make it fit.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 10:54pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/18 "2021-11-18T22:54:42Z")

</div>

good I will do that!  
but I can use only the sounds from one or can I copy one from another and mix it?

---

<div class="post-metadata">

**Author:** ![profezzorn](https://crucible.hubbe.net/user_avatar/crucible.hubbe.net/profezzorn/32/8_2.png) [@profezzorn](https://crucible.hubbe.net/u/profezzorn)\
**Post date:** [November 18, 2021, 11:02pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/19 "2021-11-18T23:02:02Z")

</div>

You can mix sounds from different fonts.  
I would recommend making it work before you start doing that.

---

<div class="post-metadata">

**Author:** ![Somnium](https://crucible.hubbe.net/letter_avatar_proxy/v4/letter/s/f14d63/32.png) [@Somnium](https://crucible.hubbe.net/u/Somnium)\
**Post date:** [November 18, 2021, 11:05pm UTC](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998/20 "2021-11-18T23:05:37Z")

</div>

good you helped me out a lot thanks again. I will try all this and if im running in a problem I will post here again!

[Next page](https://crucible.hubbe.net/t/teensy-3-2-propshield-lightsaberbuild/998.md?page=2)
