Darren Ulrich / UniGraphic

Dependents:   Bicycl_Computer_NUCLEO-F411RE Bicycl_Computer_NUCLEO-L476RG

Fork of UniGraphic by GraphicsDisplay

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SPI16.cpp Source File

SPI16.cpp

00001  /* mbed UniGraphic library - SPI16 protocol class
00002  * Copyright (c) 2015 Giuliano Dianda
00003  * Released under the MIT License: http://mbed.org/license/mit
00004  *
00005  * Derived work of:
00006  *
00007  * mbed library for 240*320 pixel display TFT based on ILI9341 LCD Controller
00008  * Copyright (c) 2013 Peter Drescher - DC2PD
00009  *
00010  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
00011  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
00012  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
00013  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
00014  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
00015  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
00016  * THE SOFTWARE.
00017  */
00018  
00019 #include "SPI16.h"
00020 //#define USE_CS
00021 
00022 SPI16::SPI16(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC)
00023     : _CS(CS), _spi(mosi, miso, sclk), _reset(reset), _DC(DC)
00024 {
00025     _reset = 1;
00026     _DC=1;
00027     _CS=1;
00028     _spi.format(16,0);                  // 8 bit spi mode 0
00029  //   _spi.frequency(12000000);          // 10 Mhz SPI clock, 12mhz for F411
00030     _spi.frequency(Hz);
00031     hw_reset();    
00032 }
00033 
00034 void SPI16::wr_cmd8(unsigned char cmd)
00035 {   
00036 #ifdef USE_CS
00037     _CS = 0;
00038 #endif
00039     _spi.format(8,0); // it takes time, better use wr_cmd16 with NOP cmd
00040     _DC.write(0); // 0=cmd
00041     _spi.write(cmd);      // write 8bit
00042     _spi.format(16,0);
00043 #ifdef USE_CS
00044     _CS = 1;
00045 #endif
00046 }
00047 void SPI16::wr_data8(unsigned char data)
00048 {
00049 #ifdef USE_CS
00050     _CS = 0;
00051 #endif
00052     _spi.format(8,0); // it takes time, check prev cmd parameter, in case use wr_data16 with repeated byte
00053     _DC.write(1); // 1=data
00054     _spi.write(data);    // write 8bit
00055     _spi.format(16,0);
00056 #ifdef USE_CS
00057     _CS = 1;
00058 #endif
00059 }
00060 void SPI16::wr_cmd16(unsigned short cmd)
00061 {   
00062 #ifdef USE_CS
00063     _CS = 0;
00064 #endif    
00065     _DC.write(0); // 0=cmd
00066     _spi.write(cmd);      // write 16bit
00067 #ifdef USE_CS
00068     _CS = 1;
00069 #endif
00070 }
00071 void SPI16::wr_data16(unsigned short data)
00072 {
00073 #ifdef USE_CS
00074     _CS = 0;
00075 #endif
00076     _DC.write(1); // 1=data
00077     _spi.write(data);    // write 16bit
00078 #ifdef USE_CS
00079     _CS = 1;
00080 #endif
00081 }
00082 void SPI16::wr_gram(unsigned short data)
00083 {
00084 #ifdef USE_CS
00085     _CS = 0;
00086 #endif
00087     _DC.write(1); // 1=data
00088     _spi.write(data);    // write 16bit
00089 #ifdef USE_CS
00090     _CS = 1;
00091 #endif
00092 }
00093 void SPI16::wr_gram(unsigned short data, unsigned int count)
00094 {
00095 #ifdef USE_CS
00096     _CS = 0;
00097 #endif
00098     _DC.write(1); // 1=data
00099     while(count)
00100     {
00101         _spi.write(data);
00102         count--;
00103     }
00104 #ifdef USE_CS
00105     _CS = 1;
00106 #endif
00107 }
00108 void SPI16::wr_grambuf(unsigned short* data, unsigned int lenght)
00109 {
00110 #ifdef USE_CS
00111     _CS = 0;
00112 #endif
00113     _DC.write(1); // 1=data
00114     while(lenght)
00115     {
00116         _spi.write(*data);
00117         data++;
00118         lenght--;
00119     }
00120 #ifdef USE_CS
00121     _CS = 1;
00122 #endif
00123 }
00124 unsigned short SPI16::rd_gram(bool convert)
00125 {
00126 #ifdef USE_CS
00127     _CS = 0;
00128 #endif
00129     unsigned int r=0;
00130     _DC.write(1); // 1=data
00131     r |= _spi.write(0); // 16bit, whole first byte is dummy, second is red
00132     r <<= 16;
00133     r |= _spi.write(0);  
00134     if(convert)
00135     {
00136         // gram is 18bit/pixel, if you set 16bit/pixel (cmd 3A), during writing the 16bits are expanded to 18bit
00137         // during reading, you read the raw 18bit gram
00138         r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
00139     }
00140     else r >>= 8;
00141 _CS = 1; // force CS HIG to interupt the "read state"
00142 #ifndef USE_CS //if CS is not used, force fixed LOW again
00143     _CS = 0;
00144 #endif
00145     return (unsigned short)r;
00146 }
00147 unsigned int SPI16::rd_reg_data32(unsigned char reg)
00148 {
00149 #ifdef USE_CS
00150     _CS = 0;
00151 #endif
00152     wr_cmd8(reg);
00153     unsigned int r=0;
00154     _DC.write(1);; // 1=data
00155    
00156     r |= _spi.write(0); // we get only 15bit valid, first bit was the dummy cycle
00157     r <<= 16;
00158     r |= _spi.write(0);
00159     r <<= 1; // 32bits are aligned, now collecting bit_0
00160     r |= (_spi.write(0) >> 15);
00161     // we clocked 15 more bit so ILI waiting for 16th, we need to reset spi bus
00162     _CS = 1; // force CS HIG to interupt the cmd
00163 #ifndef USE_CS //if CS is not used, force fixed LOW again
00164     _CS = 0;
00165 #endif
00166     return r;
00167 }
00168 unsigned int SPI16::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd)
00169 {
00170     unsigned int r=0;
00171     for(int regparam=1; regparam<4; regparam++) // when reading EXTC regs, first parameter is always dummy, so start with 1
00172     {
00173         wr_cmd8(SPIreadenablecmd);  // spi-in enable cmd, 0xD9 (ili9341) or 0xFB (ili9488) or don't know
00174         wr_data8(0xF0|regparam);    // in low nibble specify which reg parameter we want
00175         wr_cmd8(reg);               // now send cmd (select register we want to read)
00176         _DC.write(1); // 1=data
00177         r <<= 8;
00178         r |= (_spi.write(0) >> 8);
00179     }
00180 _CS = 1; // force CS HIG to interupt the cmd
00181 #ifndef USE_CS //if CS is not used, force fixed LOW again
00182     _CS = 0;
00183 #endif
00184     return r;
00185 }
00186 void SPI16::hw_reset()
00187 {
00188     wait_ms(15);
00189     _DC = 1;
00190  //   _CS = 1;
00191     _CS = 0;
00192     _reset = 0;                        // display reset
00193     wait_us(50);
00194     _reset = 1;                       // end reset
00195     wait_ms(15);
00196 #ifndef USE_CS
00197     _CS=0;      // put CS low now and forever
00198 #endif
00199 }
00200 void SPI16::BusEnable(bool enable)
00201 {
00202     _CS = enable ? 0:1;
00203 }