/ MCUME_teensy / teensyuae / psram_t.cpp
psram_t.cpp
  1  /*
  2    PSRAM driver for IPS6404
  3  */
  4  
  5  #include "psram_t.h"
  6  
  7  Page PSRAM_T::pages[MAX_PAGES];
  8  uint8_t PSRAM_T::nbPages=0;
  9  int8_t PSRAM_T::top=0;
 10  int8_t PSRAM_T::last=0;
 11  
 12  
 13  #ifdef HAS_PSRAM
 14  
 15  #include <SPI.h>
 16  #include <DMAChannel.h>
 17  
 18  #define SPI SPI2
 19  
 20  //#define SPICLOCK 104000000 
 21  #define SPICLOCK 70000000 
 22  //#define SPICLOCK 144e6 //Just a number..max speed
 23  #define SPI_MODE SPI_MODE0
 24  
 25  #define RAM_READ  0xB
 26  //#define RAM_READ  0x3
 27  #define RAM_WRITE 0x2
 28  
 29  
 30  uint8_t PSRAM_T::_cs, PSRAM_T::_miso, PSRAM_T::_mosi, PSRAM_T::_sclk;
 31  
 32  
 33  PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
 34  {
 35    _cs   = cs;
 36    _mosi = mosi;
 37    _sclk = sclk;
 38    _miso = miso;
 39    pinMode(_cs, OUTPUT); 
 40    digitalWrite(_cs, 1);
 41  }
 42  
 43  
 44  void PSRAM_T::begin(void)
 45  {
 46    SPI.setMOSI(_mosi);
 47    SPI.setMISO(_miso);
 48    SPI.setSCK(_sclk);
 49    SPI.begin();
 50  
 51    delay(1);
 52  
 53    digitalWrite(_cs, 0);
 54    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 55    SPI.transfer(0x66);
 56    digitalWrite(_cs, 1);
 57    SPI.endTransaction();  
 58    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 59    digitalWrite(_cs, 0);
 60    SPI.transfer(0x99);
 61    SPI.endTransaction();
 62    digitalWrite(_cs, 1);
 63    delayMicroseconds(20);
 64  }
 65  
 66  
 67  
 68  uint8_t PSRAM_T::psram_read(uint32_t addr) 
 69  {
 70    uint8_t val=0;
 71  
 72    digitalWrite(_cs, 0);  
 73    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 74    SPI.transfer(RAM_READ);
 75    SPI.transfer((addr>>16)&0xff);
 76    SPI.transfer((addr>>8)&0xff);
 77    SPI.transfer(addr&0xff);
 78  #if RAM_READ == 0xB  
 79    SPI.transfer(0xFF);       
 80  #endif
 81    val = SPI.transfer(0xFF);  
 82    SPI.endTransaction();
 83    digitalWrite(_cs, 1);
 84    return val;
 85  }
 86  
 87  
 88  void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 
 89  {
 90    digitalWrite(_cs, 0);
 91    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
 92    SPI.transfer(RAM_READ);
 93    SPI.transfer((addr>>16)&0xff);
 94    SPI.transfer((addr>>8)&0xff);
 95    SPI.transfer(addr&0xff);
 96  #if RAM_READ == 0xB  
 97    SPI.transfer(0xFF);       
 98  #endif
 99    /*
100    while (n > 0) {
101      *val++ = SPI.transfer(0xFF);
102      n--;       
103    }    
104    */
105    SPI.transfer(val,n);
106    SPI.endTransaction();
107    digitalWrite(_cs, 1);
108  }
109  
110  
111  void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 
112  {
113    digitalWrite(_cs, 0);
114    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
115    SPI.transfer(RAM_WRITE);
116    SPI.transfer((addr>>16)&0xff);
117    SPI.transfer((addr>>8)&0xff);
118    SPI.transfer(addr&0xff);    
119    SPI.transfer(val);
120    SPI.endTransaction();    
121    digitalWrite(_cs, 1);
122  }
123  
124  static uint8_t resp[PAGE_SIZE];
125  
126  
127  void PSRAM_T::psram_write_n(uint32_t addr, uint8_t * val, int n) 
128  {
129    digitalWrite(_cs, 0);
130    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
131    SPI.transfer(RAM_WRITE);
132    SPI.transfer((addr>>16)&0xff);
133    SPI.transfer((addr>>8)&0xff);
134    SPI.transfer(addr&0xff);
135    /*
136    while (n > 0) {
137      SPI.transfer(*val++);
138      n--;       
139    }
140    */
141    SPI.transfer(val,&resp[0],n);
142    SPI.endTransaction();  
143    digitalWrite(_cs, 1); 
144  }
145  
146  
147  #ifdef DMATRY
148  #include <DMAChannel.h>
149  
150  DMAMEM static uint8_t src[PAGE_SIZE+4]; 
151  DMAMEM static uint8_t dst[PAGE_SIZE+4];
152  static DMASetting dmasettings[8];
153  static DMAChannel dmatx;
154  static volatile uint8_t rstop = 0;
155  
156  #define DMASPI_PRINT(x) do {Serial.printf(x) ; Serial.flush();} while (0);
157  
158  static void dmaInterrupt() 
159  {
160    dmatx.clearInterrupt();
161    rstop = 1;  
162    //DMASPI_PRINT("irq");
163  }
164  
165  void PSRAM_T::psram_write_n_dma(uint32_t addr, uint8_t * val, int n) {
166    uint8_t * dstPt = &dst[0];
167    //*dstPt++ = RAM_WRITE;
168    //*dstPt++ = (addr>>16)&0xff;
169    //*dstPt++ = (addr>>8)&0xff;
170    //*dstPt++ = addr&0xff;
171    int cnt = n;
172    while (cnt > 0) {
173      *dstPt++ = *val++;
174      cnt--;       
175    }    
176    arm_dcache_flush(&dst[0], n);
177    rstop = 0;     
178    dmatx.disable();
179    dmatx.attachInterrupt(dmaInterrupt);
180  
181    dmasettings[0].sourceBuffer(&dst[0], n);
182    //dmasettings[0].destination((uint8_t &)  LPSPI4_TDR);
183    dmasettings[0].destination((uint8_t &)  IMXRT_LPSPI1_S.TDR);
184    dmasettings[0].TCD->ATTR_DST = 1;
185    dmasettings[0].interruptAtCompletion();
186  
187  Serial.printf("A") ; Serial.flush();
188  
189    digitalWrite(_cs, HIGH);
190   // SPI.begin();
191    SPI.beginTransaction(SPISettings(SPICLOCK, MSBFIRST, SPI_MODE));
192  
193    digitalWrite(_cs, 0); 
194    SPI.transfer(RAM_WRITE);
195    SPI.transfer((addr>>16)&0xff);
196    SPI.transfer((addr>>8)&0xff);
197    SPI.transfer(addr&0xff);
198    //SPI.transfer(0);
199    //SPI.transfer(1);
200  Serial.printf("B") ; Serial.flush();
201  
202  #ifdef XXX           
203    LPSPI4_CR &= ~LPSPI_CR_MEN;//disable LPSPI:
204    LPSPI4_CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX
205    //LPSPI4_TCR = 15; // Framesize 16 Bits
206    IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
207     LPSPI4_DER = LPSPI_DER_TDDE; //TX DMA Request Enable
208     // IMXRT_LPSPI4_S.DER = LPSPI_DER_TDDE; // | LPSPI_DER_RDDE; //enable DMA on both TX and RX
209    LPSPI4_CR |= LPSPI_CR_MEN; //enable LPSPI:
210     //IMXRT_LPSPI4_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
211    //  IMXRT_LPSPI4_S.FCR = 0; 
212      // Lets try to output the first byte to make sure that we are in 8 bit mode...
213   //   IMXRT_LPSPI4_S.SR = 0x3f00; // clear out all of the other status...
214     
215    dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI4_TX );
216  #endif
217    IMXRT_LPSPI1_S.CR &= ~LPSPI_CR_MEN;//disable LPSPI:
218    IMXRT_LPSPI1_S.CFGR1 |= LPSPI_CFGR1_NOSTALL; //prevent stall from RX
219    IMXRT_LPSPI1_S.TCR = (IMXRT_LPSPI4_S.TCR & ~(LPSPI_TCR_FRAMESZ(31))) | LPSPI_TCR_FRAMESZ(7);  
220    IMXRT_LPSPI1_S.DER = LPSPI_DER_TDDE; //TX DMA Request Enable
221    IMXRT_LPSPI1_S.CR |= LPSPI_CR_MEN; //enable LPSPI:
222    dmatx.triggerAtHardwareEvent( DMAMUX_SOURCE_LPSPI1_TX );
223  Serial.printf("C") ; Serial.flush();
224  //  SPI.initDMAChannels();
225    dmatx = dmasettings[0];
226        
227    dmatx.enable();
228  Serial.printf("D") ; Serial.flush();
229    while (rstop == 0) {};
230  
231   Serial.printf("E") ; Serial.flush();
232    digitalWrite(_cs, 1);
233  }
234  #endif
235  
236  
237  
238  #else
239  
240  
241  #include "emuapi.h"
242  
243  
244  PSRAM_T::PSRAM_T(uint8_t cs, uint8_t mosi, uint8_t sclk, uint8_t miso)
245  {
246  }
247  
248  void PSRAM_T::begin(void)
249  {
250    emu_FileTempInit();
251  }
252  
253  void PSRAM_T::psram_read_n(uint32_t addr, uint8_t * val, int n) 
254  {
255    emu_FileTempRead(addr,val,n);    
256  }
257  
258  
259  void PSRAM_T::psram_write(uint32_t addr, uint8_t val) 
260  {
261    emu_FileTempWrite(addr,val);  
262  }
263  
264  #endif
265  
266  
267  
268  void PSRAM_T::pswrite(uint32_t addr, uint8_t val) 
269  {
270    psram_write(addr, val);
271    //return;
272    uint32_t curPage=addr&(~(PAGE_SIZE-1));
273    for (int i=0; i<nbPages; i++) {
274      if (pages[i].pageid == curPage) {
275        pages[i].page[addr&(PAGE_SIZE-1)] = val;
276        break;
277      }
278    }   
279  }
280  
281  
282  
283  
284  uint8_t PSRAM_T::psread(uint32_t addr) 
285  {
286    //uint8_t val = psram_read(addr);
287    //return val;
288    uint32_t curPage=addr&(~(PAGE_SIZE-1));
289    uint32_t offs = addr&(PAGE_SIZE-1);
290  
291    for (int i=0; i<nbPages; i++) {
292      if (pages[i].pageid == curPage) {
293        if ( (pages[i].prev != i) && (pages[i].next != i) ) {
294          pages[pages[i].prev].next =  pages[i].next;
295          pages[pages[i].next].prev = pages[i].prev;     
296        }
297        else if (pages[i].next != i) {
298          pages[pages[i].next].prev = i;
299        }
300        else if (pages[i].prev != i) {
301          pages[pages[i].prev].next =  pages[i].prev;
302          last = pages[i].prev;        
303        }
304         // last page accessed to top
305        pages[i].prev = i; //-1;
306        pages[i].next = top;      
307        pages[top].prev = i;
308        top = i;
309        return pages[top].page[offs];
310      }
311    }
312    if (nbPages<MAX_PAGES) 
313    {
314      // add at top
315      pages[nbPages].pageid = curPage;           
316      pages[nbPages].prev = nbPages; //-1;
317      pages[nbPages].next = top;     
318      pages[top].prev = nbPages;
319      top = nbPages;
320      nbPages++;
321    }
322    else {
323        // replace last and move to top
324        int n = pages[last].prev;
325        pages[n].next = n; //-1;
326        pages[last].pageid = curPage;
327        pages[last].prev = last; //-1;
328        pages[last].next = top;      
329        pages[top].prev = last;
330        top = last;
331        last = n;
332    }
333    //emu_printi(curPage);
334    psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);   
335    return pages[top].page[offs];
336  }
337  
338  uint16_t PSRAM_T::psread_w(uint32_t addr) 
339  {
340    uint32_t curPage=addr&(~(PAGE_SIZE-1));
341    uint32_t offs = addr&(PAGE_SIZE-1);
342  
343    for (int i=0; i<nbPages; i++) {
344      if (pages[i].pageid == curPage) {
345        if ( (pages[i].prev != i) && (pages[i].next != i) ) {
346          pages[pages[i].prev].next =  pages[i].next;
347          pages[pages[i].next].prev = pages[i].prev;     
348        }
349        else if (pages[i].next != i) {
350          pages[pages[i].next].prev = i;
351        }
352        else if (pages[i].prev != i) {
353          pages[pages[i].prev].next =  pages[i].prev;
354          last = pages[i].prev;        
355        }
356         // last page accessed to top
357        pages[i].prev = i; //-1;
358        pages[i].next = top;      
359        pages[top].prev = i;
360        top = i;     
361        return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
362      }
363    }
364    if (nbPages<MAX_PAGES) 
365    {
366      // add at top
367      pages[nbPages].pageid = curPage;           
368      pages[nbPages].prev = nbPages; //-1;
369      pages[nbPages].next = top;     
370      pages[top].prev = nbPages;
371      top = nbPages;
372      nbPages++;
373    }
374    else {
375        // replace last and move to top
376        int n = pages[last].prev;
377        pages[n].next = n; //-1;
378        pages[last].pageid = curPage;
379        pages[last].prev = last; //-1;
380        pages[last].next = top;      
381        pages[top].prev = last;
382        top = last;
383        last = n;
384    }
385    //emu_printi(curPage);
386    psram_read_n(curPage,&(pages[top].page[0]),PAGE_SIZE);   
387    return (pages[top].page[offs+1]<<8) + pages[top].page[offs];
388  }
389  
390