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 SPI8.cpp Source File

SPI8.cpp

00001  /* mbed UniGraphic library - SPI8 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 "SPI8.h"
00020 
00021 //#define USE_CS
00022 
00023 SPI8::SPI8(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC)
00024     : _CS(CS), _spi(mosi, miso, sclk), _reset(reset), _DC(DC)
00025 {
00026     _reset = 1;
00027     _DC=1;
00028     _CS=1;
00029     _spi.format(8,0);                  // 8 bit spi mode 0
00030  //   _spi.frequency(12000000);          // 10 Mhz SPI clock, 12mhz for F411
00031     _spi.frequency(Hz);
00032     hw_reset();    
00033 }
00034 
00035 void SPI8::wr_cmd8(unsigned char cmd)
00036 {   
00037 #ifdef USE_CS
00038     _CS = 0;
00039 #endif    
00040     _DC.write(0); // 0=cmd
00041     _spi.write(cmd);      // write 8bit
00042 #ifdef USE_CS
00043     _CS = 1;
00044 #endif
00045 }
00046 void SPI8::wr_data8(unsigned char data)
00047 {
00048 #ifdef USE_CS
00049     _CS = 0;
00050 #endif
00051     _DC.write(1); // 1=data
00052     //_spi.write(data);    // write 8bit
00053         fastWrite(data);
00054         clearRX();
00055     
00056 #ifdef USE_CS
00057     _CS = 1;
00058 #endif
00059 }
00060 void SPI8::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>>8);      // write 8bit
00067     _spi.write(cmd&0xFF);      // write 8bit
00068 #ifdef USE_CS
00069     _CS = 1;
00070 #endif
00071 }
00072 void SPI8::wr_data16(unsigned short data)
00073 {
00074 #ifdef USE_CS
00075     _CS = 0;
00076 #endif
00077     _DC.write(1); // 1=data
00078     //_spi.write(data>>8);    // write 8bit
00079     //_spi.write(data&0xFF);    // write 8bit
00080         fastWrite(data>>8);
00081         fastWrite(data&0xFF);
00082         clearRX();
00083 #ifdef USE_CS
00084     _CS = 1;
00085 #endif
00086 }
00087 void SPI8::wr_gram(unsigned short data)
00088 {
00089 #ifdef USE_CS
00090     _CS = 0;
00091 #endif
00092     _DC.write(1); // 1=data
00093     //_spi.write(data>>8);    // write 8bit
00094    // _spi.write(data&0xFF);    // write 8bit
00095     fastWrite(data>>8);
00096     fastWrite(data&0xFF);
00097     clearRX();
00098     
00099 #ifdef USE_CS
00100     _CS = 1;
00101 #endif
00102 }
00103 void SPI8::wr_gram(unsigned short data, unsigned int count)
00104 {
00105 #ifdef USE_CS
00106     _CS = 0;
00107 #endif
00108     _DC.write(1); // 1=data
00109     if((data>>8)==(data&0xFF))
00110     {
00111         count<<=1;
00112         while(count)
00113         {
00114             //_spi.write(data);    // write 8bit
00115             fastWrite(data);
00116             count--;
00117         }
00118         clearRX();
00119     }
00120     else
00121     {
00122         while(count)
00123         {
00124             //_spi.write(data>>8);    // write 8bit
00125             //_spi.write(data&0xFF);    // write 8bit
00126               fastWrite(data>>8);
00127               fastWrite(data&0xFF);
00128               count--;
00129         }
00130         clearRX();
00131     }
00132 #ifdef USE_CS
00133     _CS = 1;
00134 #endif
00135 }
00136 void SPI8::wr_grambuf(unsigned short* data, unsigned int lenght)
00137 {
00138 #ifdef USE_CS
00139     _CS = 0;
00140 #endif
00141     _DC.write(1); // 1=data
00142     while(lenght)
00143     {
00144         //_spi.write((*data)>>8);    // write 8bit
00145         //_spi.write((*data)&0xFF);    // write 8bit
00146         fastWrite(*data>>8);
00147         fastWrite(*data&0xFF);
00148         data++;
00149         lenght--;
00150     }
00151     clearRX();
00152 #ifdef USE_CS
00153     _CS = 1;
00154 #endif
00155 }
00156 unsigned short SPI8::rd_gram(bool convert)
00157 {
00158 #ifdef USE_CS
00159     _CS = 0;
00160 #endif
00161     unsigned int r=0;
00162     _DC.write(1); // 1=data
00163     _spi.write(0); // whole first byte is dummy
00164     r |= _spi.write(0);
00165     r <<= 8;
00166     r |= _spi.write(0);
00167     if(convert)
00168     {
00169         r <<= 8;
00170         r |= _spi.write(0);
00171         // gram is 18bit/pixel, if you set 16bit/pixel (cmd 3A), during writing the 16bits are expanded to 18bit
00172         // during reading, you read the raw 18bit gram
00173         r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
00174     } 
00175     _CS = 1; // force CS HIG to interupt the "read state"
00176 #ifndef USE_CS //if CS is not used, force fixed LOW again
00177     _CS = 0;
00178 #endif
00179     return (unsigned short)r;
00180 }
00181 unsigned int SPI8::rd_reg_data32(unsigned char reg)
00182 {
00183 #ifdef USE_CS
00184     _CS = 0;
00185 #endif
00186     wr_cmd8(reg);
00187     unsigned int r=0;
00188     _DC.write(1); // 1=data
00189    
00190     r |= _spi.write(0); // we get only 7bit valid, first bit was the dummy cycle
00191     r <<= 8;
00192     r |= _spi.write(0);
00193     r <<= 8;
00194     r |= _spi.write(0);
00195     r <<= 8;
00196     r |= _spi.write(0);
00197     r <<= 1; // 32bits are aligned, now collecting bit_0
00198     r |= (_spi.write(0) >> 7);
00199     // we clocked 7 more bit so ILI waiting for 8th, we need to reset spi bus
00200     _CS = 1; // force CS HIG to interupt the cmd
00201 #ifndef USE_CS //if CS is not used, force fixed LOW again
00202     _CS = 0;
00203 #endif
00204     return r;
00205 }
00206 unsigned int SPI8::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd)
00207 {
00208     unsigned int r=0;
00209     for(int regparam=1; regparam<4; regparam++) // when reading EXTC regs, first parameter is always dummy, so start with 1
00210     {
00211         wr_cmd8(SPIreadenablecmd);  // spi-in enable cmd, 0xD9 (ili9341) or 0xFB (ili9488) or don't know
00212         wr_data8(0xF0|regparam);    // in low nibble specify which reg parameter we want
00213         wr_cmd8(reg);               // now send cmd (select register we want to read)
00214         _DC.write(1); // 1=data
00215         r <<= 8;
00216         r |= _spi.write(0);
00217         // r = _spi.write(0) >> 8; for 16bit
00218     }
00219 _CS = 1; // force CS HIG to interupt the cmd
00220 #ifndef USE_CS //if CS is not used, force fixed LOW again
00221     _CS = 0;
00222 #endif
00223     return r;
00224 }
00225 void SPI8::hw_reset()
00226 {
00227     wait_ms(15);
00228     _DC = 1;
00229  //   _CS = 1;
00230     _CS = 0;
00231     _reset = 0;                        // display reset
00232     wait_us(50);
00233     _reset = 1;                       // end reset
00234     wait_ms(15);
00235 #ifndef USE_CS
00236     _CS=0;      // put CS low now and forever
00237 #endif
00238 }
00239 void SPI8::BusEnable(bool enable)
00240 {
00241     _CS = enable ? 0:1;
00242 }
00243 
00244 // need to re-create SPI firmware to access SPI handle
00245 static SPI_HandleTypeDef SpiHandle;
00246 
00247 void SPI8::fastWrite(int data) {
00248     
00249       SpiHandle.Instance = SPI1;
00250     // Check if data is transmitted
00251     while ((SpiHandle.Instance->SR & SPI_SR_TXE) == 0);
00252     SpiHandle.Instance->DR = data;
00253 }
00254     
00255 void SPI8::clearRX( void ) {
00256         SpiHandle.Instance = SPI1;
00257     //Check if the RX buffer is busy
00258     //While busy, keep checking
00259     while (SpiHandle.Instance->SR & SPI_SR_BSY){   
00260         // Check RX buffer readable
00261         while ((SpiHandle.Instance->SR & SPI_SR_RXNE) == 0);
00262         int dummy = SpiHandle.Instance->DR;
00263     }
00264 }