Basically i glued Peter Drescher and Simon Ford libs in a GraphicsDisplay class, then derived TFT or LCD class (which inherits Protocols class), then the most derived ones (Inits), which are per-display and are the only part needed to be adapted to diff hw.

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 
00021 SPI16::SPI16(int Hz, PinName mosi, PinName miso, PinName sclk, PinName CS, PinName reset, PinName DC)
00022     : _CS(CS), _spi(mosi, miso, sclk), _reset(reset), _DC(DC)
00023 {
00024     _reset = 1;
00025     _DC=1;
00026     _CS=1;
00027     _spi.format(16,0);                  // 8 bit spi mode 0
00028  //   _spi.frequency(12000000);          // 10 Mhz SPI clock, 12mhz for F411
00029     _spi.frequency(Hz);
00030     hw_reset();    
00031 }
00032 
00033 void SPI16::wr_cmd8(unsigned char cmd)
00034 {   
00035     _spi.format(8,0); // it takes time, better use wr_cmd16 with NOP cmd
00036     _DC.write(0); // 0=cmd
00037     _spi.write(cmd);      // write 8bit
00038     _spi.format(16,0);
00039     _DC.write(1); // 1=data next
00040 }
00041 void SPI16::wr_data8(unsigned char data)
00042 {
00043     _spi.format(8,0); // it takes time, check prev cmd parameter, in case use wr_data16 with repeated byte
00044     _spi.write(data);    // write 8bit
00045     _spi.format(16,0);
00046 }
00047 void SPI16::wr_cmd16(unsigned short cmd)
00048 {     
00049     _DC.write(0); // 0=cmd
00050     _spi.write(cmd);      // write 16bit
00051     _DC.write(1); // 1=data next
00052 }
00053 void SPI16::wr_data16(unsigned short data)
00054 {
00055     _spi.write(data);    // write 16bit
00056 }
00057 void SPI16::wr_gram(unsigned short data)
00058 {
00059     _spi.write(data);    // write 16bit
00060 }
00061 void SPI16::wr_gram(unsigned short data, unsigned int count)
00062 {
00063     while(count)
00064     {
00065         _spi.write(data);
00066         count--;
00067     }
00068 }
00069 void SPI16::wr_grambuf(unsigned short* data, unsigned int lenght)
00070 {
00071     while(lenght)
00072     {
00073         _spi.write(*data);
00074         data++;
00075         lenght--;
00076     }
00077 }
00078 unsigned short SPI16::rd_gram(bool convert)
00079 {
00080     unsigned int r=0;
00081     r |= _spi.write(0); // 16bit, whole first byte is dummy, second is red
00082     r <<= 16;
00083     r |= _spi.write(0);  
00084     if(convert)
00085     {
00086         // gram is 18bit/pixel, if you set 16bit/pixel (cmd 3A), during writing the 16bits are expanded to 18bit
00087         // during reading, you read the raw 18bit gram
00088         r = RGB24to16((r&0xFF0000)>>16, (r&0xFF00)>>8, r&0xFF);// 18bit pixel padded to 24bits, rrrrrr00_gggggg00_bbbbbb00, converted to 16bit
00089     }
00090     else r >>= 8;
00091     _CS = 1; // force CS HIG to interupt the "read state"
00092     _CS = 0;
00093 
00094     return (unsigned short)r;
00095 }
00096 unsigned int SPI16::rd_reg_data32(unsigned char reg)
00097 {
00098     wr_cmd8(reg);
00099     unsigned int r=0;
00100    
00101     r |= _spi.write(0); // we get only 15bit valid, first bit was the dummy cycle
00102     r <<= 16;
00103     r |= _spi.write(0);
00104     r <<= 1; // 32bits are aligned, now collecting bit_0
00105     r |= (_spi.write(0) >> 15);
00106     // we clocked 15 more bit so ILI waiting for 16th, we need to reset spi bus
00107     _CS = 1; // force CS HIG to interupt the cmd
00108     _CS = 0;
00109     return r;
00110 }
00111 unsigned int SPI16::rd_extcreg_data32(unsigned char reg, unsigned char SPIreadenablecmd)
00112 {
00113     unsigned int r=0;
00114     for(int regparam=1; regparam<4; regparam++) // when reading EXTC regs, first parameter is always dummy, so start with 1
00115     {
00116         wr_cmd8(SPIreadenablecmd);  // spi-in enable cmd, 0xD9 (ili9341) or 0xFB (ili9488) or don't know
00117         wr_data8(0xF0|regparam);    // in low nibble specify which reg parameter we want
00118         wr_cmd8(reg);               // now send cmd (select register we want to read)
00119         r <<= 8;
00120         r |= (_spi.write(0) >> 8);
00121     }
00122     _CS = 1; // force CS HIG to interupt the cmd
00123     _CS = 0;
00124 
00125     return r;
00126 }
00127 // ILI932x specific
00128 void SPI16::dummyread()
00129 {
00130     _spi.write(0);    // dummy read
00131 }
00132 // ILI932x specific
00133 void SPI16::reg_select(unsigned char reg, bool forread)
00134 {
00135     _CS = 1;    //fixme: really needed?
00136     _CS = 0;    //fixme: really needed?
00137     _spi.write(0x70);   // write 0070
00138     _spi.write(reg);    // write 16bit
00139     _CS = 1;    //fixme: really needed?
00140     _CS = 0;    //fixme: really needed?
00141     if(forread) _spi.write(0x73);
00142     else _spi.write(0x72);
00143 }
00144 // ILI932x specific
00145 void SPI16::reg_write(unsigned char reg, unsigned short data)
00146 {
00147     _CS = 1;    //fixme: really needed?
00148     _CS = 0;    //fixme: really needed?
00149     _spi.write(0x70);   // write 0070
00150     _spi.write(reg);    // write 16bit
00151     _CS = 1;    //fixme: really needed?
00152     _CS = 0;    //fixme: really needed?
00153     _spi.write(0x72);   // write 0072 
00154     _spi.write(data);   // write 16bit
00155 }
00156 // ILI932x specific
00157 unsigned short SPI16::reg_read(unsigned char reg)
00158 {
00159     unsigned int r=0;
00160     _CS = 1;    //fixme: really needed?
00161     _CS = 0;    //fixme: really needed?
00162     _spi.write(0x70);   // write 0070
00163     _spi.write(reg);    // write 16bit
00164     _CS = 1;    //fixme: really needed?
00165     _CS = 0;    //fixme: really needed?
00166     _spi.write(0x73);   // write 0073
00167     r |= _spi.write(0);    // read 16bit, 8bit dummy + 8bit valid
00168     r <<= 16;
00169     r |= _spi.write(0);    // read 16bit
00170     
00171     _CS = 1; //fixme: to resync, maybe really needed
00172     _CS = 0; //fixme: to resync, maybe really needed
00173     return (r>>8);
00174 }
00175 void SPI16::hw_reset()
00176 {
00177     wait_ms(15);
00178     _DC = 1;
00179     _CS = 1;
00180     _reset = 0;                        // display reset
00181     wait_ms(2);
00182     _reset = 1;                       // end reset
00183     wait_ms(100);
00184 }
00185 void SPI16::BusEnable(bool enable)
00186 {
00187     _CS = enable ? 0:1;
00188 }