GR-PEACH Digital Signage sample.

Dependencies:   Display_shield_config GR-PEACH_video GraphicsFramework LCD_shield_config R_BSP SDBlockDevice_GR_PEACH USBHost_custom scan_folder

Information

Japanese version is available in lower part of this page.
このページの後半に日本語版が用意されています.



What is this ?

This example is decording JPEG files in onboard flash memory using the GR-PEACH hardware decoders. You can easily operate the screen with your fingers or USB mouse. When micro SD card or USB memory is detected, the sample will show JPEG giles on the deteted filesystem.
After displaying a certain period of time, to display the next JPEG file. JPEG files will be enlarged / reduced in accordance with the image resolution to be output to the display. For this reason, the JPEG file resolution is most clearly displayed when the same as the resolution of the display output. Display order of the JPEG file is a directory analyze order. Please write the JPEG file to the memory in the order you want to display.

/media/uploads/dkato/digital_signage_1.jpg

Supported JPEG image

The location of the fileThe depth of the folder is to 8 hierarchies.
Extension".jpg" , ".JPG"
Resolution restrictionUpper limit 1280 x 800 Pixel. MCU unit.
The size upper limit450Kbyte
The formatJPEG baseline. (Optimization and progressive are not supported.)


Touch panel operation

The following operation is possible by a touch panel.

operationwork
Left flickThe next JPEG file is indicated.
(In the case of "SCROLL_DIRECTION=1", the previous JPEG file is indicated.)
Right flickThe previous JPEG file is indicated.
(In the case of "SCROLL_DIRECTION=1", the next JPEG file is indicated.)
Pinch outEnlarge the image.
Pinch inReduced the image.
Double tapReturn the image to its original size.


Mouse operation

The following operation is possible by a usb mouse.

operationwork
Left clickhe next JPEG file is indicated.
Right clickThe previous JPEG file is indicated.
Center click
(Center wheel push)
Mouse pointer display. While a mouse pointer is being indicated, automatic page turning isn't done.
Center wheelWhen a mouse pointer is indicated:Enlarge / Reduced the image.
When a mouse pointer is not indicated:The automatic page turning interval is changed.

The USB mouse which functions by the following sample can be used.
https://developer.mbed.org/handbook/USBHostMouse

Function settings

The function setting can be changed by the following macro.

main.cpp

/**** User Selection *********/
#define WAIT_TIME                           (10000) /* wait time (ms) 0:infinite */
#define DISSOLVE_STEP_NUM                   (16)    /* minimum 1 */
#define SCROLL_STEP_NUM                     (8)     /* minimum 1 */
#define SCROLL_DIRECTION                    (-1)    /* Select 1(left to right) or -1(right to left) */
/** LCD setting **/
#define LCD_TYPE                            (0)     /* Select 0(4.3inch) , 1(7.1inch), 2(Display shield) or 3(RSK TFT) */
/*****************************/


WAIT_TIMEThe automatic page turning interval is changed. The unit is ms.
The center wheel of USB mouse or USER_BUTTON0 can be changed.
DISSOLVE_STEP_NUMThe effect amount at automatic page turning is set. The minimum value is 1.
SCROLL_STEP_NUMThe effect amount at manual page turning is set. The minimum value is 1.
SCROLL_DIRECTIONThe scrolling direction at manual page turning is set. 1:left to right. -1:right to left.
LCD_TYPEType of LCD. 0:GR-PEACH 4.3 inch LCD Shield. 1:GR-PEACH 7.1 inch LCD Shield. 2:DISPLAY SHIELD(Not for sale).3:RSK TFT.
When using the DISPLAY SHIELD, you need to close the JP3, JP8, JP9, JP10 and JP11. For more details, see here.


Constitution

GR-PEACH, micro SD card or USB memory, USB mouse(If you want to mouse operation), USB HUB(If you use both USB memory and USB mouse), LCD Shield
You need to close the JP3 when using USB.. /media/uploads/RyoheiHagimoto/usb.jpg

Examples of creating images that conform to the JPEG baseline using the GIMP

In this sample, you can display only JPEG files that conform to the JPEG baseline.
Please try the following steps if there is a JPEG file that can not be displayed.

  1. Install picture edit tool GIMP
  2. Open an image file in GIMP.
    1. Right-click on the image file.
    2. Choose "Edit with GIMP".
  3. Change the picture size
    1. "Image" -> "Scale Image"
  4. Save it by the JPEG form.
    1. "File" -> "Export As..."
    2. Choose the save places.(The file extension ".jpg".)
    3. Click on the "Export".
    4. Click on "+Advanced Options".
    5. Remove the check of the "Progressive" and "Optimize".
    6. Click on "Export". (Attention: When the output size exceeds 450Kbyte, please adjust the quality value.)


概要

オンボードフラッシュメモリに書き込まれたJPEGファイルをGR-PEACHのハードウエアでデコードしています。 表示画面はタッチパネルやUSBマウスで操作することができます。 micro SDカード、または、USBメモリを接続すると、ファイルシステム上のJPEGファイルを表示します。
一定時間表示(時間の変更可)すると次のJPEGファイルを表示します。 JPEGファイルはディスプレイに出力する画像解像度にあわせて拡大/縮小されます。そのため、JPEGファイルはディスプレイ出力に近い解像度のほうが鮮明に表示されます。 JPEGファイルの表示順はディレクトリ解析順です。表示したい順にJPEGファイルを1ファイルずつUSBメモリに書き込んでください。

/media/uploads/dkato/digital_signage_1.jpg

表示可能なJPEGファイル

