3 #include "interrupts.h"
12 * Note that this is not a normal SPI interface,
13 * it is a bodged version as used by the NXT's
16 * The display does not use MISO because you can
17 * only write to it in serial mode.
19 * Instead, the MISO pin is not used by the SPI
20 * and is instead driven as a PIO pin for controlling CD.
22 * Addional notes from Andy Shaw
23 * The following code now contains the capability to perform display
24 * updates using dma, This code was inspired by the nxos lcd/spi code
25 * (Thanks guys). More details of nxos can be found at:
26 * http://nxt.natulte.net/nxos/trac
31 #define CS_PIN (1<<10)
32 #define CD_PIN (1<<12)
33 const U8 *display = (U8 *) 0;
34 volatile U8 dirty = 0;
36 volatile const U8 *data = (U8 *) 0;
39 extern void spi_isr_entry(void);
41 static void spi_set_mode(U8 m)
45 /* nothing to do if we are already in the correct mode */
46 if (m == mode) return;
48 /* Wait until all bytes have been sent */
50 status = *AT91C_SPI_SR;
51 } while (!(status & 0x200));
52 /* Set command or data mode */
54 *AT91C_PIOA_SODR = CD_PIN;
56 *AT91C_PIOA_CODR = CD_PIN;
57 /* remember the current mode */
67 /* Check to see if we have data to display */
75 /* No so turn things off. It will get re-set if we ever have anything
78 *AT91C_SPI_IDR = AT91C_SPI_ENDTX;
82 /* Make sure we are in data mode */
84 /* now do the transfer. We make use of the auto-wrap function so simply
85 * need to send 8*132 bytes to get back to where we started. However the
86 * display buffer is structured as series of 100 byte lines, so we need to
87 * get tricky. I've made the display one line longer (9 lines) and so when we
88 * send the data we send 100 bytes from the actual line plus 32 padding bytes
89 * (that are not actually seen), from the next line. The extra line means
90 * that this is safe to do. If we can redefine the display as a 8*132 then
91 * we could just use a single dma transfer (instead of 8, 132 byte ones).
92 * However I'm not sure if this would be safe.
94 *AT91C_SPI_TNPR = (U32) data;
95 *AT91C_SPI_TNCR = 132;
96 page = (page + 1) % 8;
104 int i_state = interrupts_get_and_disable();
106 #define SPI_BITRATE 2000000
108 *AT91C_PMC_PCER = (1L << AT91C_ID_SPI); /* Enable MCK clock */
109 *AT91C_PIOA_PER = AT91C_PIO_PA12;/*EnableA0onPA12*/
110 *AT91C_PIOA_OER = AT91C_PIO_PA12;
111 *AT91C_PIOA_CODR = AT91C_PIO_PA12;
112 *AT91C_PIOA_PDR = AT91C_PA14_SPCK;/*EnableSPCKonPA14*/
113 *AT91C_PIOA_ASR = AT91C_PA14_SPCK;
114 *AT91C_PIOA_ODR = AT91C_PA14_SPCK;
115 *AT91C_PIOA_OWER = AT91C_PA14_SPCK;
116 *AT91C_PIOA_MDDR = AT91C_PA14_SPCK;
117 *AT91C_PIOA_PPUDR = AT91C_PA14_SPCK;
118 *AT91C_PIOA_IFDR = AT91C_PA14_SPCK;
119 *AT91C_PIOA_CODR = AT91C_PA14_SPCK;
120 *AT91C_PIOA_IDR = AT91C_PA14_SPCK;
121 *AT91C_PIOA_PDR = AT91C_PA13_MOSI;/*EnablemosionPA13*/
122 *AT91C_PIOA_ASR = AT91C_PA13_MOSI;
123 *AT91C_PIOA_ODR = AT91C_PA13_MOSI;
124 *AT91C_PIOA_OWER = AT91C_PA13_MOSI;
125 *AT91C_PIOA_MDDR = AT91C_PA13_MOSI;
126 *AT91C_PIOA_PPUDR = AT91C_PA13_MOSI;
127 *AT91C_PIOA_IFDR = AT91C_PA13_MOSI;
128 *AT91C_PIOA_CODR = AT91C_PA13_MOSI;
129 *AT91C_PIOA_IDR = AT91C_PA13_MOSI;
130 *AT91C_PIOA_PDR = AT91C_PA10_NPCS2;/*Enablenpcs0onPA10*/
131 *AT91C_PIOA_BSR = AT91C_PA10_NPCS2;
132 *AT91C_PIOA_ODR = AT91C_PA10_NPCS2;
133 *AT91C_PIOA_OWER = AT91C_PA10_NPCS2;
134 *AT91C_PIOA_MDDR = AT91C_PA10_NPCS2;
135 *AT91C_PIOA_PPUDR = AT91C_PA10_NPCS2;
136 *AT91C_PIOA_IFDR = AT91C_PA10_NPCS2;
137 *AT91C_PIOA_CODR = AT91C_PA10_NPCS2;
138 *AT91C_PIOA_IDR = AT91C_PA10_NPCS2;
139 *AT91C_SPI_CR = AT91C_SPI_SWRST;/*Softreset*/
140 *AT91C_SPI_CR = AT91C_SPI_SPIEN;/*Enablespi*/
141 *AT91C_SPI_MR = AT91C_SPI_MSTR|AT91C_SPI_MODFDIS | (0xB<<16);
142 AT91C_SPI_CSR[2] = ((OSC/SPI_BITRATE)<<8) | AT91C_SPI_CPOL;
144 /* Set mode to unknown */
147 /* Set up safe dma refresh state */
148 data = display = (U8 *) 0;
152 /* Install the interrupt handler */
153 aic_mask_off(AT91C_PERIPHERAL_ID_SPI);
154 aic_set_vector(AT91C_PERIPHERAL_ID_SPI, AIC_INT_LEVEL_NORMAL, (U32)spi_isr_entry);
155 aic_mask_on(AT91C_PERIPHERAL_ID_SPI);
156 *AT91C_SPI_PTCR = AT91C_PDC_TXTEN;
164 nxt_spi_write(U32 CD, const U8 *data, U32 nBytes)
167 U32 cd_mask = (CD ? 0x100 : 0);
171 *AT91C_SPI_TDR = (*data | cd_mask);
174 /* Wait until byte sent */
176 status = *AT91C_SPI_SR;
177 } while (!(status & 0x200));
183 nxt_spi_set_display(const U8 *disp)
185 /* Set the display buffer to be used for dma refresh.
186 * it is really only safe to set the display once. Should probably
187 * sort this out so that it is set separately from requesting a refresh
189 if (!display) display = disp;
193 nxt_spi_refresh(void)
195 /* Request the start of a dma refresh of the display
197 // If the display is not set nothing to do.
198 if (!display) return;
199 // Say we have changes
201 // Start the DMA refresh
202 *AT91C_SPI_IER = AT91C_SPI_ENDTX;