Fork of Smoothie to port to mbed non-LPC targets.

Dependencies:   mbed

Fork of Smoothie by Stéphane Cachat

Committer:
Michael J. Spencer
Date:
Fri Feb 28 18:52:52 2014 -0800
Revision:
2:1df0b61d3b5a
Update to latest Smoothie.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Michael J. Spencer 2:1df0b61d3b5a 1 #include "spi.h"
Michael J. Spencer 2:1df0b61d3b5a 2
Michael J. Spencer 2:1df0b61d3b5a 3 #include "lpc17xx_clkpwr.h"
Michael J. Spencer 2:1df0b61d3b5a 4 #include "lpc17xx_pinsel.h"
Michael J. Spencer 2:1df0b61d3b5a 5 #include "lpc17xx_ssp.h"
Michael J. Spencer 2:1df0b61d3b5a 6 #include "lpc17xx_gpio.h"
Michael J. Spencer 2:1df0b61d3b5a 7
Michael J. Spencer 2:1df0b61d3b5a 8 #include <stdio.h>
Michael J. Spencer 2:1df0b61d3b5a 9
Michael J. Spencer 2:1df0b61d3b5a 10 SPI* SPI::isr_dispatch[N_SPI_INTERRUPT_ROUTINES];
Michael J. Spencer 2:1df0b61d3b5a 11
Michael J. Spencer 2:1df0b61d3b5a 12 class DMA;
Michael J. Spencer 2:1df0b61d3b5a 13
Michael J. Spencer 2:1df0b61d3b5a 14 SPI::SPI(PinName mosi, PinName miso, PinName sclk)
Michael J. Spencer 2:1df0b61d3b5a 15 {
Michael J. Spencer 2:1df0b61d3b5a 16 this->mosi.port = (mosi >> 5) & 7;
Michael J. Spencer 2:1df0b61d3b5a 17 this->mosi.pin = mosi & 0x1F;
Michael J. Spencer 2:1df0b61d3b5a 18
Michael J. Spencer 2:1df0b61d3b5a 19 this->miso.port = (miso >> 5) & 7;
Michael J. Spencer 2:1df0b61d3b5a 20 this->miso.pin = miso & 0x1F;
Michael J. Spencer 2:1df0b61d3b5a 21
Michael J. Spencer 2:1df0b61d3b5a 22 this->sclk.port = (sclk >> 5) & 7;
Michael J. Spencer 2:1df0b61d3b5a 23 this->sclk.pin = sclk & 0x1F;
Michael J. Spencer 2:1df0b61d3b5a 24
Michael J. Spencer 2:1df0b61d3b5a 25 FIO_SetDir(this->mosi.port, 1UL << this->mosi.pin, 1);
Michael J. Spencer 2:1df0b61d3b5a 26 FIO_SetDir(this->miso.port, 1UL << this->miso.pin, 0);
Michael J. Spencer 2:1df0b61d3b5a 27 FIO_SetDir(this->sclk.port, 1UL << this->sclk.pin, 1);
Michael J. Spencer 2:1df0b61d3b5a 28
Michael J. Spencer 2:1df0b61d3b5a 29 if (mosi == P0_9 && miso == P0_8 && sclk == P0_7)
Michael J. Spencer 2:1df0b61d3b5a 30 {
Michael J. Spencer 2:1df0b61d3b5a 31 // iprintf("SPI: using 0.7,0.8,0.9 with SSP1\n");
Michael J. Spencer 2:1df0b61d3b5a 32 // SSP1 on 0.7,0.8,0.9
Michael J. Spencer 2:1df0b61d3b5a 33 sspr = LPC_SSP1;
Michael J. Spencer 2:1df0b61d3b5a 34 isr_dispatch[1] = this;
Michael J. Spencer 2:1df0b61d3b5a 35
Michael J. Spencer 2:1df0b61d3b5a 36 LPC_PINCON->PINSEL0 &= ~((3 << (7*2)) | (3 << (8*2)) | (3 << (9*2)));
Michael J. Spencer 2:1df0b61d3b5a 37 LPC_PINCON->PINSEL0 |= ((2 << (7*2)) | (2 << (8*2)) | (2 << (9*2)));
Michael J. Spencer 2:1df0b61d3b5a 38
Michael J. Spencer 2:1df0b61d3b5a 39 LPC_SC->PCLKSEL0 &= 0xFFCFFFFF;
Michael J. Spencer 2:1df0b61d3b5a 40 LPC_SC->PCLKSEL0 |= 0x00100000;
Michael J. Spencer 2:1df0b61d3b5a 41
Michael J. Spencer 2:1df0b61d3b5a 42 LPC_SC->PCONP |= CLKPWR_PCONP_PCSSP1;
Michael J. Spencer 2:1df0b61d3b5a 43 }
Michael J. Spencer 2:1df0b61d3b5a 44 else if (mosi == P0_18 && miso == P0_17 && sclk == P0_15)
Michael J. Spencer 2:1df0b61d3b5a 45 {
Michael J. Spencer 2:1df0b61d3b5a 46 // iprintf("SPI: using 0.15,0.17,0.18 with SSP0\n");
Michael J. Spencer 2:1df0b61d3b5a 47 // SSP0 on 0.15,0.16,0.17,0.18
Michael J. Spencer 2:1df0b61d3b5a 48 sspr = LPC_SSP0;
Michael J. Spencer 2:1df0b61d3b5a 49 isr_dispatch[0] = this;
Michael J. Spencer 2:1df0b61d3b5a 50
Michael J. Spencer 2:1df0b61d3b5a 51 LPC_PINCON->PINSEL0 &= ~(3 << (15*2));
Michael J. Spencer 2:1df0b61d3b5a 52 LPC_PINCON->PINSEL0 |= (2 << (15*2));
Michael J. Spencer 2:1df0b61d3b5a 53 LPC_PINCON->PINSEL1 &= ~( (3 << ((17*2)&30)) | (3 << ((18*2)&30)) );
Michael J. Spencer 2:1df0b61d3b5a 54 LPC_PINCON->PINSEL1 |= ( (2 << ((17*2)&30)) | (2 << ((18*2)&30)) );
Michael J. Spencer 2:1df0b61d3b5a 55
Michael J. Spencer 2:1df0b61d3b5a 56 LPC_SC->PCLKSEL1 &= 0xFFFFF3FF;
Michael J. Spencer 2:1df0b61d3b5a 57 LPC_SC->PCLKSEL1 |= 0x00000400;
Michael J. Spencer 2:1df0b61d3b5a 58
Michael J. Spencer 2:1df0b61d3b5a 59 LPC_SC->PCONP |= CLKPWR_PCONP_PCSSP0;
Michael J. Spencer 2:1df0b61d3b5a 60 }
Michael J. Spencer 2:1df0b61d3b5a 61 else if (mosi == P1_24 && miso == P1_23 && sclk == P1_20)
Michael J. Spencer 2:1df0b61d3b5a 62 {
Michael J. Spencer 2:1df0b61d3b5a 63 // iprintf("SPI: using 1.20,1.23,1.24 with SSP0\n");
Michael J. Spencer 2:1df0b61d3b5a 64 // SSP0 on 1.20,1.23,1.24
Michael J. Spencer 2:1df0b61d3b5a 65 sspr = LPC_SSP0;
Michael J. Spencer 2:1df0b61d3b5a 66 isr_dispatch[0] = this;
Michael J. Spencer 2:1df0b61d3b5a 67
Michael J. Spencer 2:1df0b61d3b5a 68 // // LPC_PINCON->PINSEL3 &= 0xFFFC3CFF;
Michael J. Spencer 2:1df0b61d3b5a 69 // LPC_PINCON->PINSEL3 |= 0x0003C300;
Michael J. Spencer 2:1df0b61d3b5a 70
Michael J. Spencer 2:1df0b61d3b5a 71 // LPC_PINCON->PINSEL3 &= ~( (3 << ((20*2)&30)) | (3 << ((23*2)&30)) | (3 << ((24*2)&30)) );
Michael J. Spencer 2:1df0b61d3b5a 72 LPC_PINCON->PINSEL3 |= ( (3 << ((20*2)&30)) | (3 << ((23*2)&30)) | (3 << ((24*2)&30)) );
Michael J. Spencer 2:1df0b61d3b5a 73
Michael J. Spencer 2:1df0b61d3b5a 74 LPC_SC->PCLKSEL1 &= 0xFFFFF3FF;
Michael J. Spencer 2:1df0b61d3b5a 75 LPC_SC->PCLKSEL1 |= 0x00000400;
Michael J. Spencer 2:1df0b61d3b5a 76
Michael J. Spencer 2:1df0b61d3b5a 77 LPC_SC->PCONP |= CLKPWR_PCONP_PCSSP0;
Michael J. Spencer 2:1df0b61d3b5a 78 }
Michael J. Spencer 2:1df0b61d3b5a 79 else
Michael J. Spencer 2:1df0b61d3b5a 80 {
Michael J. Spencer 2:1df0b61d3b5a 81 // iprintf("SPI: using soft-SPI\n");
Michael J. Spencer 2:1df0b61d3b5a 82 sspr = (LPC_SSP_TypeDef *) 0;
Michael J. Spencer 2:1df0b61d3b5a 83 }
Michael J. Spencer 2:1df0b61d3b5a 84
Michael J. Spencer 2:1df0b61d3b5a 85 if (sspr) {
Michael J. Spencer 2:1df0b61d3b5a 86 sspr->CR0 = SSP_DATABIT_8 |
Michael J. Spencer 2:1df0b61d3b5a 87 SSP_FRAME_SPI;
Michael J. Spencer 2:1df0b61d3b5a 88 sspr->CR1 = SSP_MASTER_MODE;
Michael J. Spencer 2:1df0b61d3b5a 89 frequency(10000);
Michael J. Spencer 2:1df0b61d3b5a 90 sspr->CR1 |= SSP_CR1_SSP_EN;
Michael J. Spencer 2:1df0b61d3b5a 91 }
Michael J. Spencer 2:1df0b61d3b5a 92 }
Michael J. Spencer 2:1df0b61d3b5a 93
Michael J. Spencer 2:1df0b61d3b5a 94 SPI::~SPI()
Michael J. Spencer 2:1df0b61d3b5a 95 {
Michael J. Spencer 2:1df0b61d3b5a 96 if (sspr == LPC_SSP0)
Michael J. Spencer 2:1df0b61d3b5a 97 LPC_SC->PCONP &= CLKPWR_PCONP_PCSSP0;
Michael J. Spencer 2:1df0b61d3b5a 98 else if (sspr == LPC_SSP1)
Michael J. Spencer 2:1df0b61d3b5a 99 LPC_SC->PCONP &= CLKPWR_PCONP_PCSSP1;
Michael J. Spencer 2:1df0b61d3b5a 100 }
Michael J. Spencer 2:1df0b61d3b5a 101
Michael J. Spencer 2:1df0b61d3b5a 102 void SPI::frequency(uint32_t f)
Michael J. Spencer 2:1df0b61d3b5a 103 {
Michael J. Spencer 2:1df0b61d3b5a 104 // CCLK = 25MHz
Michael J. Spencer 2:1df0b61d3b5a 105 // CPSR = 2 to 254, even only
Michael J. Spencer 2:1df0b61d3b5a 106 // CR0[8:15] (SCR, 0..255) is a further prescale
Michael J. Spencer 2:1df0b61d3b5a 107
Michael J. Spencer 2:1df0b61d3b5a 108 // iprintf("SPI: frequency %lu:", f);
Michael J. Spencer 2:1df0b61d3b5a 109 delay = 25000000 / f;
Michael J. Spencer 2:1df0b61d3b5a 110 // f = 25MHz / (CPSR . [SCR + 1])
Michael J. Spencer 2:1df0b61d3b5a 111 // CPSR . (SCR + 1) = 25MHz / f
Michael J. Spencer 2:1df0b61d3b5a 112 // min freq is 25MHz / (254 * 256)
Michael J. Spencer 2:1df0b61d3b5a 113 if (sspr) {
Michael J. Spencer 2:1df0b61d3b5a 114 if (f < 385) {
Michael J. Spencer 2:1df0b61d3b5a 115 sspr->CPSR = 254;
Michael J. Spencer 2:1df0b61d3b5a 116 sspr->CR0 &= 0x00FF;
Michael J. Spencer 2:1df0b61d3b5a 117 sspr->CR0 |= 255 << 8;
Michael J. Spencer 2:1df0b61d3b5a 118 }
Michael J. Spencer 2:1df0b61d3b5a 119 // max freq is 25MHz / (2 * 1)
Michael J. Spencer 2:1df0b61d3b5a 120 else if (f > 12500000) {
Michael J. Spencer 2:1df0b61d3b5a 121 sspr->CPSR = 2;
Michael J. Spencer 2:1df0b61d3b5a 122 sspr->CR0 &= 0x00FF;
Michael J. Spencer 2:1df0b61d3b5a 123 }
Michael J. Spencer 2:1df0b61d3b5a 124 else {
Michael J. Spencer 2:1df0b61d3b5a 125 sspr->CPSR = delay & 0xFE;
Michael J. Spencer 2:1df0b61d3b5a 126 // CPSR . (SCR + 1) = f;
Michael J. Spencer 2:1df0b61d3b5a 127 // (SCR + 1) = f / CPSR;
Michael J. Spencer 2:1df0b61d3b5a 128 // SCR = (f / CPSR) - 1
Michael J. Spencer 2:1df0b61d3b5a 129 sspr->CR0 &= 0x00FF;
Michael J. Spencer 2:1df0b61d3b5a 130 sspr->CR0 |= (((delay / sspr->CPSR) - 1) & 0xFF) << 8;
Michael J. Spencer 2:1df0b61d3b5a 131 }
Michael J. Spencer 2:1df0b61d3b5a 132 // iprintf(" CPSR=%lu, CR0=%lu", sspr->CPSR, sspr->CR0);
Michael J. Spencer 2:1df0b61d3b5a 133 }
Michael J. Spencer 2:1df0b61d3b5a 134 // iprintf("\n");
Michael J. Spencer 2:1df0b61d3b5a 135 }
Michael J. Spencer 2:1df0b61d3b5a 136
Michael J. Spencer 2:1df0b61d3b5a 137 void _delay(uint32_t ticks) {
Michael J. Spencer 2:1df0b61d3b5a 138 for (;ticks;ticks--)
Michael J. Spencer 2:1df0b61d3b5a 139 asm volatile("nop\n\t");
Michael J. Spencer 2:1df0b61d3b5a 140 }
Michael J. Spencer 2:1df0b61d3b5a 141
Michael J. Spencer 2:1df0b61d3b5a 142 uint8_t SPI::write(uint8_t data)
Michael J. Spencer 2:1df0b61d3b5a 143 {
Michael J. Spencer 2:1df0b61d3b5a 144 // _cs = 1;
Michael J. Spencer 2:1df0b61d3b5a 145 uint8_t r = 0;
Michael J. Spencer 2:1df0b61d3b5a 146 // iprintf("SPI: >0x%02X", data);
Michael J. Spencer 2:1df0b61d3b5a 147 if (sspr) {
Michael J. Spencer 2:1df0b61d3b5a 148 while ((sspr->SR & SSP_SR_TNF) == 0);
Michael J. Spencer 2:1df0b61d3b5a 149 sspr->DR = data;
Michael J. Spencer 2:1df0b61d3b5a 150 while ((sspr->SR & SSP_SR_RNE) == 0);
Michael J. Spencer 2:1df0b61d3b5a 151 r = sspr->DR & 255;
Michael J. Spencer 2:1df0b61d3b5a 152 }
Michael J. Spencer 2:1df0b61d3b5a 153 else {
Michael J. Spencer 2:1df0b61d3b5a 154 for (int i = 0; i < 8; i++) {
Michael J. Spencer 2:1df0b61d3b5a 155 FIO_ClearValue(sclk.port, 1UL << sclk.pin); // clock LOW
Michael J. Spencer 2:1df0b61d3b5a 156
Michael J. Spencer 2:1df0b61d3b5a 157 if (data & 0x80) // WRITE
Michael J. Spencer 2:1df0b61d3b5a 158 FIO_SetValue(mosi.port, 1UL << mosi.pin);
Michael J. Spencer 2:1df0b61d3b5a 159 else
Michael J. Spencer 2:1df0b61d3b5a 160 FIO_ClearValue(mosi.port, 1UL << mosi.pin);
Michael J. Spencer 2:1df0b61d3b5a 161 data <<= 1;
Michael J. Spencer 2:1df0b61d3b5a 162
Michael J. Spencer 2:1df0b61d3b5a 163 _delay(delay >> 1); // DELAY
Michael J. Spencer 2:1df0b61d3b5a 164
Michael J. Spencer 2:1df0b61d3b5a 165 FIO_SetValue(sclk.port, 1UL << sclk.pin); // clock HIGH
Michael J. Spencer 2:1df0b61d3b5a 166
Michael J. Spencer 2:1df0b61d3b5a 167 _delay(delay >> 1); // DELAY
Michael J. Spencer 2:1df0b61d3b5a 168
Michael J. Spencer 2:1df0b61d3b5a 169 r <<= 1;
Michael J. Spencer 2:1df0b61d3b5a 170 if (FIO_ReadValue(miso.port) & (1UL << miso.pin)) // READ
Michael J. Spencer 2:1df0b61d3b5a 171 r |= 1;
Michael J. Spencer 2:1df0b61d3b5a 172 }
Michael J. Spencer 2:1df0b61d3b5a 173 FIO_ClearValue(sclk.port, 1UL << sclk.pin);
Michael J. Spencer 2:1df0b61d3b5a 174 }
Michael J. Spencer 2:1df0b61d3b5a 175 // iprintf(" <0x%02X\n", r);
Michael J. Spencer 2:1df0b61d3b5a 176 return r;
Michael J. Spencer 2:1df0b61d3b5a 177 }
Michael J. Spencer 2:1df0b61d3b5a 178
Michael J. Spencer 2:1df0b61d3b5a 179 // TODO: timer feeds DMA feeds 0xFFs to card then we listen for responses using our interrupt
Michael J. Spencer 2:1df0b61d3b5a 180 // allow me to do something like:
Michael J. Spencer 2:1df0b61d3b5a 181 // disk.start_multi_write(int blocks, int blocksize, void *buffer);
Michael J. Spencer 2:1df0b61d3b5a 182 // enable_usb_isr();
Michael J. Spencer 2:1df0b61d3b5a 183 // [...]
Michael J. Spencer 2:1df0b61d3b5a 184 // usb_isr() {
Michael J. Spencer 2:1df0b61d3b5a 185 // if (disk.buffer_in_use(void *buffer))
Michael J. Spencer 2:1df0b61d3b5a 186 // return;
Michael J. Spencer 2:1df0b61d3b5a 187 // usb_ep_read(buffer);
Michael J. Spencer 2:1df0b61d3b5a 188 // if (buffer_full)
Michael J. Spencer 2:1df0b61d3b5a 189 // disk.validate_buffer(buffer);
Michael J. Spencer 2:1df0b61d3b5a 190 // if (disk.finished_transfer())
Michael J. Spencer 2:1df0b61d3b5a 191 // disk.end_multi_write();
Michael J. Spencer 2:1df0b61d3b5a 192 // };
Michael J. Spencer 2:1df0b61d3b5a 193
Michael J. Spencer 2:1df0b61d3b5a 194 bool SPI::can_DMA()
Michael J. Spencer 2:1df0b61d3b5a 195 {
Michael J. Spencer 2:1df0b61d3b5a 196 return (sspr != NULL);
Michael J. Spencer 2:1df0b61d3b5a 197 }
Michael J. Spencer 2:1df0b61d3b5a 198
Michael J. Spencer 2:1df0b61d3b5a 199 // int SPI::setup_DMA_rx(DMA_REG *dma)
Michael J. Spencer 2:1df0b61d3b5a 200 // {
Michael J. Spencer 2:1df0b61d3b5a 201 // if (!sspr)
Michael J. Spencer 2:1df0b61d3b5a 202 // return -1;
Michael J. Spencer 2:1df0b61d3b5a 203 //
Michael J. Spencer 2:1df0b61d3b5a 204 // dma->DMACCControl = 0;
Michael J. Spencer 2:1df0b61d3b5a 205 // dma->DMACCConfiguration = 0;
Michael J. Spencer 2:1df0b61d3b5a 206 // if (sspr == LPC_SSP0)
Michael J. Spencer 2:1df0b61d3b5a 207 // dma->DMACCConfiguration |= (GPDMA_CONN_SSP0_Rx << 6);
Michael J. Spencer 2:1df0b61d3b5a 208 // if (sspr == LPC_SSP1)
Michael J. Spencer 2:1df0b61d3b5a 209 // dma->DMACCConfiguration |= (GPDMA_CONN_SSP1_Rx << 6);
Michael J. Spencer 2:1df0b61d3b5a 210 //
Michael J. Spencer 2:1df0b61d3b5a 211 // dma->DMACCConfiguration |= GPDMA_TRANSFERTYPE_M2P << 11;
Michael J. Spencer 2:1df0b61d3b5a 212 // return 0;
Michael J. Spencer 2:1df0b61d3b5a 213 // }
Michael J. Spencer 2:1df0b61d3b5a 214 //
Michael J. Spencer 2:1df0b61d3b5a 215 // int SPI::start_DMA_rx(DMA_REG *dma)
Michael J. Spencer 2:1df0b61d3b5a 216 // {
Michael J. Spencer 2:1df0b61d3b5a 217 // dma->DMACCConfiguration |=
Michael J. Spencer 2:1df0b61d3b5a 218 // }
Michael J. Spencer 2:1df0b61d3b5a 219
Michael J. Spencer 2:1df0b61d3b5a 220 // int SPI::writeblock(uint8_t *block, int blocklen)
Michael J. Spencer 2:1df0b61d3b5a 221 // {
Michael J. Spencer 2:1df0b61d3b5a 222 // static DMA *d = new DMA();
Michael J. Spencer 2:1df0b61d3b5a 223 // d.sourceaddr(block);
Michael J. Spencer 2:1df0b61d3b5a 224 // d.transferlength(blocklen);
Michael J. Spencer 2:1df0b61d3b5a 225 // d.destinationperipheral(sspr);
Michael J. Spencer 2:1df0b61d3b5a 226 // d.start();
Michael J. Spencer 2:1df0b61d3b5a 227 // while (d.active());
Michael J. Spencer 2:1df0b61d3b5a 228 // return blocklen;
Michael J. Spencer 2:1df0b61d3b5a 229 // return 0;
Michael J. Spencer 2:1df0b61d3b5a 230 // }
Michael J. Spencer 2:1df0b61d3b5a 231
Michael J. Spencer 2:1df0b61d3b5a 232 void SPI::irq()
Michael J. Spencer 2:1df0b61d3b5a 233 {
Michael J. Spencer 2:1df0b61d3b5a 234 }
Michael J. Spencer 2:1df0b61d3b5a 235
Michael J. Spencer 2:1df0b61d3b5a 236 void SSP0_IRQHandler(void) {
Michael J. Spencer 2:1df0b61d3b5a 237 if (SPI::isr_dispatch[0])
Michael J. Spencer 2:1df0b61d3b5a 238 SPI::isr_dispatch[0]->irq();
Michael J. Spencer 2:1df0b61d3b5a 239 }
Michael J. Spencer 2:1df0b61d3b5a 240
Michael J. Spencer 2:1df0b61d3b5a 241 void SSP1_IRQHandler(void) {
Michael J. Spencer 2:1df0b61d3b5a 242 if (SPI::isr_dispatch[1])
Michael J. Spencer 2:1df0b61d3b5a 243 (SPI::isr_dispatch[1])->irq();
Michael J. Spencer 2:1df0b61d3b5a 244 }