ファイル位置フォルダの深さはルートフォルダを含め8階層まで。
ファイル名半角英数字 (全角には対応していません)
拡張子".jpg" , ".JPG"
解像度制限上限1280 x 800 ピクセル。MCU単位のサイズ。
サイズ上限450Kbyte
フォーマットJPEGベースラインに準拠 (最適化、および、プログレッシブには対応していません)


タッチパネル操作

LCD上のタッチパネルにて、以下の操作が可能です。

操作動作
左フリック次のJPEGファイルを表示します。
(SCROLL_DIRECTION=1時は一つ前のJPEGファイルを表示します。)
右フリック一つ前のJPEGファイルを表示します。
(SCROLL_DIRECTION=1時は次のJPEGファイルを表示します。)
ピンチアウト画面を拡大します。
ピンチイン拡大した画面を縮小します。
ダブルタップ拡大中に、素早く画面を2回タップすると元のサイズに戻します。


マウス操作

USBマウスを接続することで、以下の操作が可能です。

操作動作
左クリック次のJPEGファイルを表示します。
右クリック一つ前のJPEGファイルを表示します。
センタークリック
(センターホイール押し込み)
マウスポインタ表示。マウスポインタ表示中は時間経過による次ファイル遷移は行いません。
センターホイールマウスポインタ表示中:画面の拡大/縮小。
マウスポインタ非表示中:JPEGファイルの表示する時間を変更。

一部使用できないUSBマウスがあります。使用可能なUSBマウスは下記サンプルで動作するデバイスのみです。
https://developer.mbed.org/handbook/USBHostMouse

機能設定

下記のマクロを変更することで、一部機能を変更できます。

main.cpp

/**** User Selection *********/
#define WAIT_TIME                           (10000) /* wait time (ms) 0:infinite */
#define DISSOLVE_STEP_NUM                   (16)    /* minimum 1 */
#define SCROLL_STEP_NUM                     (8)     /* minimum 1 */
#define SCROLL_DIRECTION                    (-1)    /* Select 1(left to right) or -1(right to left) */
/** LCD setting **/
#define LCD_TYPE                            (0)    /* Select 0(4.3inch) , 1(7.1inch), 2(Display shield) or 3(RSK TFT) */
/*****************************/


WAIT_TIME一つのJPEGファイルを表示する時間(デフォルト値)を設定します。単位はmsです。
動作後はUSER_BUTTON0、または、マウスのホイールで表示時間を変更できます。
DISSOLVE_STEP_NUM時間経過によって表示が変わる際のDISSOLVEエフェクトの長さを設定します。設定可能な最小値は1です。
SCROLL_STEP_NUM画面遷移時のスクロールエフェクトの長さを設定します。設定可能な最小値は1です。
SCROLL_DIRECTION次画面遷移時のスクロール方向を設定します。1を設定すると左から右へスクロール、-1を設定すると右から左へスクロールします。
LCD_TYPE0を設定するとGR-PEACH 4.3 inch LCD Shield、1を設定するとGR-PEACH 7.1 inch LCD Shield、2を設定するとDISPLAY SHIELD(非売品)、3を設定するとRSKボード用TFTの設定となります。
DISPLAY SHIELDを使用する際は、GR-PEACHのJP3、JP8、JP9、JP10、JP11をショートする必要があります。Jumper位置についてはこちらを参照ください。


構成

GR-PEACH、micro SDカード または USBメモリ、USBマウス(マウス操作を行わない場合は不要)、USB HUB(USBメモリとUSBマウスを両方使用する場合)、LCD Shield。
USBを使用する際はJP3をショートする必要があります。 /media/uploads/RyoheiHagimoto/usb.jpg

GIMPを使ったJPEGベースラインに準拠 したJPEGファイルの作成例

このサンプルでは、JPEGベースラインに準拠したJPEGファイルのみ表示可能です。
表示できないJPEGファイルがある場合は以下の手順をお試しください。

  1. 画像編集ツールGIMPをインストールする
  2. GIMPで画像ファイルを開く
    1. 画像ファイル上で右クリック
    2. Edit with GIMPを選択
  3. 画像サイズを変更する
    1. 「画像」→「画像の拡大・縮小」を選んで、画像の拡大・縮小ダイアログをから変更する
  4. JPEG形式で保存
    1. 「ファイル」→「名前をつけてエクスポート」で保存ダイアログを表示
    2. 保存先フォルダを選択 (ファイルの拡張子は.jpg)
    3. 「エクスポート」をクリックし、エクスポートダイアログを表示
    4. 「+詳細設定」の「+」部分をクリックして詳細設定画面を表示
    5. 「最適化」と「プログレッシブ」のチェックを外す
    6. エクスポートボタンを押す (注意:出力サイズが450Kbyteを超える場合は、品質値を調整して下さい。)
