mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Committer:
AnnaBridge
Date:
Wed Feb 20 22:31:08 2019 +0000
Revision:
189:f392fc9709a3
Parent:
186:707f6e361f3e
mbed library release version 165

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Anna Bridge 186:707f6e361f3e 1 /* mbed Microcontroller Library
Anna Bridge 186:707f6e361f3e 2 * Copyright (c) 2006-2018 ARM Limited
Anna Bridge 186:707f6e361f3e 3 *
Anna Bridge 186:707f6e361f3e 4 * Licensed under the Apache License, Version 2.0 (the "License");
Anna Bridge 186:707f6e361f3e 5 * you may not use this file except in compliance with the License.
Anna Bridge 186:707f6e361f3e 6 * You may obtain a copy of the License at
Anna Bridge 186:707f6e361f3e 7 *
Anna Bridge 186:707f6e361f3e 8 * http://www.apache.org/licenses/LICENSE-2.0
Anna Bridge 186:707f6e361f3e 9 *
Anna Bridge 186:707f6e361f3e 10 * Unless required by applicable law or agreed to in writing, software
Anna Bridge 186:707f6e361f3e 11 * distributed under the License is distributed on an "AS IS" BASIS,
Anna Bridge 186:707f6e361f3e 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Anna Bridge 186:707f6e361f3e 13 * See the License for the specific language governing permissions and
Anna Bridge 186:707f6e361f3e 14 * limitations under the License.
Anna Bridge 186:707f6e361f3e 15 */
Anna Bridge 186:707f6e361f3e 16 #include <math.h>
Anna Bridge 186:707f6e361f3e 17
Anna Bridge 186:707f6e361f3e 18 #include "spi_api.h"
Anna Bridge 186:707f6e361f3e 19 #include "spi_def.h"
Anna Bridge 186:707f6e361f3e 20 #include "cmsis.h"
Anna Bridge 186:707f6e361f3e 21 #include "pinmap.h"
Anna Bridge 186:707f6e361f3e 22 #include "mbed_error.h"
Anna Bridge 186:707f6e361f3e 23 #include "mbed_wait_api.h"
Anna Bridge 186:707f6e361f3e 24
Anna Bridge 186:707f6e361f3e 25 static const PinMap PinMap_SPI_SCLK[] = {
Anna Bridge 186:707f6e361f3e 26 {SCLK_SPI, SPI_0, 0},
Anna Bridge 186:707f6e361f3e 27 {CLCD_SCLK, SPI_1, 0},
Anna Bridge 186:707f6e361f3e 28 {ADC_SCLK, SPI_2, 0},
Anna Bridge 186:707f6e361f3e 29 {SHIELD_0_SPI_SCK, SPI_3, 0},
Anna Bridge 186:707f6e361f3e 30 {SHIELD_1_SPI_SCK, SPI_4, 0},
Anna Bridge 186:707f6e361f3e 31 {NC, NC, 0}
Anna Bridge 186:707f6e361f3e 32 };
Anna Bridge 186:707f6e361f3e 33
Anna Bridge 186:707f6e361f3e 34 static const PinMap PinMap_SPI_MOSI[] = {
Anna Bridge 186:707f6e361f3e 35 {MOSI_SPI, SPI_0, 0},
Anna Bridge 186:707f6e361f3e 36 {CLCD_MOSI, SPI_1, 0},
Anna Bridge 186:707f6e361f3e 37 {ADC_MOSI, SPI_2, 0},
Anna Bridge 186:707f6e361f3e 38 {SHIELD_0_SPI_MOSI, SPI_3, 0},
Anna Bridge 186:707f6e361f3e 39 {SHIELD_1_SPI_MOSI, SPI_4, 0},
Anna Bridge 186:707f6e361f3e 40 {NC, NC, 0}
Anna Bridge 186:707f6e361f3e 41 };
Anna Bridge 186:707f6e361f3e 42
Anna Bridge 186:707f6e361f3e 43 static const PinMap PinMap_SPI_MISO[] = {
Anna Bridge 186:707f6e361f3e 44 {MISO_SPI, SPI_0, 0},
Anna Bridge 186:707f6e361f3e 45 {CLCD_MISO, SPI_1, 0},
Anna Bridge 186:707f6e361f3e 46 {ADC_MISO, SPI_2, 0},
Anna Bridge 186:707f6e361f3e 47 {SHIELD_0_SPI_MISO, SPI_3, 0},
Anna Bridge 186:707f6e361f3e 48 {SHIELD_1_SPI_MISO, SPI_4, 0},
Anna Bridge 186:707f6e361f3e 49 {NC, NC, 0}
Anna Bridge 186:707f6e361f3e 50 };
Anna Bridge 186:707f6e361f3e 51
Anna Bridge 186:707f6e361f3e 52 static const PinMap PinMap_SPI_SSEL[] = {
Anna Bridge 186:707f6e361f3e 53 {SSEL_SPI, SPI_0, 0},
Anna Bridge 186:707f6e361f3e 54 {CLCD_SSEL, SPI_1, 0},
Anna Bridge 186:707f6e361f3e 55 {ADC_SSEL, SPI_2, 0},
Anna Bridge 186:707f6e361f3e 56 {SHIELD_0_SPI_nCS, SPI_3, 0},
Anna Bridge 186:707f6e361f3e 57 {SHIELD_1_SPI_nCS, SPI_4, 0},
Anna Bridge 186:707f6e361f3e 58 {NC, NC, 0}
Anna Bridge 186:707f6e361f3e 59 };
Anna Bridge 186:707f6e361f3e 60
Anna Bridge 186:707f6e361f3e 61 static inline int ssp_disable(spi_t *obj);
Anna Bridge 186:707f6e361f3e 62 static inline int ssp_enable(spi_t *obj);
Anna Bridge 186:707f6e361f3e 63
Anna Bridge 186:707f6e361f3e 64 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel)
Anna Bridge 186:707f6e361f3e 65 {
Anna Bridge 186:707f6e361f3e 66
Anna Bridge 186:707f6e361f3e 67 int altfunction[4];
Anna Bridge 186:707f6e361f3e 68 // determine the SPI to use
Anna Bridge 186:707f6e361f3e 69 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
Anna Bridge 186:707f6e361f3e 70 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
Anna Bridge 186:707f6e361f3e 71 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
Anna Bridge 186:707f6e361f3e 72 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
Anna Bridge 186:707f6e361f3e 73 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
Anna Bridge 186:707f6e361f3e 74 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
Anna Bridge 186:707f6e361f3e 75 obj->spi = (MPS2_SSP_TypeDef *)pinmap_merge(spi_data, spi_cntl);
Anna Bridge 186:707f6e361f3e 76 if ((int)obj->spi == NC) {
Anna Bridge 186:707f6e361f3e 77 error("SPI pinout mapping failed");
Anna Bridge 186:707f6e361f3e 78 }
Anna Bridge 186:707f6e361f3e 79
Anna Bridge 186:707f6e361f3e 80 // enable power and clocking
Anna Bridge 186:707f6e361f3e 81 switch ((int)obj->spi) {
Anna Bridge 186:707f6e361f3e 82 case (int)SPI_0:
Anna Bridge 186:707f6e361f3e 83 obj->spi->CR1 = 0;
Anna Bridge 186:707f6e361f3e 84 obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
Anna Bridge 186:707f6e361f3e 85 obj->spi->CPSR = SSP_CPSR_DFLT;
Anna Bridge 186:707f6e361f3e 86 obj->spi->IMSC = 0x8;
Anna Bridge 186:707f6e361f3e 87 obj->spi->DMACR = 0;
Anna Bridge 186:707f6e361f3e 88 obj->spi->CR1 = SSP_CR1_SSE_Msk;
Anna Bridge 186:707f6e361f3e 89 obj->spi->ICR = 0x3;
Anna Bridge 186:707f6e361f3e 90 break;
Anna Bridge 186:707f6e361f3e 91 case (int)SPI_1:
Anna Bridge 186:707f6e361f3e 92 /* Configure SSP used for LCD */
Anna Bridge 186:707f6e361f3e 93 obj->spi->CR1 = 0; /* Synchronous serial port disable */
Anna Bridge 186:707f6e361f3e 94 obj->spi->DMACR = 0; /* Disable FIFO DMA */
Anna Bridge 186:707f6e361f3e 95 obj->spi->IMSC = 0; /* Mask all FIFO/IRQ interrupts */
Anna Bridge 186:707f6e361f3e 96 obj->spi->ICR = ((1ul << 0) | /* Clear SSPRORINTR interrupt */
Anna Bridge 186:707f6e361f3e 97 (1ul << 1)); /* Clear SSPRTINTR interrupt */
Anna Bridge 186:707f6e361f3e 98 obj->spi->CR0 = ((7ul << 0) | /* 8 bit data size */
Anna Bridge 186:707f6e361f3e 99 (0ul << 4) | /* Motorola frame format */
Anna Bridge 186:707f6e361f3e 100 (0ul << 6) | /* CPOL = 0 */
Anna Bridge 186:707f6e361f3e 101 (0ul << 7) | /* CPHA = 0 */
Anna Bridge 186:707f6e361f3e 102 (1ul << 8)); /* Set serial clock rate */
Anna Bridge 186:707f6e361f3e 103 obj->spi->CPSR = (2ul << 0); /* set SSP clk to 6MHz (6.6MHz max) */
Anna Bridge 186:707f6e361f3e 104 obj->spi->CR1 = ((1ul << 1) | /* Synchronous serial port enable */
Anna Bridge 186:707f6e361f3e 105 (0ul << 2)); /* Device configured as master */
Anna Bridge 186:707f6e361f3e 106 break;
Anna Bridge 186:707f6e361f3e 107 case (int)SPI_2:
Anna Bridge 186:707f6e361f3e 108 obj->spi->CR1 = 0;
Anna Bridge 186:707f6e361f3e 109 obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
Anna Bridge 186:707f6e361f3e 110 obj->spi->CPSR = SSP_CPSR_DFLT;
Anna Bridge 186:707f6e361f3e 111 obj->spi->IMSC = 0x8;
Anna Bridge 186:707f6e361f3e 112 obj->spi->DMACR = 0;
Anna Bridge 186:707f6e361f3e 113 obj->spi->CR1 = SSP_CR1_SSE_Msk;
Anna Bridge 186:707f6e361f3e 114 obj->spi->ICR = 0x3;
Anna Bridge 186:707f6e361f3e 115 break;
Anna Bridge 186:707f6e361f3e 116 case (int)SPI_3:
Anna Bridge 186:707f6e361f3e 117 obj->spi->CR1 = 0;
Anna Bridge 186:707f6e361f3e 118 obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
Anna Bridge 186:707f6e361f3e 119 obj->spi->CPSR = SSP_CPSR_DFLT;
Anna Bridge 186:707f6e361f3e 120 obj->spi->IMSC = 0x8;
Anna Bridge 186:707f6e361f3e 121 obj->spi->DMACR = 0;
Anna Bridge 186:707f6e361f3e 122 obj->spi->CR1 = SSP_CR1_SSE_Msk;
Anna Bridge 186:707f6e361f3e 123 obj->spi->ICR = 0x3;
Anna Bridge 186:707f6e361f3e 124 break;
Anna Bridge 186:707f6e361f3e 125 case (int)SPI_4:
Anna Bridge 186:707f6e361f3e 126 obj->spi->CR1 = 0;
Anna Bridge 186:707f6e361f3e 127 obj->spi->CR0 = SSP_CR0_SCR_DFLT | SSP_CR0_FRF_MOT | SSP_CR0_DSS_8;
Anna Bridge 186:707f6e361f3e 128 obj->spi->CPSR = SSP_CPSR_DFLT;
Anna Bridge 186:707f6e361f3e 129 obj->spi->IMSC = 0x8;
Anna Bridge 186:707f6e361f3e 130 obj->spi->DMACR = 0;
Anna Bridge 186:707f6e361f3e 131 obj->spi->CR1 = SSP_CR1_SSE_Msk;
Anna Bridge 186:707f6e361f3e 132 obj->spi->ICR = 0x3;
Anna Bridge 186:707f6e361f3e 133 break;
Anna Bridge 186:707f6e361f3e 134 }
Anna Bridge 186:707f6e361f3e 135
Anna Bridge 186:707f6e361f3e 136 if (mosi != NC) {
Anna Bridge 186:707f6e361f3e 137 altfunction[0] = 1;
Anna Bridge 186:707f6e361f3e 138 } else {
Anna Bridge 186:707f6e361f3e 139 altfunction[0] = 0;
Anna Bridge 186:707f6e361f3e 140 }
Anna Bridge 186:707f6e361f3e 141 if (miso != NC) {
Anna Bridge 186:707f6e361f3e 142 altfunction[1] = 1;
Anna Bridge 186:707f6e361f3e 143 } else {
Anna Bridge 186:707f6e361f3e 144 altfunction[1] = 0;
Anna Bridge 186:707f6e361f3e 145 }
Anna Bridge 186:707f6e361f3e 146 if (sclk != NC) {
Anna Bridge 186:707f6e361f3e 147 altfunction[2] = 1;
Anna Bridge 186:707f6e361f3e 148 } else {
Anna Bridge 186:707f6e361f3e 149 altfunction[2] = 0;
Anna Bridge 186:707f6e361f3e 150 }
Anna Bridge 186:707f6e361f3e 151 if (ssel != NC) {
Anna Bridge 186:707f6e361f3e 152 altfunction[3] = 1;
Anna Bridge 186:707f6e361f3e 153 } else {
Anna Bridge 186:707f6e361f3e 154 altfunction[3] = 0;
Anna Bridge 186:707f6e361f3e 155 }
Anna Bridge 186:707f6e361f3e 156
Anna Bridge 186:707f6e361f3e 157 // enable alt function
Anna Bridge 186:707f6e361f3e 158 switch ((int)obj->spi) {
Anna Bridge 186:707f6e361f3e 159 case (int)SPI_2:
Anna Bridge 186:707f6e361f3e 160 CMSDK_GPIO1->ALTFUNCSET |= (altfunction[2] << 3 | altfunction[0] << 2 | altfunction[1] << 1 | altfunction[3]);
Anna Bridge 186:707f6e361f3e 161 break;
Anna Bridge 186:707f6e361f3e 162 case (int)SPI_3:
Anna Bridge 186:707f6e361f3e 163 CMSDK_GPIO0->ALTFUNCSET |= (altfunction[1] << 14 | altfunction[0] << 13 | altfunction[3] << 12 | altfunction[2] << 11);
Anna Bridge 186:707f6e361f3e 164 break;
Anna Bridge 186:707f6e361f3e 165 case (int)SPI_4:
Anna Bridge 186:707f6e361f3e 166 CMSDK_GPIO2->ALTFUNCSET |= (altfunction[2] << 12 | altfunction[1] << 8 | altfunction[0] << 7 | altfunction[3] << 6);
Anna Bridge 186:707f6e361f3e 167 break;
Anna Bridge 186:707f6e361f3e 168 }
Anna Bridge 186:707f6e361f3e 169
Anna Bridge 186:707f6e361f3e 170 // set default format and frequency
Anna Bridge 186:707f6e361f3e 171 if (ssel == NC) {
Anna Bridge 186:707f6e361f3e 172 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
Anna Bridge 186:707f6e361f3e 173 } else {
Anna Bridge 186:707f6e361f3e 174 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
Anna Bridge 186:707f6e361f3e 175 }
Anna Bridge 186:707f6e361f3e 176 spi_frequency(obj, 1000000);
Anna Bridge 186:707f6e361f3e 177
Anna Bridge 186:707f6e361f3e 178 // enable the ssp channel
Anna Bridge 186:707f6e361f3e 179 ssp_enable(obj);
Anna Bridge 186:707f6e361f3e 180
Anna Bridge 186:707f6e361f3e 181 // pin out the spi pins
Anna Bridge 186:707f6e361f3e 182 pinmap_pinout(mosi, PinMap_SPI_MOSI);
Anna Bridge 186:707f6e361f3e 183 pinmap_pinout(miso, PinMap_SPI_MISO);
Anna Bridge 186:707f6e361f3e 184 pinmap_pinout(sclk, PinMap_SPI_SCLK);
Anna Bridge 186:707f6e361f3e 185 if (ssel != NC) {
Anna Bridge 186:707f6e361f3e 186 pinmap_pinout(ssel, PinMap_SPI_SSEL);
Anna Bridge 186:707f6e361f3e 187 }
Anna Bridge 186:707f6e361f3e 188 }
Anna Bridge 186:707f6e361f3e 189
Anna Bridge 186:707f6e361f3e 190 void spi_free(spi_t *obj) {}
Anna Bridge 186:707f6e361f3e 191
Anna Bridge 186:707f6e361f3e 192 void spi_format(spi_t *obj, int bits, int mode, int slave)
Anna Bridge 186:707f6e361f3e 193 {
Anna Bridge 186:707f6e361f3e 194 ssp_disable(obj);
Anna Bridge 186:707f6e361f3e 195 if (!(bits >= 4 && bits <= 16) || !(mode >= 0 && mode <= 3)) {
Anna Bridge 186:707f6e361f3e 196 error("SPI format error");
Anna Bridge 186:707f6e361f3e 197 }
Anna Bridge 186:707f6e361f3e 198
Anna Bridge 186:707f6e361f3e 199 int polarity = (mode & 0x2) ? 1 : 0;
Anna Bridge 186:707f6e361f3e 200 int phase = (mode & 0x1) ? 1 : 0;
Anna Bridge 186:707f6e361f3e 201
Anna Bridge 186:707f6e361f3e 202 // set it up
Anna Bridge 186:707f6e361f3e 203 int DSS = bits - 1; // DSS (data select size)
Anna Bridge 186:707f6e361f3e 204 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
Anna Bridge 186:707f6e361f3e 205 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
Anna Bridge 186:707f6e361f3e 206
Anna Bridge 186:707f6e361f3e 207 int FRF = 0; // FRF (frame format) = SPI
Anna Bridge 186:707f6e361f3e 208 uint32_t tmp = obj->spi->CR0;
Anna Bridge 186:707f6e361f3e 209 tmp &= ~(0xFFFF);
Anna Bridge 186:707f6e361f3e 210 tmp |= DSS << 0
Anna Bridge 186:707f6e361f3e 211 | FRF << 4
Anna Bridge 186:707f6e361f3e 212 | SPO << 6
Anna Bridge 186:707f6e361f3e 213 | SPH << 7;
Anna Bridge 186:707f6e361f3e 214 obj->spi->CR0 = tmp;
Anna Bridge 186:707f6e361f3e 215
Anna Bridge 186:707f6e361f3e 216 tmp = obj->spi->CR1;
Anna Bridge 186:707f6e361f3e 217 tmp &= ~(0xD);
Anna Bridge 186:707f6e361f3e 218 tmp |= 0 << 0 // LBM - loop back mode - off
Anna Bridge 186:707f6e361f3e 219 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
Anna Bridge 186:707f6e361f3e 220 | 0 << 3; // SOD - slave output disable - na
Anna Bridge 186:707f6e361f3e 221 obj->spi->CR1 = tmp;
Anna Bridge 186:707f6e361f3e 222
Anna Bridge 186:707f6e361f3e 223 ssp_enable(obj);
Anna Bridge 186:707f6e361f3e 224 }
Anna Bridge 186:707f6e361f3e 225
Anna Bridge 186:707f6e361f3e 226 void spi_frequency(spi_t *obj, int hz)
Anna Bridge 186:707f6e361f3e 227 {
Anna Bridge 186:707f6e361f3e 228 ssp_disable(obj);
Anna Bridge 186:707f6e361f3e 229
Anna Bridge 186:707f6e361f3e 230 uint32_t PCLK = SystemCoreClock;
Anna Bridge 186:707f6e361f3e 231
Anna Bridge 186:707f6e361f3e 232 int prescaler;
Anna Bridge 186:707f6e361f3e 233
Anna Bridge 186:707f6e361f3e 234 for (prescaler = 2; prescaler <= 254; prescaler += 2) {
Anna Bridge 186:707f6e361f3e 235 int prescale_hz = PCLK / prescaler;
Anna Bridge 186:707f6e361f3e 236
Anna Bridge 186:707f6e361f3e 237 // calculate the divider
Anna Bridge 186:707f6e361f3e 238 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
Anna Bridge 186:707f6e361f3e 239
Anna Bridge 186:707f6e361f3e 240 // check we can support the divider
Anna Bridge 186:707f6e361f3e 241 if (divider < 256) {
Anna Bridge 186:707f6e361f3e 242 // prescaler
Anna Bridge 186:707f6e361f3e 243 obj->spi->CPSR = prescaler;
Anna Bridge 186:707f6e361f3e 244
Anna Bridge 186:707f6e361f3e 245 // divider
Anna Bridge 186:707f6e361f3e 246 obj->spi->CR0 &= ~(0xFFFF << 8);
Anna Bridge 186:707f6e361f3e 247 obj->spi->CR0 |= (divider - 1) << 8;
Anna Bridge 186:707f6e361f3e 248 ssp_enable(obj);
Anna Bridge 186:707f6e361f3e 249 return;
Anna Bridge 186:707f6e361f3e 250 }
Anna Bridge 186:707f6e361f3e 251 }
Anna Bridge 186:707f6e361f3e 252 error("Couldn't setup requested SPI frequency");
Anna Bridge 186:707f6e361f3e 253 }
Anna Bridge 186:707f6e361f3e 254
Anna Bridge 186:707f6e361f3e 255 static inline int ssp_disable(spi_t *obj)
Anna Bridge 186:707f6e361f3e 256 {
Anna Bridge 186:707f6e361f3e 257 return obj->spi->CR1 &= ~(1 << 1);
Anna Bridge 186:707f6e361f3e 258 }
Anna Bridge 186:707f6e361f3e 259
Anna Bridge 186:707f6e361f3e 260 static inline int ssp_enable(spi_t *obj)
Anna Bridge 186:707f6e361f3e 261 {
Anna Bridge 186:707f6e361f3e 262 return obj->spi->CR1 |= SSP_CR1_SSE_Msk;
Anna Bridge 186:707f6e361f3e 263 }
Anna Bridge 186:707f6e361f3e 264
Anna Bridge 186:707f6e361f3e 265 static inline int ssp_readable(spi_t *obj)
Anna Bridge 186:707f6e361f3e 266 {
Anna Bridge 186:707f6e361f3e 267 return obj->spi->SR & (1 << 2);
Anna Bridge 186:707f6e361f3e 268 }
Anna Bridge 186:707f6e361f3e 269
Anna Bridge 186:707f6e361f3e 270 static inline int ssp_writeable(spi_t *obj)
Anna Bridge 186:707f6e361f3e 271 {
Anna Bridge 186:707f6e361f3e 272 return obj->spi->SR & SSP_SR_BSY_Msk;
Anna Bridge 186:707f6e361f3e 273 }
Anna Bridge 186:707f6e361f3e 274
Anna Bridge 186:707f6e361f3e 275 static inline void ssp_write(spi_t *obj, int value)
Anna Bridge 186:707f6e361f3e 276 {
Anna Bridge 186:707f6e361f3e 277 obj->spi->DR = value;
Anna Bridge 186:707f6e361f3e 278 while (ssp_writeable(obj));
Anna Bridge 186:707f6e361f3e 279 }
Anna Bridge 186:707f6e361f3e 280 static inline int ssp_read(spi_t *obj)
Anna Bridge 186:707f6e361f3e 281 {
Anna Bridge 186:707f6e361f3e 282 int read_DR = obj->spi->DR;
Anna Bridge 186:707f6e361f3e 283 return read_DR;
Anna Bridge 186:707f6e361f3e 284 }
Anna Bridge 186:707f6e361f3e 285
Anna Bridge 186:707f6e361f3e 286 static inline int ssp_busy(spi_t *obj)
Anna Bridge 186:707f6e361f3e 287 {
Anna Bridge 186:707f6e361f3e 288 return (obj->spi->SR & (1 << 4)) ? (1) : (0);
Anna Bridge 186:707f6e361f3e 289 }
Anna Bridge 186:707f6e361f3e 290
Anna Bridge 186:707f6e361f3e 291 int spi_master_write(spi_t *obj, int value)
Anna Bridge 186:707f6e361f3e 292 {
Anna Bridge 186:707f6e361f3e 293 ssp_write(obj, value);
Anna Bridge 186:707f6e361f3e 294 while (obj->spi->SR & SSP_SR_BSY_Msk); /* Wait for send to finish */
Anna Bridge 186:707f6e361f3e 295 return (ssp_read(obj));
Anna Bridge 186:707f6e361f3e 296 }
Anna Bridge 186:707f6e361f3e 297
Anna Bridge 186:707f6e361f3e 298 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
Anna Bridge 186:707f6e361f3e 299 char *rx_buffer, int rx_length, char write_fill)
Anna Bridge 186:707f6e361f3e 300 {
Anna Bridge 186:707f6e361f3e 301 int total = (tx_length > rx_length) ? tx_length : rx_length;
Anna Bridge 186:707f6e361f3e 302
Anna Bridge 186:707f6e361f3e 303 for (int i = 0; i < total; i++) {
Anna Bridge 186:707f6e361f3e 304 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
Anna Bridge 186:707f6e361f3e 305 char in = spi_master_write(obj, out);
Anna Bridge 186:707f6e361f3e 306 if (i < rx_length) {
Anna Bridge 186:707f6e361f3e 307 rx_buffer[i] = in;
Anna Bridge 186:707f6e361f3e 308 }
Anna Bridge 186:707f6e361f3e 309 }
Anna Bridge 186:707f6e361f3e 310
Anna Bridge 186:707f6e361f3e 311 return total;
Anna Bridge 186:707f6e361f3e 312 }
Anna Bridge 186:707f6e361f3e 313
Anna Bridge 186:707f6e361f3e 314 int spi_slave_receive(spi_t *obj)
Anna Bridge 186:707f6e361f3e 315 {
Anna Bridge 186:707f6e361f3e 316 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
Anna Bridge 186:707f6e361f3e 317 }
Anna Bridge 186:707f6e361f3e 318
Anna Bridge 186:707f6e361f3e 319 int spi_slave_read(spi_t *obj)
Anna Bridge 186:707f6e361f3e 320 {
Anna Bridge 186:707f6e361f3e 321 return obj->spi->DR;
Anna Bridge 186:707f6e361f3e 322 }
Anna Bridge 186:707f6e361f3e 323
Anna Bridge 186:707f6e361f3e 324 void spi_slave_write(spi_t *obj, int value)
Anna Bridge 186:707f6e361f3e 325 {
Anna Bridge 186:707f6e361f3e 326 while (ssp_writeable(obj) == 0) ;
Anna Bridge 186:707f6e361f3e 327 obj->spi->DR = value;
Anna Bridge 186:707f6e361f3e 328 }
Anna Bridge 186:707f6e361f3e 329
Anna Bridge 186:707f6e361f3e 330 int spi_busy(spi_t *obj)
Anna Bridge 186:707f6e361f3e 331 {
Anna Bridge 186:707f6e361f3e 332 return ssp_busy(obj);
Anna Bridge 186:707f6e361f3e 333 }