<?xml version="1.0"?>
<rss version="2.0">
   <channel>
      <title>Programming the Teensy by ykg_np</title>
      <link>https://padlet.com/ykgatnp/Teensy</link>
      <description>Training</description>
      <language>en-us</language>
      <pubDate>2017-09-06 08:09:35 UTC</pubDate>
      <lastBuildDate>2023-01-22 04:00:01 UTC</lastBuildDate>
      <webMaster>hello@padlet.com</webMaster>
      <image>
         <url>https://padlet-assets.s3.amazonaws.com/icons/Playcontrol.png</url>
      </image>
      <item>
         <title>TimeLib_snprintf</title>
         <author></author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185029790</link>
         <description><![CDATA[<div>#include &lt;TimeLib.h&gt;<br>time_t    t;<br><br>time_t getTeensy3Time() { return Teensy3Clock.get(); }<br><br>void setup() {<br>  setSyncProvider(getTeensy3Time);<br>  Serial.begin(19200);<br>}<br>// A function to print date in "dd-mm-yyyy " format<br>void printDate() {<br>  char DateStr[16]; // Buffer to store date string<br>  snprintf(DateStr, 16, "%02d-%02d-%04d ", day(t), month(t), year(t));<br>  Serial.print(DateStr);<br>}<br>// A function to print time in hh:mm:ss format with a new line<br>void printTime() {<br>  char TimeStr[16]; // Buffer to store time string<br>  snprintf(TimeStr, 16, "%02d:%02d:%02d", hour(t), minute(t), second(t));<br>  Serial.println(TimeStr);<br>}<br><br>void loop() {<br>  t = now(); // Get the time now<br>  printDate(); printTime(); delay(1000);<br>}</div>]]></description>
         <enclosure url="" />
         <pubDate>2017-09-06 08:14:51 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185029790</guid>
      </item>
      <item>
         <title>SSD1306 OLED Oins</title>
         <author>ykgatnp</author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185030021</link>
         <description><![CDATA[]]></description>
         <enclosure url="https://padletuploads.blob.core.windows.net/prod/361925/d2c587dc551b87012341dd61bd3b6a99/public.jpeg" />
         <pubDate>2017-09-06 08:16:04 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185030021</guid>
      </item>
      <item>
         <title>OLED - Simple</title>
         <author></author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185031490</link>
         <description><![CDATA[<div>#include &lt;Adafruit_SSD1306.h&gt;<br><br>#define OLED_DC     9<br>#define OLED_CS     2<br>#define OLED_RESET 14<br><br>Adafruit_SSD1306 display(OLED_DC, OLED_RESET, OLED_CS);<br><br><br>void setup() {<br><br>  display.begin(SSD1306_SWITCHCAPVCC); // Generate high voltage internally<br>  display.setTextColor(WHITE); // White text<br>}<br><br>void loop() {<br>  display.clearDisplay(); // clear internal display buffer<br>  display.setCursor(0,0);<br>  display.print("Hello");<br>  display.display();<br>  delay(1000); <br>}</div>]]></description>
         <enclosure url="" />
         <pubDate>2017-09-06 08:23:50 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185031490</guid>
      </item>
      <item>
         <title>OLED Display</title>
         <author></author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185033640</link>
         <description><![CDATA[]]></description>
         <enclosure url="https://padletuploads.blob.core.windows.net/prod/218645575/1907fcf81ea6da2619a0990582d4ef04/image.png" />
         <pubDate>2017-09-06 08:34:19 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185033640</guid>
      </item>
      <item>
         <title>Yoong HM at Github</title>
         <author>ykgatnp</author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185362749</link>
         <description><![CDATA[<div><a href="https://github.com/yoonghm/Teensy_3.x">https://github.com/yoonghm/Teensy_3.x</a></div>]]></description>
         <enclosure url="https://github.com/yoonghm/Teensy_3.x" />
         <pubDate>2017-09-07 02:23:34 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185362749</guid>
      </item>
      <item>
         <title>MTP.h</title>
         <author>ykgatnp</author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185412260</link>
         <description><![CDATA[<div>// MTP.h - Teensy MTP Responder library <br>// Copyright (C) 2017 Fredrik Hubinette &lt;hubbe@hubbe.net&gt;<br>//<br>// With updates from MichaelMC, YoongHM<br>// <br>// Permission is hereby granted, free of charge, to any person obtaining a copy<br>// of this software and associated documentation files (the "Software"), to deal<br>// in the Software without restriction, including without limitation the rights<br>// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell<br>// copies of the Software, and to permit persons to whom the Software is<br>// furnished to do so, subject to the following conditions:<br>//<br>// The above copyright notice and this permission notice shall be included in all<br>// copies or substantial portions of the Software.<br>// <br>// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR<br>// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,<br>// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE<br>// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER<br>// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,<br>// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE<br>// SOFTWARE.<br><br>#ifndef MTP_H<br>#define MTP_H<br><br>#include &lt;Arduino.h&gt;<br>// #include &lt;HardwareSerial.h&gt;<br>#include &lt;usb_dev.h&gt;<br>#include &lt;SPI.h&gt;<br>#include "SdFat.h"<br><br>SdFatSdioEX SD;<br><br>// TODO:<br>//   support multiple storages<br>//   support serialflash<br>//   partial object fetch/receive<br>//   events (notify usb host when local storage changes)<br><br>// These should probably be weak.<br>void mtp_yield() {}<br>void mtp_lock_storage(bool lock) { }<br><br>// This interface lets the MTP responder interface any storage.<br>// We'll need to give the MTP responder a pointer to one of these.<br>class MTPStorageInterface {<br>public:<br>  // Return true if this storage is read-only<br>  virtual bool readonly() = 0;<br> <br>  // Does it have directories?<br>  virtual bool has_directories() = 0;<br><br>  // Return size of storage in bytes.<br>  virtual uint64_t size() = 0;<br><br>  // Return free space in bytes.<br>  virtual uint64_t free() = 0;<br><br>  // parent = 0 means get all handles.<br>  // parent = 0xFFFFFFFF means get root folder.<br>  virtual void StartGetObjectHandles(uint32_t parent) = 0;<br>  virtual uint32_t GetNextObjectHandle() = 0;<br><br>  // Size should be 0xFFFFFFFF if it's a directory.<br>  virtual void GetObjectInfo(uint32_t handle,<br>        char* name,<br>        uint32_t* size,<br>        uint32_t* parent) = 0;<br>  virtual uint32_t GetSize(uint32_t handle) = 0;<br>  virtual void read(uint32_t handle,<br>        uint32_t pos,<br>        char* buffer,<br>        uint32_t bytes) = 0;<br>  virtual uint32_t Create(uint32_t parent,<br>        bool folder,<br>        const char* filename) = 0;<br>  virtual void write(const char* data, uint32_t size);<br>  virtual void close();<br>  virtual bool DeleteObject(uint32_t object) = 0;<br>};<br><br>// Storage implementation for SD. SD needs to be already initialized.<br>class MTPStorage_SD : public MTPStorageInterface {<br>private:<br>  File index_;<br><br>  uint8_t mode_ = 0;<br>  uint32_t open_file_ = 0xFFFFFFFEUL;<br>  File f_;<br>  uint32_t index_entries_ = 0;<br><br>  struct Record {<br>    uint32_t parent;<br>    uint32_t child;  // size stored here for files<br>    uint32_t sibling;<br>    uint8_t isdir;<br>    uint8_t scanned;<br>    char name[64];<br>  };<br><br>  bool readonly() { return false; }<br>  bool has_directories() { return true; }<br>  uint64_t size(){<br>     return (uint64_t)512 * (uint64_t)SD.clusterCount() * (uint64_t)SD.vol()-&gt;blocksPerCluster();<br>  }<br>  <br>  uint64_t free() {<br>     uint64_t volFree = SD.vol()-&gt;freeClusterCount();<br>     uint64_t ssize = (uint64_t)512 * volFree * (uint64_t)SD.vol()-&gt;blocksPerCluster();<br>     return ssize;<br>  }<br><br>  void OpenIndex() {<br>    if (index_) return;<br>    mtp_lock_storage(true);<br>    index_ = SD.open("mtpindex.dat", FILE_WRITE);<br>    mtp_lock_storage(false);<br>  }<br><br>  void WriteIndexRecord(uint32_t i, const Record&amp; r) {<br>    OpenIndex();<br>    mtp_lock_storage(true);<br>    index_.seek(sizeof(r) * i);<br>    index_.write((char*)&amp;r, sizeof(r));<br>    mtp_lock_storage(false);<br>  }<br>  <br>  uint32_t AppendIndexRecord(const Record&amp; r) {<br>    uint32_t new_record = index_entries_++;<br>    WriteIndexRecord(new_record, r);<br>    return new_record;<br>  }<br><br>  // TODO(hubbe): Cache a few records for speed.<br>  Record ReadIndexRecord(uint32_t i) {<br>    Record ret;<br>    if (i &gt; index_entries_) {<br>      memset(&amp;ret, 0, sizeof(ret));<br>      return ret;<br>    }<br>    OpenIndex();<br>    mtp_lock_storage(true);<br>    index_.seek(sizeof(ret) * i);<br>    index_.read(&amp;ret, sizeof(ret));<br>    mtp_lock_storage(false);<br>    return ret;<br>  }<br><br>  void ConstructFilename(int i, char* out) {<br>    if (i == 0) {<br>      strcpy(out, "/");<br>    } else {<br>      Record tmp = ReadIndexRecord(i);<br>      ConstructFilename(tmp.parent, out);<br>      if (out[strlen(out)-1] != '/')<br>        strcat(out, "/");<br>      strcat(out, tmp.name);<br>    }<br>  }<br><br>  void OpenFileByIndex(uint32_t i, uint8_t mode = O_RDONLY) {<br>    if (open_file_ == i &amp;&amp; mode_ == mode)<br>      return;<br>    char filename[256];<br>    ConstructFilename(i, filename);<br>    mtp_lock_storage(true);<br>    f_.close();<br>    f_ = SD.open(filename, mode);<br>    open_file_ = i;<br>    mode_ = mode;<br>    mtp_lock_storage(false);<br>  }<br><br>  // MTP object handles should not change or be re-used during a session.<br>  // This would be easy if we could just have a list of all files in memory.<br>  // Since our RAM is limited, we'll keep the index in a file instead.<br>  bool index_generated = false;<br>  void GenerateIndex() {<br>    if (index_generated) return;<br>    index_generated = true;<br><br>    mtp_lock_storage(true);<br>    SD.remove("mtpindex.dat");<br>    mtp_lock_storage(false);<br>    index_entries_ = 0;<br><br>    Record r;<br>    r.parent = 0;<br>    r.sibling = 0;<br>    r.child = 0;<br>    r.isdir = true;<br>    r.scanned = false;<br>    strcpy(r.name, "/");<br>    AppendIndexRecord(r);<br>  }<br><br>  void ScanDir(uint32_t i) {<br>    Record record = ReadIndexRecord(i);<br>    if (record.isdir &amp;&amp; !record.scanned) {<br>      OpenFileByIndex(i);<br>      if (!f_) return;<br>      int sibling = 0;<br>      while (true) {<br>        mtp_lock_storage(true);<br>        File child = f_.openNextFile();<br>        mtp_lock_storage(false);<br><br>        if (!child) break;<br><br>        Record r;<br>        r.parent = i;<br>        r.sibling = sibling;<br>        r.isdir = child.isDirectory();<br>        r.child = r.isdir ? 0 : child.size();<br>        r.scanned = false;<br>        child.getName(r.name, 64);<br>        sibling = AppendIndexRecord(r);<br>        child.close();<br>      }<br>      record.scanned = true;<br>      record.child = sibling;<br>      WriteIndexRecord(i, record);<br>    }<br>  }<br><br>  bool all_scanned_ = false;<br>  void ScanAll() {<br>    if (all_scanned_) return;<br>    all_scanned_ = true;<br><br>    GenerateIndex();<br>    for (uint32_t i = 0; i &lt; index_entries_; i++) {<br>      ScanDir(i);<br>    }<br>  }<br><br>  uint32_t next_;<br>  bool follow_sibling_;<br>  void StartGetObjectHandles(uint32_t parent) override {<br>    GenerateIndex();<br>    if (parent) {<br>      if (parent == 0xFFFFFFFF) parent = 0;<br><br>      ScanDir(parent);<br>      follow_sibling_ = true;<br>      // Root folder?<br>      next_ = ReadIndexRecord(parent).child;<br>    } else {<br>      ScanAll();<br>      follow_sibling_ = false;<br>      next_ = 1;<br>    }<br>  }<br><br>  uint32_t GetNextObjectHandle() override {<br>    while (true) {<br>      if (next_ == 0) return 0;<br><br>      int ret = next_;<br>      Record r = ReadIndexRecord(ret);<br>      if (follow_sibling_) {<br>        next_ = r.sibling;<br>      } else {<br>        next_++;<br>        if (next_ &gt;= index_entries_)<br>          next_ = 0;<br>      }<br>      if (r.name[0]) return ret;<br>    }<br>  }<br><br>  void GetObjectInfo(uint32_t handle,<br>        char* name,<br>        uint32_t* size,<br>        uint32_t* parent) override {<br>    Record r = ReadIndexRecord(handle);<br>    strcpy(name, r.name);<br>    *parent = r.parent;<br>    *size = r.isdir ? 0xFFFFFFFFUL : r.child;<br>  }<br><br>  uint32_t GetSize(uint32_t handle) {<br>    return ReadIndexRecord(handle).child;<br>  }<br><br>  void read(uint32_t handle,<br>        uint32_t pos,<br>        char* out,<br>        uint32_t bytes) override {<br>    OpenFileByIndex(handle);<br>    mtp_lock_storage(true);<br>    f_.seek(pos);<br>    f_.read(out, bytes);<br>    mtp_lock_storage(false);<br>  }<br><br>  bool DeleteObject(uint32_t object) override {<br>    char filename[256];<br>    Record r;<br>    while (true) {<br>      r = ReadIndexRecord(object == 0xFFFFFFFFUL ? 0 : object);<br>      if (!r.isdir) break;<br>      if (!r.child) break;<br>      if (!DeleteObject(r.child))<br>        return false;<br>    }<br><br>    // We can't actually delete the root folder,<br>    // but if we deleted everything else, return true.<br>    if (object == 0xFFFFFFFFUL) return true;<br><br>    ConstructFilename(object, filename);<br>    bool success;<br>    mtp_lock_storage(true);<br>    if (r.isdir) {<br>      success = SD.rmdir(filename);<br>    } else {<br>      success = SD.remove(filename);<br>    }<br>    mtp_lock_storage(false);<br>    if (!success) return false;<br>    r.name[0] = 0;<br>    int p = r.parent;<br>    WriteIndexRecord(object, r);<br>    Record tmp = ReadIndexRecord(p);<br>    if (tmp.child == object) {<br>      tmp.child = r.sibling;<br>      WriteIndexRecord(p, tmp);<br>    } else {<br>      int c = tmp.child;<br>      while (c) {<br>  tmp = ReadIndexRecord(c);<br>  if (tmp.sibling == object) {<br>    tmp.sibling = r.sibling;<br>    WriteIndexRecord(c, tmp);<br>    break;<br>  } else {<br>    c = tmp.sibling;<br>  }<br>      }<br>    }<br>    return true;<br>  }<br><br>  uint32_t Create(uint32_t parent,<br>      bool folder,<br>      const char* filename) override {<br>    uint32_t ret;<br>    if (parent == 0xFFFFFFFFUL) parent = 0;<br>    Record p = ReadIndexRecord(parent);<br>    Record r;<br>    if (strlen(filename) &gt; 62) return 0;<br>    strcpy(r.name, filename);<br>    r.parent = parent;<br>    r.child = 0;<br>    r.sibling = p.child;<br>    r.isdir = folder;<br>    // New folder is empty, scanned = true.<br>    r.scanned = 1;<br>    ret = p.child = AppendIndexRecord(r);<br>    WriteIndexRecord(parent, p);<br>    if (folder) {<br>      char filename[256];<br>      ConstructFilename(ret, filename);<br>      mtp_lock_storage(true);<br>      SD.mkdir(filename);<br>      mtp_lock_storage(false);<br>    } else {<br>      OpenFileByIndex(ret, FILE_WRITE);<br>    }<br>    return ret;<br>  }<br><br>  void write(const char* data, uint32_t bytes) override {<br>    mtp_lock_storage(true);<br>    f_.write(data, bytes);<br>    mtp_lock_storage(false);<br>  }<br><br>  void close() override {<br>    mtp_lock_storage(true);<br>    uint64_t size = f_.size();<br>    f_.close();<br>    mtp_lock_storage(false);<br>    Record r = ReadIndexRecord(open_file_);<br>    r.child = size;<br>    WriteIndexRecord(open_file_, r);<br>    open_file_ = 0xFFFFFFFEUL;<br>  }<br>};<br><br>// MTP Responder.<br>class MTPD {<br>public:<br>  explicit MTPD(MTPStorageInterface* storage) : storage_(storage) {}<br><br>private:<br>  MTPStorageInterface* storage_;<br><br>  struct MTPHeader {<br>    uint32_t len;  // 0<br>    uint16_t type; // 4<br>    uint16_t op;   // 6<br>    uint32_t transaction_id; // 8<br>  };<br><br>  struct MTPContainer {<br>    uint32_t len;  // 0<br>    uint16_t type; // 4<br>    uint16_t op;   // 6<br>    uint32_t transaction_id; // 8<br>    uint32_t params[5];    // 12<br>  };<br><br>  void PrintPacket(const usb_packet_t *x) {<br>#if 0<br>    for (int i = 0; i &lt; x-&gt;len; i++) {<br>      Serial1.print("0123456789ABCDEF"[x-&gt;buf[i] &gt;&gt; 4]);<br>      Serial1.print("0123456789ABCDEF"[x-&gt;buf[i] &amp; 0xf]);<br>      if ((i &amp; 3) == 3) Serial1.print(" ");<br>    } <br>    Serial1.println("");<br>#endif<br>#if 0<br>    MTPContainer *tmp = (struct MTPContainer*)(x-&gt;buf);<br>    Serial1.print(" len = ");<br>    Serial1.print(tmp-&gt;len, HEX);<br>    Serial1.print(" type = ");<br>    Serial1.print(tmp-&gt;type, HEX);<br>    Serial1.print(" op = ");<br>    Serial1.print(tmp-&gt;op, HEX);<br>    Serial1.print(" transaction_id = ");<br>    Serial1.print(tmp-&gt;transaction_id, HEX);<br>    for (int i = 0; i * 4 &lt; x-&gt;len - 12; i ++) {<br>      Serial1.print(" p");<br>      Serial1.print(i);<br>      Serial1.print(" = ");<br>      Serial1.print(tmp-&gt;params[i], HEX);<br>    }<br>    Serial1.println("");<br>#endif<br>  }<br><br>  usb_packet_t *data_buffer_ = NULL;<br>  void get_buffer() {<br>    while (!data_buffer_) {<br>      data_buffer_ = usb_malloc();<br>      if (!data_buffer_) mtp_yield();<br>    }<br>  }<br><br>  void receive_buffer() {<br>    while (!data_buffer_) {<br>      data_buffer_ = usb_rx(MTP_RX_ENDPOINT);<br>      if (!data_buffer_) mtp_yield();<br>    }<br>  }<br><br>  bool write_get_length_ = false;<br>  uint32_t write_length_ = 0;<br>  void write(const char *data, int len) {<br>    if (write_get_length_) {<br>      write_length_ += len;<br>    } else {<br>      int pos = 0;<br>      while (pos &lt; len) {<br>        get_buffer();<br>        int avail = sizeof(data_buffer_-&gt;buf) - data_buffer_-&gt;len;<br>        int to_copy = min(len - pos, avail);<br>        memcpy(data_buffer_-&gt;buf + data_buffer_-&gt;len,<br>               data + pos,<br>               to_copy);<br>        data_buffer_-&gt;len += to_copy;<br>        pos += to_copy;<br>        if (data_buffer_-&gt;len == sizeof(data_buffer_-&gt;buf)) {<br>          usb_tx(MTP_TX_ENDPOINT, data_buffer_);<br>          data_buffer_ = NULL;<br>          // Serial1.println("SENT...");<br>        }<br>      }<br>    }<br>  }<br>  <br>  void write8 (uint8_t  x) { write((char*)&amp;x, sizeof(x)); }<br><br>  void write16(uint16_t x) { write((char*)&amp;x, sizeof(x)); }<br>  <br>  void write32(uint32_t x) { write((char*)&amp;x, sizeof(x)); }<br>  <br>  void write64(uint64_t x) { write((char*)&amp;x, sizeof(x)); }<br>  <br>  void writestring(const char* str) {<br>    if (*str) {<br>      write8(strlen(str) + 1);<br>      while (*str) {<br>        write16(*str);<br>        ++str;<br>      }<br>      write16(0);<br>    } else {<br>      write8(0);<br>    }<br>  }<br><br>  void WriteDescriptor() {<br>    write16(100);  // MTP version<br>    write32(6);    // MTP extension<br>//    write32(0xFFFFFFFFUL);    // MTP extension<br>    write16(100);  // MTP version<br>    writestring("microsoft.com: 1.0;");<br>    write16(0);    // functional mode<br><br>    // Supported operations (array of uint16)<br>    write32(14);<br>    write16(0x1001);  // GetDeviceInfo<br>    write16(0x1002);  // OpenSession<br>    write16(0x1003);  // CloseSession<br>    write16(0x1004);  // GetStorageIDs<br><br>    write16(0x1005);  // GetStorageInfo<br>    write16(0x1006);  // GetNumObjects<br>    write16(0x1007);  // GetObjectHandles<br>    write16(0x1008);  // GetObjectInfo<br><br>    write16(0x1009);  // GetObject<br>    write16(0x100B);  // DeleteObject<br>    write16(0x100C);  // SendObjectInfo<br>    write16(0x100D);  // SendObject<br><br>    write16(0x1014);  // GetDevicePropDesc<br>    write16(0x1015);  // GetDevicePropValue<br><br>//    write16(0x1010);  // Reset<br>//    write16(0x1019);  // MoveObject<br>//    write16(0x101A);  // CopyObject<br><br>    write32(0);       // Events (array of uint16)<br><br>    write32(1);       // Device properties (array of uint16)<br>    write16(0xd402);  // Device friendly name<br><br>    write32(0);       // Capture formats (array of uint16)<br><br>    write32(2);       // Playback formats (array of uint16)<br>    write16(0x3000);  // Undefined format<br>    write16(0x3001);  // Folders (associations)<br><br>    writestring("PJRC");     // Manufacturer<br>    writestring("Teensy");   // Model<br>    writestring("1.0");      // version<br>    writestring("???");      // serial<br>  }<br><br>  void WriteStorageIDs() {<br>    write32(1); // 1 entry<br>    write32(1); // 1 storage<br>  }<br><br>  void GetStorageInfo(uint32_t storage) {<br>    write16(storage_-&gt;readonly() ? 0x0001 : 0x0004);   // storage type (removable RAM)<br>    write16(storage_-&gt;has_directories() ? 0x0002: 0x0001);   // filesystem type (generic hierarchical)<br>    write16(0x0000);   // access capability (read-write)<br>    write64(storage_-&gt;size());  // max capacity<br>    write64(storage_-&gt;free());  // free space (100M)<br>    write32(0xFFFFFFFFUL);  // free space (objects)<br>    writestring("SD Card");  // storage descriptor<br>    writestring("");  // volume identifier<br>  }<br><br>  uint32_t GetNumObjects(uint32_t storage,<br>       uint32_t parent) {<br>    storage_-&gt;StartGetObjectHandles(parent);<br>    int num = 0;<br>    while (storage_-&gt;GetNextObjectHandle()) num++;<br>    return num;<br>  }<br><br>  void GetObjectHandles(uint32_t storage,<br>      uint32_t parent) {<br>    uint32_t num = 0;<br>    if (!write_get_length_) {<br>      num = GetNumObjects(storage, parent);<br>    }<br>    write32(num);<br>    int handle;<br>    storage_-&gt;StartGetObjectHandles(parent);<br>    while ((handle = storage_-&gt;GetNextObjectHandle()))<br>      write32(handle);<br>  }<br><br>  void GetObjectInfo(uint32_t handle) {<br>    char filename[256];<br>    uint32_t size, parent;<br>    storage_-&gt;GetObjectInfo(handle, filename, &amp;size, &amp;parent);<br><br>    write32(1); // storage<br>    write16(size == 0xFFFFFFFFUL ? 0x3001 : 0x0000); // format<br>    write16(0);  // protection<br>    write32(size); // size<br>    write16(0); // thumb format<br>    write32(0); // thumb size<br>    write32(0); // thumb width<br>    write32(0); // thumb height<br>    write32(0); // pix width<br>    write32(0); // pix height<br>    write32(0); // bit depth<br>    write32(parent); // parent<br>    write16(size == 0xFFFFFFFFUL ? 1 : 0); // association type<br>    write32(0); // association description<br>    write32(0);  // sequence number<br>    writestring(filename);<br>    writestring("");  // date created<br>    writestring("");  // date modified<br>    writestring("");  // keywords<br>  }<br><br>  void GetObject(uint32_t object_id) {<br>    uint32_t size = storage_-&gt;GetSize(object_id);<br>    if (write_get_length_) {<br>      write_length_ += size;<br>    } else {<br>      uint32_t pos = 0;<br>      while (pos &lt; size) {<br>        get_buffer();<br>        uint32_t avail = sizeof(data_buffer_-&gt;buf) - data_buffer_-&gt;len;<br>        uint32_t to_copy = min(pos - size, avail);<br>        // Read directly from storage into usb buffer.<br>        storage_-&gt;read(object_id, pos,<br>                    (char*)(data_buffer_-&gt;buf + data_buffer_-&gt;len), <br>                    to_copy);<br>        pos += to_copy;<br>        data_buffer_-&gt;len += to_copy;<br>        if (data_buffer_-&gt;len == sizeof(data_buffer_-&gt;buf)) {<br>          usb_tx(MTP_TX_ENDPOINT, data_buffer_);<br>          data_buffer_ = NULL;<br>        }<br>      }<br>    }<br>  }<br><br>inline MTPContainer *contains (usb_packet_t *receive_buffer){<br>  return (MTPContainer*)(receive_buffer-&gt;buf);<br>}<br>#define CONTAINER contains(receive_buffer)<br><br>#define TRANSMIT(FUN) do {                              \<br>    write_length_ = 0;                                  \<br>    write_get_length_ = true;                           \<br>    FUN;                                                \<br>    write_get_length_ = false;                          \<br>    MTPHeader header;                                   \<br>    header.len = write_length_ + 12;                    \<br>    header.type = 2;                                    \<br>    header.op = CONTAINER-&gt;op;                          \<br>    header.transaction_id = CONTAINER-&gt;transaction_id;  \<br>    write((char *)&amp;header, sizeof(header));             \<br>    FUN;                                                \<br>    get_buffer();                                       \<br>    usb_tx(MTP_TX_ENDPOINT, data_buffer_);              \<br>    data_buffer_ = NULL;                                \<br>  } while(0)<br>  <br>  void read(char* data, uint32_t size) {<br>    while (size) {<br>      receive_buffer();<br>      uint32_t to_copy = data_buffer_-&gt;len - data_buffer_-&gt;index;<br>      to_copy = min(to_copy, size);<br>      if (data) {<br>        memcpy(data, data_buffer_-&gt;buf + data_buffer_-&gt;index, to_copy);<br>        data += to_copy;<br>      }<br>      size -= to_copy;<br>      data_buffer_-&gt;index += to_copy;<br>      if (data_buffer_-&gt;index == data_buffer_-&gt;len) {<br>        usb_free(data_buffer_);<br>        data_buffer_ = NULL;<br>      }<br>    }<br>  }<br><br>  uint32_t ReadMTPHeader() {<br>    MTPHeader header;<br>    read((char *)&amp;header, sizeof(MTPHeader));<br>    // check that the type is data<br>    return header.len - 12;<br>  }<br><br>  uint8_t read8() {<br>    uint8_t ret;<br>    read((char*)&amp;ret, sizeof(ret));<br>    return ret;<br>  }<br><br>  uint16_t read16() {<br>    uint16_t ret;<br>    read((char*)&amp;ret, sizeof(ret));<br>    return ret;<br>  }<br><br>  uint32_t read32() {<br>    uint32_t ret;<br>    read((char*)&amp;ret, sizeof(ret));<br>    return ret;<br>  }<br><br>  void readstring(char* buffer) {<br>    int len = read8();<br>    if (!buffer) {<br>      read(NULL, len * 2);<br>    } else {<br>      for (int i = 0; i &lt; len; i++) {<br>        *(buffer++) = read16();<br>      }<br>    }<br>  }<br><br>  void read_until_short_packet() {<br>    bool done = false;<br>    while (!done) {<br>      receive_buffer();<br>      done = data_buffer_-&gt;len != sizeof(data_buffer_-&gt;buf);<br>      usb_free(data_buffer_);<br>      data_buffer_ = NULL;<br>    }<br>  }<br><br>  uint32_t SendObjectInfo(uint32_t storage, uint32_t parent) {<br>    ReadMTPHeader();<br>    char filename[256];<br><br>    read32(); // storage<br>    bool dir = read16() == 0x3001; // format<br>    read16();  // protection<br>    read32(); // size<br>    read16(); // thumb format<br>    read32(); // thumb size<br>    read32(); // thumb width<br>    read32(); // thumb height<br>    read32(); // pix width<br>    read32(); // pix height<br>    read32(); // bit depth<br>    read32(); // parent<br>    read16(); // association type<br>    read32(); // association description<br>    read32(); // sequence number<br><br>    readstring(filename);<br>    read_until_short_packet();  // ignores dates &amp; keywords<br>    return storage_-&gt;Create(parent, dir, filename);<br>  }<br><br>  void SendObject() {<br>    uint32_t len = ReadMTPHeader();<br>    while (len) {<br>      receive_buffer();<br>      uint32_t to_copy = data_buffer_-&gt;len - data_buffer_-&gt;index;<br>      to_copy = min(to_copy, len);<br>      storage_-&gt;write((char*)(data_buffer_-&gt;buf + data_buffer_-&gt;index),<br>                    to_copy);<br>      data_buffer_-&gt;index += to_copy;<br>      len -= to_copy;<br>      if (data_buffer_-&gt;index == data_buffer_-&gt;len) {<br>        usb_free(data_buffer_);<br>        data_buffer_ = NULL;<br>      }<br>    }<br>    storage_-&gt;close();<br>  }<br><br>  void GetDevicePropValue(uint32_t prop) {<br>    switch (prop) {<br>      case 0xd402: // friendly name<br>        // This is the name we'll actually see in the windows explorer.<br>        // Should probably be configurable.<br>        writestring("Teensy");<br>        break;<br>    }<br>  }<br><br>  void GetDevicePropDesc(uint32_t prop) {<br>    switch (prop) {<br>      case 0xd402: // friendly name<br>        write16(prop);<br>        write16(0xFFFF); // string type<br>        write8(0);       // read-only<br>        GetDevicePropValue(prop);<br>        GetDevicePropValue(prop);<br>        write8(0);       // no form<br>    }<br>  }<br><br>public:<br>  void loop() {<br>    usb_packet_t *receive_buffer;<br>    if ((receive_buffer = usb_rx(MTP_RX_ENDPOINT))) {<br>      PrintPacket(receive_buffer);<br>      uint32_t return_code = 0;<br>      uint32_t p1 = 0;<br>      if (receive_buffer-&gt;len &gt;= 12) {<br>        return_code = 0x2001;  // Ok<br>        receive_buffer-&gt;len = 16;<br>        if (CONTAINER-&gt;type == 1) { // command<br>          switch (CONTAINER-&gt;op) {<br>            case 0x1001: // GetDescription<br>              TRANSMIT(WriteDescriptor());<br>              break;<br>            case 0x1002:  // OpenSession<br>              break;<br>            case 0x1003:  // CloseSession<br>              break;<br>            case 0x1004:  // GetStorageIDs<br>              TRANSMIT(WriteStorageIDs());<br>              break;<br>            case 0x1005:  // GetStorageInfo<br>              TRANSMIT(GetStorageInfo(CONTAINER-&gt;params[0]));<br>              break;<br>            case 0x1006:  // GetNumObjects<br>              if (CONTAINER-&gt;params[1]) {<br>                return_code = 0x2014; // spec by format unsupported<br>              } else {<br>                p1 = GetNumObjects(CONTAINER-&gt;params[0],<br>                CONTAINER-&gt;params[2]);<br>              }<br>              break;<br>            case 0x1007:  // GetObjectHandles<br>              if (CONTAINER-&gt;params[1]) {<br>                return_code = 0x2014; // spec by format unsupported<br>              } else {<br>                TRANSMIT(GetObjectHandles(CONTAINER-&gt;params[0],<br>                CONTAINER-&gt;params[2]));<br>              }<br>              break;<br>            case 0x1008:  // GetObjectInfo<br>              TRANSMIT(GetObjectInfo(CONTAINER-&gt;params[0]));<br>              break;<br>            case 0x1009:  // GetObject<br>              TRANSMIT(GetObject(CONTAINER-&gt;params[0]));<br>              break;<br>            case 0x100B:  // DeleteObject<br>              if (CONTAINER-&gt;params[1]) {<br>                return_code = 0x2014; // spec by format unsupported<br>              } else {<br>                if (!storage_-&gt;DeleteObject(CONTAINER-&gt;params[0])) {<br>                  return_code = 0x2012; // partial deletion<br>                }<br>              }<br>              break;<br>            case 0x100C:  // SendObjectInfo<br>              CONTAINER-&gt;params[2] =<br>                  SendObjectInfo(CONTAINER-&gt;params[0], // storage<br>                                 CONTAINER-&gt;params[1]); // parent<br>                  p1 = CONTAINER-&gt;params[0];<br>              if (!p1) p1 = 1;<br>              CONTAINER-&gt;len = receive_buffer-&gt;len = 12 + 3 * 4;<br>              break;<br>            case 0x100D:  // SendObject<br>              SendObject();<br>              break;<br>            case 0x1014:  // GetDevicePropDesc<br>              TRANSMIT(GetDevicePropDesc(CONTAINER-&gt;params[0]));<br>              break;<br>            case 0x1015:  // GetDevicePropvalue<br>              TRANSMIT(GetDevicePropValue(CONTAINER-&gt;params[0]));<br>              break;<br>            default:<br>              return_code = 0x2005;  // operation not supported<br>              break;<br>          }<br>        } else {<br>          return_code = 0x2000;  // undefined<br>        }<br>      }<br>      if (return_code) {<br>        CONTAINER-&gt;type = 3;<br>        CONTAINER-&gt;op = return_code;<br>        CONTAINER-&gt;params[0] = p1;<br>        PrintPacket(receive_buffer);<br>        usb_tx(MTP_TX_ENDPOINT, receive_buffer);<br>        receive_buffer = 0;<br>      } else {<br>          usb_free(receive_buffer);<br>      }<br>    }<br>    // Maybe put event handling inside mtp_yield()?<br>    if ((receive_buffer = usb_rx(MTP_EVENT_ENDPOINT))) {<br>      usb_free(receive_buffer);<br>    }<br>  }<br>};<br><br>#endif</div>]]></description>
         <enclosure url="" />
         <pubDate>2017-09-07 08:13:53 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185412260</guid>
      </item>
      <item>
         <title>MTP_Blinky</title>
         <author>ykgatnp</author>
         <link>https://padlet.com/ykgatnp/Teensy/wish/185412822</link>
         <description><![CDATA[<div>/*<br>&nbsp; This example demonstrates MTP with blinky using systick interrupt.<br><br>&nbsp; This example tests MTP and SdFat<br>*/<br><br><br>#include &lt;MTP.h&gt;<br><br>MTPStorage_SD storage;<br>MTPD mtpd(&amp;storage);<br><br>volatile int status = 0;<br>/*<br>void systick_isr() {<br>&nbsp; systick_millis_count++; &nbsp; // Original ISR code<br>&nbsp; if (systick_millis_count % 1000 == 0) {<br>&nbsp; &nbsp; digitalWrite(LED_BUILTIN, status);<br>&nbsp; &nbsp; status = !status;<br>&nbsp; }<br>}<br>*/<br>void setup() {<br>&nbsp; pinMode(LED_BUILTIN, OUTPUT);<br><br>&nbsp; if (SD.begin()) {<br>&nbsp; &nbsp; Serial.println("SD found");<br>&nbsp; } else {<br>&nbsp; &nbsp; Serial.println("SD not found");<br>&nbsp; }<br>}<br><br>void loop() {<br>&nbsp; mtpd.loop();<br>}</div>]]></description>
         <enclosure url="" />
         <pubDate>2017-09-07 08:17:54 UTC</pubDate>
         <guid>https://padlet.com/ykgatnp/Teensy/wish/185412822</guid>
      </item>
   </channel>
</rss>
