3 #include "lpc17xx_clkpwr.h"
4 #include "lpc17xx_pinsel.h"
5 #include "lpc17xx_ssp.h"
6 #include "lpc17xx_gpio.h"
10 SPI
* SPI::isr_dispatch
[N_SPI_INTERRUPT_ROUTINES
];
14 SPI::SPI(PinName mosi
, PinName miso
, PinName sclk
)
16 this->mosi
.port
= (mosi
>> 5) & 7;
17 this->mosi
.pin
= mosi
& 0x1F;
19 this->miso
.port
= (miso
>> 5) & 7;
20 this->miso
.pin
= miso
& 0x1F;
22 this->sclk
.port
= (sclk
>> 5) & 7;
23 this->sclk
.pin
= sclk
& 0x1F;
25 FIO_SetDir(this->mosi
.port
, 1UL << this->mosi
.pin
, 1);
26 FIO_SetDir(this->miso
.port
, 1UL << this->miso
.pin
, 0);
27 FIO_SetDir(this->sclk
.port
, 1UL << this->sclk
.pin
, 1);
29 if (mosi
== P0_9
&& miso
== P0_8
&& sclk
== P0_7
)
31 // iprintf("SPI: using 0.7,0.8,0.9 with SSP1\n");
32 // SSP1 on 0.7,0.8,0.9
34 isr_dispatch
[1] = this;
36 LPC_PINCON
->PINSEL0
&= ~((3 << (7*2)) | (3 << (8*2)) | (3 << (9*2)));
37 LPC_PINCON
->PINSEL0
|= ((2 << (7*2)) | (2 << (8*2)) | (2 << (9*2)));
39 LPC_SC
->PCLKSEL0
&= 0xFFCFFFFF;
40 LPC_SC
->PCLKSEL0
|= 0x00100000;
42 LPC_SC
->PCONP
|= CLKPWR_PCONP_PCSSP1
;
44 else if (mosi
== P0_18
&& miso
== P0_17
&& sclk
== P0_15
)
46 // iprintf("SPI: using 0.15,0.17,0.18 with SSP0\n");
47 // SSP0 on 0.15,0.16,0.17,0.18
49 isr_dispatch
[0] = this;
51 LPC_PINCON
->PINSEL0
&= ~(3 << (15*2));
52 LPC_PINCON
->PINSEL0
|= (2 << (15*2));
53 LPC_PINCON
->PINSEL1
&= ~( (3 << ((17*2)&30)) | (3 << ((18*2)&30)) );
54 LPC_PINCON
->PINSEL1
|= ( (2 << ((17*2)&30)) | (2 << ((18*2)&30)) );
56 LPC_SC
->PCLKSEL1
&= 0xFFFFF3FF;
57 LPC_SC
->PCLKSEL1
|= 0x00000400;
59 LPC_SC
->PCONP
|= CLKPWR_PCONP_PCSSP0
;
61 else if (mosi
== P1_24
&& miso
== P1_23
&& sclk
== P1_20
)
63 // iprintf("SPI: using 1.20,1.23,1.24 with SSP0\n");
64 // SSP0 on 1.20,1.23,1.24
66 isr_dispatch
[0] = this;
68 // // LPC_PINCON->PINSEL3 &= 0xFFFC3CFF;
69 // LPC_PINCON->PINSEL3 |= 0x0003C300;
71 // LPC_PINCON->PINSEL3 &= ~( (3 << ((20*2)&30)) | (3 << ((23*2)&30)) | (3 << ((24*2)&30)) );
72 LPC_PINCON
->PINSEL3
|= ( (3 << ((20*2)&30)) | (3 << ((23*2)&30)) | (3 << ((24*2)&30)) );
74 LPC_SC
->PCLKSEL1
&= 0xFFFFF3FF;
75 LPC_SC
->PCLKSEL1
|= 0x00000400;
77 LPC_SC
->PCONP
|= CLKPWR_PCONP_PCSSP0
;
81 // iprintf("SPI: using soft-SPI\n");
82 sspr
= (LPC_SSP_TypeDef
*) 0;
86 sspr
->CR0
= SSP_DATABIT_8
|
88 sspr
->CR1
= SSP_MASTER_MODE
;
90 sspr
->CR1
|= SSP_CR1_SSP_EN
;
97 LPC_SC
->PCONP
&= CLKPWR_PCONP_PCSSP0
;
98 else if (sspr
== LPC_SSP1
)
99 LPC_SC
->PCONP
&= CLKPWR_PCONP_PCSSP1
;
102 void SPI::frequency(uint32_t f
)
105 // CPSR = 2 to 254, even only
106 // CR0[8:15] (SCR, 0..255) is a further prescale
108 // iprintf("SPI: frequency %lu:", f);
109 delay
= 25000000 / f
;
110 // f = 25MHz / (CPSR . [SCR + 1])
111 // CPSR . (SCR + 1) = 25MHz / f
112 // min freq is 25MHz / (254 * 256)
117 sspr
->CR0
|= 255 << 8;
119 // max freq is 25MHz / (2 * 1)
120 else if (f
> 12500000) {
125 sspr
->CPSR
= delay
& 0xFE;
126 // CPSR . (SCR + 1) = f;
127 // (SCR + 1) = f / CPSR;
128 // SCR = (f / CPSR) - 1
130 sspr
->CR0
|= (((delay
/ sspr
->CPSR
) - 1) & 0xFF) << 8;
132 // iprintf(" CPSR=%lu, CR0=%lu", sspr->CPSR, sspr->CR0);
137 void _delay(uint32_t ticks
) {
139 asm volatile("nop\n\t");
142 uint8_t SPI::write(uint8_t data
)
146 // iprintf("SPI: >0x%02X", data);
148 while ((sspr
->SR
& SSP_SR_TNF
) == 0);
150 while ((sspr
->SR
& SSP_SR_RNE
) == 0);
154 for (int i
= 0; i
< 8; i
++) {
155 FIO_ClearValue(sclk
.port
, 1UL << sclk
.pin
); // clock LOW
157 if (data
& 0x80) // WRITE
158 FIO_SetValue(mosi
.port
, 1UL << mosi
.pin
);
160 FIO_ClearValue(mosi
.port
, 1UL << mosi
.pin
);
163 _delay(delay
>> 1); // DELAY
165 FIO_SetValue(sclk
.port
, 1UL << sclk
.pin
); // clock HIGH
167 _delay(delay
>> 1); // DELAY
170 if (FIO_ReadValue(miso
.port
) & (1UL << miso
.pin
)) // READ
173 FIO_ClearValue(sclk
.port
, 1UL << sclk
.pin
);
175 // iprintf(" <0x%02X\n", r);
179 // TODO: timer feeds DMA feeds 0xFFs to card then we listen for responses using our interrupt
180 // allow me to do something like:
181 // disk.start_multi_write(int blocks, int blocksize, void *buffer);
185 // if (disk.buffer_in_use(void *buffer))
187 // usb_ep_read(buffer);
189 // disk.validate_buffer(buffer);
190 // if (disk.finished_transfer())
191 // disk.end_multi_write();
196 return (sspr
!= NULL
);
199 // int SPI::setup_DMA_rx(DMA_REG *dma)
204 // dma->DMACCControl = 0;
205 // dma->DMACCConfiguration = 0;
206 // if (sspr == LPC_SSP0)
207 // dma->DMACCConfiguration |= (GPDMA_CONN_SSP0_Rx << 6);
208 // if (sspr == LPC_SSP1)
209 // dma->DMACCConfiguration |= (GPDMA_CONN_SSP1_Rx << 6);
211 // dma->DMACCConfiguration |= GPDMA_TRANSFERTYPE_M2P << 11;
215 // int SPI::start_DMA_rx(DMA_REG *dma)
217 // dma->DMACCConfiguration |=
220 // int SPI::writeblock(uint8_t *block, int blocklen)
222 // static DMA *d = new DMA();
223 // d.sourceaddr(block);
224 // d.transferlength(blocklen);
225 // d.destinationperipheral(sspr);
227 // while (d.active());
236 void SSP0_IRQHandler(void) {
237 if (SPI::isr_dispatch
[0])
238 SPI::isr_dispatch
[0]->irq();
241 void SSP1_IRQHandler(void) {
242 if (SPI::isr_dispatch
[1])
243 (SPI::isr_dispatch
[1])->irq();