Committer:
dkato
Date:
Thu Jul 28 09:07:23 2016 +0000
Revision:
0:2156833a74a8
first commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
dkato 0:2156833a74a8 1 /* mbed Microcontroller Library
dkato 0:2156833a74a8 2 * Copyright (c) 2006-2012 ARM Limited
dkato 0:2156833a74a8 3 *
dkato 0:2156833a74a8 4 * Permission is hereby granted, free of charge, to any person obtaining a copy
dkato 0:2156833a74a8 5 * of this software and associated documentation files (the "Software"), to deal
dkato 0:2156833a74a8 6 * in the Software without restriction, including without limitation the rights
dkato 0:2156833a74a8 7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
dkato 0:2156833a74a8 8 * copies of the Software, and to permit persons to whom the Software is
dkato 0:2156833a74a8 9 * furnished to do so, subject to the following conditions:
dkato 0:2156833a74a8 10 *
dkato 0:2156833a74a8 11 * The above copyright notice and this permission notice shall be included in
dkato 0:2156833a74a8 12 * all copies or substantial portions of the Software.
dkato 0:2156833a74a8 13 *
dkato 0:2156833a74a8 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
dkato 0:2156833a74a8 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
dkato 0:2156833a74a8 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
dkato 0:2156833a74a8 17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
dkato 0:2156833a74a8 18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
dkato 0:2156833a74a8 19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
dkato 0:2156833a74a8 20 * SOFTWARE.
dkato 0:2156833a74a8 21 */
dkato 0:2156833a74a8 22 /* Introduction
dkato 0:2156833a74a8 23 * ------------
dkato 0:2156833a74a8 24 * SD and MMC cards support a number of interfaces, but common to them all
dkato 0:2156833a74a8 25 * is one based on SPI. This is the one I'm implmenting because it means
dkato 0:2156833a74a8 26 * it is much more portable even though not so performant, and we already
dkato 0:2156833a74a8 27 * have the mbed SPI Interface!
dkato 0:2156833a74a8 28 *
dkato 0:2156833a74a8 29 * The main reference I'm using is Chapter 7, "SPI Mode" of:
dkato 0:2156833a74a8 30 * http://www.sdcard.org/developers/tech/sdcard/pls/Simplified_Physical_Layer_Spec.pdf
dkato 0:2156833a74a8 31 *
dkato 0:2156833a74a8 32 * SPI Startup
dkato 0:2156833a74a8 33 * -----------
dkato 0:2156833a74a8 34 * The SD card powers up in SD mode. The SPI interface mode is selected by
dkato 0:2156833a74a8 35 * asserting CS low and sending the reset command (CMD0). The card will
dkato 0:2156833a74a8 36 * respond with a (R1) response.
dkato 0:2156833a74a8 37 *
dkato 0:2156833a74a8 38 * CMD8 is optionally sent to determine the voltage range supported, and
dkato 0:2156833a74a8 39 * indirectly determine whether it is a version 1.x SD/non-SD card or
dkato 0:2156833a74a8 40 * version 2.x. I'll just ignore this for now.
dkato 0:2156833a74a8 41 *
dkato 0:2156833a74a8 42 * ACMD41 is repeatedly issued to initialise the card, until "in idle"
dkato 0:2156833a74a8 43 * (bit 0) of the R1 response goes to '0', indicating it is initialised.
dkato 0:2156833a74a8 44 *
dkato 0:2156833a74a8 45 * You should also indicate whether the host supports High Capicity cards,
dkato 0:2156833a74a8 46 * and check whether the card is high capacity - i'll also ignore this
dkato 0:2156833a74a8 47 *
dkato 0:2156833a74a8 48 * SPI Protocol
dkato 0:2156833a74a8 49 * ------------
dkato 0:2156833a74a8 50 * The SD SPI protocol is based on transactions made up of 8-bit words, with
dkato 0:2156833a74a8 51 * the host starting every bus transaction by asserting the CS signal low. The
dkato 0:2156833a74a8 52 * card always responds to commands, data blocks and errors.
dkato 0:2156833a74a8 53 *
dkato 0:2156833a74a8 54 * The protocol supports a CRC, but by default it is off (except for the
dkato 0:2156833a74a8 55 * first reset CMD0, where the CRC can just be pre-calculated, and CMD8)
dkato 0:2156833a74a8 56 * I'll leave the CRC off I think!
dkato 0:2156833a74a8 57 *
dkato 0:2156833a74a8 58 * Standard capacity cards have variable data block sizes, whereas High
dkato 0:2156833a74a8 59 * Capacity cards fix the size of data block to 512 bytes. I'll therefore
dkato 0:2156833a74a8 60 * just always use the Standard Capacity cards with a block size of 512 bytes.
dkato 0:2156833a74a8 61 * This is set with CMD16.
dkato 0:2156833a74a8 62 *
dkato 0:2156833a74a8 63 * You can read and write single blocks (CMD17, CMD25) or multiple blocks
dkato 0:2156833a74a8 64 * (CMD18, CMD25). For simplicity, I'll just use single block accesses. When
dkato 0:2156833a74a8 65 * the card gets a read command, it responds with a response token, and then
dkato 0:2156833a74a8 66 * a data token or an error.
dkato 0:2156833a74a8 67 *
dkato 0:2156833a74a8 68 * SPI Command Format
dkato 0:2156833a74a8 69 * ------------------
dkato 0:2156833a74a8 70 * Commands are 6-bytes long, containing the command, 32-bit argument, and CRC.
dkato 0:2156833a74a8 71 *
dkato 0:2156833a74a8 72 * +---------------+------------+------------+-----------+----------+--------------+
dkato 0:2156833a74a8 73 * | 01 | cmd[5:0] | arg[31:24] | arg[23:16] | arg[15:8] | arg[7:0] | crc[6:0] | 1 |
dkato 0:2156833a74a8 74 * +---------------+------------+------------+-----------+----------+--------------+
dkato 0:2156833a74a8 75 *
dkato 0:2156833a74a8 76 * As I'm not using CRC, I can fix that byte to what is needed for CMD0 (0x95)
dkato 0:2156833a74a8 77 *
dkato 0:2156833a74a8 78 * All Application Specific commands shall be preceded with APP_CMD (CMD55).
dkato 0:2156833a74a8 79 *
dkato 0:2156833a74a8 80 * SPI Response Format
dkato 0:2156833a74a8 81 * -------------------
dkato 0:2156833a74a8 82 * The main response format (R1) is a status byte (normally zero). Key flags:
dkato 0:2156833a74a8 83 * idle - 1 if the card is in an idle state/initialising
dkato 0:2156833a74a8 84 * cmd - 1 if an illegal command code was detected
dkato 0:2156833a74a8 85 *
dkato 0:2156833a74a8 86 * +-------------------------------------------------+
dkato 0:2156833a74a8 87 * R1 | 0 | arg | addr | seq | crc | cmd | erase | idle |
dkato 0:2156833a74a8 88 * +-------------------------------------------------+
dkato 0:2156833a74a8 89 *
dkato 0:2156833a74a8 90 * R1b is the same, except it is followed by a busy signal (zeros) until
dkato 0:2156833a74a8 91 * the first non-zero byte when it is ready again.
dkato 0:2156833a74a8 92 *
dkato 0:2156833a74a8 93 * Data Response Token
dkato 0:2156833a74a8 94 * -------------------
dkato 0:2156833a74a8 95 * Every data block written to the card is acknowledged by a byte
dkato 0:2156833a74a8 96 * response token
dkato 0:2156833a74a8 97 *
dkato 0:2156833a74a8 98 * +----------------------+
dkato 0:2156833a74a8 99 * | xxx | 0 | status | 1 |
dkato 0:2156833a74a8 100 * +----------------------+
dkato 0:2156833a74a8 101 * 010 - OK!
dkato 0:2156833a74a8 102 * 101 - CRC Error
dkato 0:2156833a74a8 103 * 110 - Write Error
dkato 0:2156833a74a8 104 *
dkato 0:2156833a74a8 105 * Single Block Read and Write
dkato 0:2156833a74a8 106 * ---------------------------
dkato 0:2156833a74a8 107 *
dkato 0:2156833a74a8 108 * Block transfers have a byte header, followed by the data, followed
dkato 0:2156833a74a8 109 * by a 16-bit CRC. In our case, the data will always be 512 bytes.
dkato 0:2156833a74a8 110 *
dkato 0:2156833a74a8 111 * +------+---------+---------+- - - -+---------+-----------+----------+
dkato 0:2156833a74a8 112 * | 0xFE | data[0] | data[1] | | data[n] | crc[15:8] | crc[7:0] |
dkato 0:2156833a74a8 113 * +------+---------+---------+- - - -+---------+-----------+----------+
dkato 0:2156833a74a8 114 */
dkato 0:2156833a74a8 115 #include "SDFileSystem.h"
dkato 0:2156833a74a8 116 #include "mbed_debug.h"
dkato 0:2156833a74a8 117
dkato 0:2156833a74a8 118 #define SD_COMMAND_TIMEOUT 5000
dkato 0:2156833a74a8 119
dkato 0:2156833a74a8 120 #define SD_DBG 0
dkato 0:2156833a74a8 121
dkato 0:2156833a74a8 122 SDFileSystem::SDFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name) :
dkato 0:2156833a74a8 123 FATFileSystem(name), _spi(mosi, miso, sclk), _cs(cs), _is_initialized(0) {
dkato 0:2156833a74a8 124 _cs = 1;
dkato 0:2156833a74a8 125
dkato 0:2156833a74a8 126 // Set default to 100kHz for initialisation and 1MHz for data transfer
dkato 0:2156833a74a8 127 _init_sck = 100000;
dkato 0:2156833a74a8 128 _transfer_sck = 1000000;
dkato 0:2156833a74a8 129 }
dkato 0:2156833a74a8 130
dkato 0:2156833a74a8 131 #define R1_IDLE_STATE (1 << 0)
dkato 0:2156833a74a8 132 #define R1_ERASE_RESET (1 << 1)
dkato 0:2156833a74a8 133 #define R1_ILLEGAL_COMMAND (1 << 2)
dkato 0:2156833a74a8 134 #define R1_COM_CRC_ERROR (1 << 3)
dkato 0:2156833a74a8 135 #define R1_ERASE_SEQUENCE_ERROR (1 << 4)
dkato 0:2156833a74a8 136 #define R1_ADDRESS_ERROR (1 << 5)
dkato 0:2156833a74a8 137 #define R1_PARAMETER_ERROR (1 << 6)
dkato 0:2156833a74a8 138
dkato 0:2156833a74a8 139 // Types
dkato 0:2156833a74a8 140 // - v1.x Standard Capacity
dkato 0:2156833a74a8 141 // - v2.x Standard Capacity
dkato 0:2156833a74a8 142 // - v2.x High Capacity
dkato 0:2156833a74a8 143 // - Not recognised as an SD Card
dkato 0:2156833a74a8 144 #define SDCARD_FAIL 0
dkato 0:2156833a74a8 145 #define SDCARD_V1 1
dkato 0:2156833a74a8 146 #define SDCARD_V2 2
dkato 0:2156833a74a8 147 #define SDCARD_V2HC 3
dkato 0:2156833a74a8 148
dkato 0:2156833a74a8 149 int SDFileSystem::initialise_card() {
dkato 0:2156833a74a8 150 // Set to SCK for initialisation, and clock card with cs = 1
dkato 0:2156833a74a8 151 _spi.frequency(_init_sck);
dkato 0:2156833a74a8 152 _cs = 1;
dkato 0:2156833a74a8 153 for (int i = 0; i < 16; i++) {
dkato 0:2156833a74a8 154 _spi.write(0xFF);
dkato 0:2156833a74a8 155 }
dkato 0:2156833a74a8 156
dkato 0:2156833a74a8 157 // send CMD0, should return with all zeros except IDLE STATE set (bit 0)
dkato 0:2156833a74a8 158 if (_cmd(0, 0) != R1_IDLE_STATE) {
dkato 0:2156833a74a8 159 debug("No disk, or could not put SD card in to SPI idle state\n");
dkato 0:2156833a74a8 160 return SDCARD_FAIL;
dkato 0:2156833a74a8 161 }
dkato 0:2156833a74a8 162
dkato 0:2156833a74a8 163 // send CMD8 to determine whther it is ver 2.x
dkato 0:2156833a74a8 164 int r = _cmd8();
dkato 0:2156833a74a8 165 if (r == R1_IDLE_STATE) {
dkato 0:2156833a74a8 166 return initialise_card_v2();
dkato 0:2156833a74a8 167 } else if (r == (R1_IDLE_STATE | R1_ILLEGAL_COMMAND)) {
dkato 0:2156833a74a8 168 return initialise_card_v1();
dkato 0:2156833a74a8 169 } else {
dkato 0:2156833a74a8 170 debug("Not in idle state after sending CMD8 (not an SD card?)\n");
dkato 0:2156833a74a8 171 return SDCARD_FAIL;
dkato 0:2156833a74a8 172 }
dkato 0:2156833a74a8 173 }
dkato 0:2156833a74a8 174
dkato 0:2156833a74a8 175 int SDFileSystem::initialise_card_v1() {
dkato 0:2156833a74a8 176 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
dkato 0:2156833a74a8 177 _cmd(55, 0);
dkato 0:2156833a74a8 178 if (_cmd(41, 0) == 0) {
dkato 0:2156833a74a8 179 cdv = 512;
dkato 0:2156833a74a8 180 debug_if(SD_DBG, "\n\rInit: SEDCARD_V1\n\r");
dkato 0:2156833a74a8 181 return SDCARD_V1;
dkato 0:2156833a74a8 182 }
dkato 0:2156833a74a8 183 }
dkato 0:2156833a74a8 184
dkato 0:2156833a74a8 185 debug("Timeout waiting for v1.x card\n");
dkato 0:2156833a74a8 186 return SDCARD_FAIL;
dkato 0:2156833a74a8 187 }
dkato 0:2156833a74a8 188
dkato 0:2156833a74a8 189 int SDFileSystem::initialise_card_v2() {
dkato 0:2156833a74a8 190 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
dkato 0:2156833a74a8 191 wait_ms(50);
dkato 0:2156833a74a8 192 _cmd58();
dkato 0:2156833a74a8 193 _cmd(55, 0);
dkato 0:2156833a74a8 194 if (_cmd(41, 0x40000000) == 0) {
dkato 0:2156833a74a8 195 _cmd58();
dkato 0:2156833a74a8 196 debug_if(SD_DBG, "\n\rInit: SDCARD_V2\n\r");
dkato 0:2156833a74a8 197 cdv = 1;
dkato 0:2156833a74a8 198 return SDCARD_V2;
dkato 0:2156833a74a8 199 }
dkato 0:2156833a74a8 200 }
dkato 0:2156833a74a8 201
dkato 0:2156833a74a8 202 debug("Timeout waiting for v2.x card\n");
dkato 0:2156833a74a8 203 return SDCARD_FAIL;
dkato 0:2156833a74a8 204 }
dkato 0:2156833a74a8 205
dkato 0:2156833a74a8 206 int SDFileSystem::disk_initialize() {
dkato 0:2156833a74a8 207 _is_initialized = initialise_card();
dkato 0:2156833a74a8 208 if (_is_initialized == 0) {
dkato 0:2156833a74a8 209 debug("Fail to initialize card\n");
dkato 0:2156833a74a8 210 return 1;
dkato 0:2156833a74a8 211 }
dkato 0:2156833a74a8 212 debug_if(SD_DBG, "init card = %d\n", _is_initialized);
dkato 0:2156833a74a8 213 _sectors = _sd_sectors();
dkato 0:2156833a74a8 214
dkato 0:2156833a74a8 215 // Set block length to 512 (CMD16)
dkato 0:2156833a74a8 216 if (_cmd(16, 512) != 0) {
dkato 0:2156833a74a8 217 debug("Set 512-byte block timed out\n");
dkato 0:2156833a74a8 218 return 1;
dkato 0:2156833a74a8 219 }
dkato 0:2156833a74a8 220
dkato 0:2156833a74a8 221 // Set SCK for data transfer
dkato 0:2156833a74a8 222 _spi.frequency(_transfer_sck);
dkato 0:2156833a74a8 223 return 0;
dkato 0:2156833a74a8 224 }
dkato 0:2156833a74a8 225
dkato 0:2156833a74a8 226 int SDFileSystem::disk_write(const uint8_t* buffer, uint32_t block_number, uint32_t count) {
dkato 0:2156833a74a8 227 if (!_is_initialized) {
dkato 0:2156833a74a8 228 return -1;
dkato 0:2156833a74a8 229 }
dkato 0:2156833a74a8 230
dkato 0:2156833a74a8 231 for (uint32_t b = block_number; b < block_number + count; b++) {
dkato 0:2156833a74a8 232 // set write address for single block (CMD24)
dkato 0:2156833a74a8 233 if (_cmd(24, b * cdv) != 0) {
dkato 0:2156833a74a8 234 return 1;
dkato 0:2156833a74a8 235 }
dkato 0:2156833a74a8 236
dkato 0:2156833a74a8 237 // send the data block
dkato 0:2156833a74a8 238 _write(buffer, 512);
dkato 0:2156833a74a8 239 buffer += 512;
dkato 0:2156833a74a8 240 }
dkato 0:2156833a74a8 241
dkato 0:2156833a74a8 242 return 0;
dkato 0:2156833a74a8 243 }
dkato 0:2156833a74a8 244
dkato 0:2156833a74a8 245 int SDFileSystem::disk_read(uint8_t* buffer, uint32_t block_number, uint32_t count) {
dkato 0:2156833a74a8 246 if (!_is_initialized) {
dkato 0:2156833a74a8 247 return -1;
dkato 0:2156833a74a8 248 }
dkato 0:2156833a74a8 249
dkato 0:2156833a74a8 250 for (uint32_t b = block_number; b < block_number + count; b++) {
dkato 0:2156833a74a8 251 // set read address for single block (CMD17)
dkato 0:2156833a74a8 252 if (_cmd(17, b * cdv) != 0) {
dkato 0:2156833a74a8 253 return 1;
dkato 0:2156833a74a8 254 }
dkato 0:2156833a74a8 255
dkato 0:2156833a74a8 256 // receive the data
dkato 0:2156833a74a8 257 _read(buffer, 512);
dkato 0:2156833a74a8 258 buffer += 512;
dkato 0:2156833a74a8 259 }
dkato 0:2156833a74a8 260
dkato 0:2156833a74a8 261 return 0;
dkato 0:2156833a74a8 262 }
dkato 0:2156833a74a8 263
dkato 0:2156833a74a8 264 int SDFileSystem::disk_status() {
dkato 0:2156833a74a8 265 // FATFileSystem::disk_status() returns 0 when initialized
dkato 0:2156833a74a8 266 if (_is_initialized) {
dkato 0:2156833a74a8 267 return 0;
dkato 0:2156833a74a8 268 } else {
dkato 0:2156833a74a8 269 return 1;
dkato 0:2156833a74a8 270 }
dkato 0:2156833a74a8 271 }
dkato 0:2156833a74a8 272
dkato 0:2156833a74a8 273 int SDFileSystem::disk_sync() { return 0; }
dkato 0:2156833a74a8 274 uint32_t SDFileSystem::disk_sectors() { return _sectors; }
dkato 0:2156833a74a8 275
dkato 0:2156833a74a8 276
dkato 0:2156833a74a8 277 // PRIVATE FUNCTIONS
dkato 0:2156833a74a8 278 int SDFileSystem::_cmd(int cmd, int arg) {
dkato 0:2156833a74a8 279 _cs = 0;
dkato 0:2156833a74a8 280
dkato 0:2156833a74a8 281 // send a command
dkato 0:2156833a74a8 282 _spi.write(0x40 | cmd);
dkato 0:2156833a74a8 283 _spi.write(arg >> 24);
dkato 0:2156833a74a8 284 _spi.write(arg >> 16);
dkato 0:2156833a74a8 285 _spi.write(arg >> 8);
dkato 0:2156833a74a8 286 _spi.write(arg >> 0);
dkato 0:2156833a74a8 287 _spi.write(0x95);
dkato 0:2156833a74a8 288
dkato 0:2156833a74a8 289 // wait for the repsonse (response[7] == 0)
dkato 0:2156833a74a8 290 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
dkato 0:2156833a74a8 291 int response = _spi.write(0xFF);
dkato 0:2156833a74a8 292 if (!(response & 0x80)) {
dkato 0:2156833a74a8 293 _cs = 1;
dkato 0:2156833a74a8 294 _spi.write(0xFF);
dkato 0:2156833a74a8 295 return response;
dkato 0:2156833a74a8 296 }
dkato 0:2156833a74a8 297 }
dkato 0:2156833a74a8 298 _cs = 1;
dkato 0:2156833a74a8 299 _spi.write(0xFF);
dkato 0:2156833a74a8 300 return -1; // timeout
dkato 0:2156833a74a8 301 }
dkato 0:2156833a74a8 302 int SDFileSystem::_cmdx(int cmd, int arg) {
dkato 0:2156833a74a8 303 _cs = 0;
dkato 0:2156833a74a8 304
dkato 0:2156833a74a8 305 // send a command
dkato 0:2156833a74a8 306 _spi.write(0x40 | cmd);
dkato 0:2156833a74a8 307 _spi.write(arg >> 24);
dkato 0:2156833a74a8 308 _spi.write(arg >> 16);
dkato 0:2156833a74a8 309 _spi.write(arg >> 8);
dkato 0:2156833a74a8 310 _spi.write(arg >> 0);
dkato 0:2156833a74a8 311 _spi.write(0x95);
dkato 0:2156833a74a8 312
dkato 0:2156833a74a8 313 // wait for the repsonse (response[7] == 0)
dkato 0:2156833a74a8 314 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
dkato 0:2156833a74a8 315 int response = _spi.write(0xFF);
dkato 0:2156833a74a8 316 if (!(response & 0x80)) {
dkato 0:2156833a74a8 317 return response;
dkato 0:2156833a74a8 318 }
dkato 0:2156833a74a8 319 }
dkato 0:2156833a74a8 320 _cs = 1;
dkato 0:2156833a74a8 321 _spi.write(0xFF);
dkato 0:2156833a74a8 322 return -1; // timeout
dkato 0:2156833a74a8 323 }
dkato 0:2156833a74a8 324
dkato 0:2156833a74a8 325
dkato 0:2156833a74a8 326 int SDFileSystem::_cmd58() {
dkato 0:2156833a74a8 327 _cs = 0;
dkato 0:2156833a74a8 328 int arg = 0;
dkato 0:2156833a74a8 329
dkato 0:2156833a74a8 330 // send a command
dkato 0:2156833a74a8 331 _spi.write(0x40 | 58);
dkato 0:2156833a74a8 332 _spi.write(arg >> 24);
dkato 0:2156833a74a8 333 _spi.write(arg >> 16);
dkato 0:2156833a74a8 334 _spi.write(arg >> 8);
dkato 0:2156833a74a8 335 _spi.write(arg >> 0);
dkato 0:2156833a74a8 336 _spi.write(0x95);
dkato 0:2156833a74a8 337
dkato 0:2156833a74a8 338 // wait for the repsonse (response[7] == 0)
dkato 0:2156833a74a8 339 for (int i = 0; i < SD_COMMAND_TIMEOUT; i++) {
dkato 0:2156833a74a8 340 int response = _spi.write(0xFF);
dkato 0:2156833a74a8 341 if (!(response & 0x80)) {
dkato 0:2156833a74a8 342 int ocr = _spi.write(0xFF) << 24;
dkato 0:2156833a74a8 343 ocr |= _spi.write(0xFF) << 16;
dkato 0:2156833a74a8 344 ocr |= _spi.write(0xFF) << 8;
dkato 0:2156833a74a8 345 ocr |= _spi.write(0xFF) << 0;
dkato 0:2156833a74a8 346 _cs = 1;
dkato 0:2156833a74a8 347 _spi.write(0xFF);
dkato 0:2156833a74a8 348 return response;
dkato 0:2156833a74a8 349 }
dkato 0:2156833a74a8 350 }
dkato 0:2156833a74a8 351 _cs = 1;
dkato 0:2156833a74a8 352 _spi.write(0xFF);
dkato 0:2156833a74a8 353 return -1; // timeout
dkato 0:2156833a74a8 354 }
dkato 0:2156833a74a8 355
dkato 0:2156833a74a8 356 int SDFileSystem::_cmd8() {
dkato 0:2156833a74a8 357 _cs = 0;
dkato 0:2156833a74a8 358
dkato 0:2156833a74a8 359 // send a command
dkato 0:2156833a74a8 360 _spi.write(0x40 | 8); // CMD8
dkato 0:2156833a74a8 361 _spi.write(0x00); // reserved
dkato 0:2156833a74a8 362 _spi.write(0x00); // reserved
dkato 0:2156833a74a8 363 _spi.write(0x01); // 3.3v
dkato 0:2156833a74a8 364 _spi.write(0xAA); // check pattern
dkato 0:2156833a74a8 365 _spi.write(0x87); // crc
dkato 0:2156833a74a8 366
dkato 0:2156833a74a8 367 // wait for the repsonse (response[7] == 0)
dkato 0:2156833a74a8 368 for (int i = 0; i < SD_COMMAND_TIMEOUT * 1000; i++) {
dkato 0:2156833a74a8 369 char response[5];
dkato 0:2156833a74a8 370 response[0] = _spi.write(0xFF);
dkato 0:2156833a74a8 371 if (!(response[0] & 0x80)) {
dkato 0:2156833a74a8 372 for (int j = 1; j < 5; j++) {
dkato 0:2156833a74a8 373 response[i] = _spi.write(0xFF);
dkato 0:2156833a74a8 374 }
dkato 0:2156833a74a8 375 _cs = 1;
dkato 0:2156833a74a8 376 _spi.write(0xFF);
dkato 0:2156833a74a8 377 return response[0];
dkato 0:2156833a74a8 378 }
dkato 0:2156833a74a8 379 }
dkato 0:2156833a74a8 380 _cs = 1;
dkato 0:2156833a74a8 381 _spi.write(0xFF);
dkato 0:2156833a74a8 382 return -1; // timeout
dkato 0:2156833a74a8 383 }
dkato 0:2156833a74a8 384
dkato 0:2156833a74a8 385 int SDFileSystem::_read(uint8_t *buffer, uint32_t length) {
dkato 0:2156833a74a8 386 _cs = 0;
dkato 0:2156833a74a8 387
dkato 0:2156833a74a8 388 // read until start byte (0xFF)
dkato 0:2156833a74a8 389 while (_spi.write(0xFF) != 0xFE);
dkato 0:2156833a74a8 390
dkato 0:2156833a74a8 391 // read data
dkato 0:2156833a74a8 392 for (uint32_t i = 0; i < length; i++) {
dkato 0:2156833a74a8 393 buffer[i] = _spi.write(0xFF);
dkato 0:2156833a74a8 394 }
dkato 0:2156833a74a8 395 _spi.write(0xFF); // checksum
dkato 0:2156833a74a8 396 _spi.write(0xFF);
dkato 0:2156833a74a8 397
dkato 0:2156833a74a8 398 _cs = 1;
dkato 0:2156833a74a8 399 _spi.write(0xFF);
dkato 0:2156833a74a8 400 return 0;
dkato 0:2156833a74a8 401 }
dkato 0:2156833a74a8 402
dkato 0:2156833a74a8 403 int SDFileSystem::_write(const uint8_t*buffer, uint32_t length) {
dkato 0:2156833a74a8 404 _cs = 0;
dkato 0:2156833a74a8 405
dkato 0:2156833a74a8 406 // indicate start of block
dkato 0:2156833a74a8 407 _spi.write(0xFE);
dkato 0:2156833a74a8 408
dkato 0:2156833a74a8 409 // write the data
dkato 0:2156833a74a8 410 for (uint32_t i = 0; i < length; i++) {
dkato 0:2156833a74a8 411 _spi.write(buffer[i]);
dkato 0:2156833a74a8 412 }
dkato 0:2156833a74a8 413
dkato 0:2156833a74a8 414 // write the checksum
dkato 0:2156833a74a8 415 _spi.write(0xFF);
dkato 0:2156833a74a8 416 _spi.write(0xFF);
dkato 0:2156833a74a8 417
dkato 0:2156833a74a8 418 // check the response token
dkato 0:2156833a74a8 419 if ((_spi.write(0xFF) & 0x1F) != 0x05) {
dkato 0:2156833a74a8 420 _cs = 1;
dkato 0:2156833a74a8 421 _spi.write(0xFF);
dkato 0:2156833a74a8 422 return 1;
dkato 0:2156833a74a8 423 }
dkato 0:2156833a74a8 424
dkato 0:2156833a74a8 425 // wait for write to finish
dkato 0:2156833a74a8 426 while (_spi.write(0xFF) == 0);
dkato 0:2156833a74a8 427
dkato 0:2156833a74a8 428 _cs = 1;
dkato 0:2156833a74a8 429 _spi.write(0xFF);
dkato 0:2156833a74a8 430 return 0;
dkato 0:2156833a74a8 431 }
dkato 0:2156833a74a8 432
dkato 0:2156833a74a8 433 static uint32_t ext_bits(unsigned char *data, int msb, int lsb) {
dkato 0:2156833a74a8 434 uint32_t bits = 0;
dkato 0:2156833a74a8 435 uint32_t size = 1 + msb - lsb;
dkato 0:2156833a74a8 436 for (uint32_t i = 0; i < size; i++) {
dkato 0:2156833a74a8 437 uint32_t position = lsb + i;
dkato 0:2156833a74a8 438 uint32_t byte = 15 - (position >> 3);
dkato 0:2156833a74a8 439 uint32_t bit = position & 0x7;
dkato 0:2156833a74a8 440 uint32_t value = (data[byte] >> bit) & 1;
dkato 0:2156833a74a8 441 bits |= value << i;
dkato 0:2156833a74a8 442 }
dkato 0:2156833a74a8 443 return bits;
dkato 0:2156833a74a8 444 }
dkato 0:2156833a74a8 445
dkato 0:2156833a74a8 446 uint32_t SDFileSystem::_sd_sectors() {
dkato 0:2156833a74a8 447 uint32_t c_size, c_size_mult, read_bl_len;
dkato 0:2156833a74a8 448 uint32_t block_len, mult, blocknr, capacity;
dkato 0:2156833a74a8 449 uint32_t hc_c_size;
dkato 0:2156833a74a8 450 uint32_t blocks;
dkato 0:2156833a74a8 451
dkato 0:2156833a74a8 452 // CMD9, Response R2 (R1 byte + 16-byte block read)
dkato 0:2156833a74a8 453 if (_cmdx(9, 0) != 0) {
dkato 0:2156833a74a8 454 debug("Didn't get a response from the disk\n");
dkato 0:2156833a74a8 455 return 0;
dkato 0:2156833a74a8 456 }
dkato 0:2156833a74a8 457
dkato 0:2156833a74a8 458 uint8_t csd[16];
dkato 0:2156833a74a8 459 if (_read(csd, 16) != 0) {
dkato 0:2156833a74a8 460 debug("Couldn't read csd response from disk\n");
dkato 0:2156833a74a8 461 return 0;
dkato 0:2156833a74a8 462 }
dkato 0:2156833a74a8 463
dkato 0:2156833a74a8 464 // csd_structure : csd[127:126]
dkato 0:2156833a74a8 465 // c_size : csd[73:62]
dkato 0:2156833a74a8 466 // c_size_mult : csd[49:47]
dkato 0:2156833a74a8 467 // read_bl_len : csd[83:80] - the *maximum* read block length
dkato 0:2156833a74a8 468
dkato 0:2156833a74a8 469 int csd_structure = ext_bits(csd, 127, 126);
dkato 0:2156833a74a8 470
dkato 0:2156833a74a8 471 switch (csd_structure) {
dkato 0:2156833a74a8 472 case 0:
dkato 0:2156833a74a8 473 cdv = 512;
dkato 0:2156833a74a8 474 c_size = ext_bits(csd, 73, 62);
dkato 0:2156833a74a8 475 c_size_mult = ext_bits(csd, 49, 47);
dkato 0:2156833a74a8 476 read_bl_len = ext_bits(csd, 83, 80);
dkato 0:2156833a74a8 477
dkato 0:2156833a74a8 478 block_len = 1 << read_bl_len;
dkato 0:2156833a74a8 479 mult = 1 << (c_size_mult + 2);
dkato 0:2156833a74a8 480 blocknr = (c_size + 1) * mult;
dkato 0:2156833a74a8 481 capacity = blocknr * block_len;
dkato 0:2156833a74a8 482 blocks = capacity / 512;
dkato 0:2156833a74a8 483 debug_if(SD_DBG, "\n\rSDCard\n\rc_size: %d \n\rcapacity: %ld \n\rsectors: %lld\n\r", c_size, capacity, blocks);
dkato 0:2156833a74a8 484 break;
dkato 0:2156833a74a8 485
dkato 0:2156833a74a8 486 case 1:
dkato 0:2156833a74a8 487 cdv = 1;
dkato 0:2156833a74a8 488 hc_c_size = ext_bits(csd, 63, 48);
dkato 0:2156833a74a8 489 blocks = (hc_c_size+1)*1024;
dkato 0:2156833a74a8 490 debug_if(SD_DBG, "\n\rSDHC Card \n\rhc_c_size: %d\n\rcapacity: %lld \n\rsectors: %lld\n\r", hc_c_size, blocks*512, blocks);
dkato 0:2156833a74a8 491 break;
dkato 0:2156833a74a8 492
dkato 0:2156833a74a8 493 default:
dkato 0:2156833a74a8 494 debug("CSD struct unsupported\r\n");
dkato 0:2156833a74a8 495 return 0;
dkato 0:2156833a74a8 496 };
dkato 0:2156833a74a8 497 return blocks;
dkato 0:2156833a74a8 498 }