#!/usr/bin/env python
# coding: utf-8
# オリジナルの作成:2015/02/15
# ## Arduino SDカードライブラリ
# SDカードシールドを作ってから、LBEDにはまだSDカードライブラリがないことに気づきました。
#
# 通常なら、LBEDは完全を目指す物では無いのでまぁいいや的になるのですが、 lbeDuinoではシールドを作成したガジェットを外に持ち運ぶことが想定されます。
#
# このような状況で記録手段がないことは大きな問題と考え、思い腰を持ち上げてArduinoのSDライブラリの 移植に取り掛かりました。
#
# この記事のみどころ?は、どうやって移植したかでは無く、どうやって動くようにしたかです。
#
# ### Arduino SDカードのマシン依存部
# 移植の元にしたのは、Arduinoアプリケーション配下の(MacOSX版で説明します)Contents/Resources/Java/libraries/SDです。
#
# このソースはとても良くできていて、SDカードのSPIの処理に関連する部分は、utility/Sd2Card.cpp, SdCard.hに凝縮されています。
#
# lbedへの移植は、Sd2Cardクラスのメンバ変数にSPIクラスの_spi変数とDigitalOutクラスのchipSelect_を追加し、初期化とspiSend, spiRec関数をlbedのSPI用に書き替えるだけです。 *1
#
# Sd2Card.hの変更点
#
# ```C++
# //#include "Sd2PinMap.h"
# #include "SdInfo.h"
# #include "lbed.h" // LBEDのヘッダをインクルード
#
#
# // コンストラクタの変更
# Sd2Card(void) : errorCode_(0), inBlock_(0), partialBlockRead_(0), type_(0),
# spi_(MOSI, MISO, SCKL), chipSelect_(D4){}
#
#
# // spiSend, spiRecの変更
# void spiSend(uint8_t b) { spi_.write((int)b); };
# uint8_t spiRec(void) { return spi_.write((int)0xFF); };
#
# // private:宣言の追加
# SPI spi_;
# DigitalOut chipSelect_;
# ```
#
# ここでは、SDカードシールドに合わせchipSelectをD4に固定としています。
# ## 失敗談
# 最初は、SPIのSCKLのピンをD10に割り当てており、SDカードの初期化に失敗していました。
#
# ここでもLabToolのプロトコルアナライザーが役に立ちました。
#
#
#
# LabToolとlbeDuinoとの接続は、以下の通りです。
#
# | LabToolピン | ケーブルの色 | 機能 | lbeDuino |
# |---|---|---|---|
# | DIO_3 | Orange | SPI-SSEL | D4 |
# | DIO_4 | Yellow | SPI-MOSI | D11 |
# | DIO_5 | Green | SPI-MISO | D12 |
# | DIO_6 | Blue | SPI_SCK | D13 |
#
# ### 初期化は規定どおり
# SDカードの処理手順は、ChaNさんの
# [MMC/SDCの使いかた](http://elm-chan.org/docs/mmc/mmc.html)
# を参考にさせて頂きました。
#
# 初期化のchipSelectがHightでSCKLを74クロック以上入れるとある部分では、80回のクロックを入れた後初期化コマンドを送っています。
#
#
# ## MBRの読込失敗
# 初期化でSDカードの情報のタイプはきちんと読み込んでいるのですが、SDカードのMBRを読み込んだ後にエラーとなってしまいます。
#
# ここでもLabToolが役立ちました。以下の画面では、0x0が続いて読み込まれており、デバッガでもその値が正しく読み取れました。
#
#
#
# このような状態ではSPIの読込が原因では無いことが明らかです。
#
# そこで、FAT関連の構造体をよく見てみると原因が隠れていました。
#
# FatStructs.hを見てみると、fat32BootSectorの構造体が以下の様に定義されています。
#
# ```C++
# struct fat32BootSector {
# /** X86 jmp to boot program */
# uint8_t jmpToBootCode[3];
# /** informational only - don't depend on it */
# char oemName[8];
# /** BIOS Parameter Block */
# bpb_t bpb;
# /** for int0x13 use value 0X80 for hard drive */
# uint8_t driveNumber;
# /** used by Windows NT - should be zero for FAT */
# uint8_t reserved1;
# /** 0X29 if next three fields are valid */
# uint8_t bootSignature;
# /** usually generated by combining date and time */
# uint32_t volumeSerialNumber;
# /** should match volume label in root dir */
# char volumeLabel[11];
# /** informational only - don't depend on it */
# char fileSystemType[8];
# /** X86 boot code */
# uint8_t bootCode[420];
# /** must be 0X55 */
# uint8_t bootSectorSig0;
# /** must be 0XAA */
# uint8_t bootSectorSig1;
# }__attribute__ ((packed));
# ```
#
# volumeSerialNumberの後に、char型でvolumeLabel[11], fileSystemType[8]と定義されています。 32bitマイコンのLPC1114では、構造体のアライメントが32bit単位となるので、volumeLabelとfileSystemTypeは連続した領域に割り当てられません。そこで、FatStructs.h内の構造体の終わりに
# ```
# __attribute__ ((packed))
# ```
# を付けてやりました。 これで何とかSDライブラリが動くようになりました。
# ### 動作確認
# Arduino勉強会/0G-lbeDuinoシールドを作るの結果を再度掲載します。
#
#
# In[ ]: