BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:47:08 2018 +0000
Revision:
1:9c5af431a1f1
sdf

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gustavatmel 1:9c5af431a1f1 1 /* mbed Microcontroller Library
gustavatmel 1:9c5af431a1f1 2 * Copyright (c) 2006-2013 ARM Limited
gustavatmel 1:9c5af431a1f1 3 *
gustavatmel 1:9c5af431a1f1 4 * Licensed under the Apache License, Version 2.0 (the "License");
gustavatmel 1:9c5af431a1f1 5 * you may not use this file except in compliance with the License.
gustavatmel 1:9c5af431a1f1 6 * You may obtain a copy of the License at
gustavatmel 1:9c5af431a1f1 7 *
gustavatmel 1:9c5af431a1f1 8 * http://www.apache.org/licenses/LICENSE-2.0
gustavatmel 1:9c5af431a1f1 9 *
gustavatmel 1:9c5af431a1f1 10 * Unless required by applicable law or agreed to in writing, software
gustavatmel 1:9c5af431a1f1 11 * distributed under the License is distributed on an "AS IS" BASIS,
gustavatmel 1:9c5af431a1f1 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
gustavatmel 1:9c5af431a1f1 13 * See the License for the specific language governing permissions and
gustavatmel 1:9c5af431a1f1 14 * limitations under the License.
gustavatmel 1:9c5af431a1f1 15 *
gustavatmel 1:9c5af431a1f1 16 * Ported to NXP LPC43XX by Micromint USA <support@micromint.com>
gustavatmel 1:9c5af431a1f1 17 */
gustavatmel 1:9c5af431a1f1 18 #include "mbed_assert.h"
gustavatmel 1:9c5af431a1f1 19 #include <math.h>
gustavatmel 1:9c5af431a1f1 20
gustavatmel 1:9c5af431a1f1 21 #include "spi_api.h"
gustavatmel 1:9c5af431a1f1 22 #include "cmsis.h"
gustavatmel 1:9c5af431a1f1 23 #include "pinmap.h"
gustavatmel 1:9c5af431a1f1 24 #include "mbed_error.h"
gustavatmel 1:9c5af431a1f1 25
gustavatmel 1:9c5af431a1f1 26 // SCU mode for SPI pins
gustavatmel 1:9c5af431a1f1 27 #define SCU_PINIO_SPI SCU_PINIO_FAST
gustavatmel 1:9c5af431a1f1 28
gustavatmel 1:9c5af431a1f1 29 static const PinMap PinMap_SPI_SCLK[] = {
gustavatmel 1:9c5af431a1f1 30 {P1_19, SPI_1, (SCU_PINIO_SPI | 1)},
gustavatmel 1:9c5af431a1f1 31 {P3_0, SPI_0, (SCU_PINIO_SPI | 4)},
gustavatmel 1:9c5af431a1f1 32 {P3_3, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 33 {PF_0, SPI_0, (SCU_PINIO_SPI | 0)},
gustavatmel 1:9c5af431a1f1 34 {PF_4, SPI_1, (SCU_PINIO_SPI | 0)},
gustavatmel 1:9c5af431a1f1 35 {NC, NC, 0}
gustavatmel 1:9c5af431a1f1 36 };
gustavatmel 1:9c5af431a1f1 37
gustavatmel 1:9c5af431a1f1 38 static const PinMap PinMap_SPI_MOSI[] = {
gustavatmel 1:9c5af431a1f1 39 {P0_1, SPI_1, (SCU_PINIO_SPI | 1)},
gustavatmel 1:9c5af431a1f1 40 {P1_2, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 41 {P1_4, SPI_1, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 42 {P3_7, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 43 {P3_8, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 44 {P9_2, SPI_0, (SCU_PINIO_SPI | 7)},
gustavatmel 1:9c5af431a1f1 45 {PF_3, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 46 {PF_7, SPI_1, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 47 {NC, NC, 0}
gustavatmel 1:9c5af431a1f1 48 };
gustavatmel 1:9c5af431a1f1 49
gustavatmel 1:9c5af431a1f1 50 static const PinMap PinMap_SPI_MISO[] = {
gustavatmel 1:9c5af431a1f1 51 {P0_0, SPI_1, (SCU_PINIO_SPI | 1)},
gustavatmel 1:9c5af431a1f1 52 {P1_1, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 53 {P1_3, SPI_1, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 54 {P3_6, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 55 {P3_7, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 56 {P9_1, SPI_0, (SCU_PINIO_SPI | 7)},
gustavatmel 1:9c5af431a1f1 57 {PF_2, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 58 {PF_6, SPI_1, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 59 {NC, NC, 0}
gustavatmel 1:9c5af431a1f1 60 };
gustavatmel 1:9c5af431a1f1 61
gustavatmel 1:9c5af431a1f1 62 static const PinMap PinMap_SPI_SSEL[] = {
gustavatmel 1:9c5af431a1f1 63 {P1_0, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 64 {P1_5, SPI_1, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 65 {P1_20, SPI_1, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 66 {P3_6, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 67 {P3_8, SPI_0, (SCU_PINIO_SPI | 5)},
gustavatmel 1:9c5af431a1f1 68 {P9_0, SPI_0, (SCU_PINIO_SPI | 7)},
gustavatmel 1:9c5af431a1f1 69 {PF_1, SPI_0, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 70 {PF_5, SPI_1, (SCU_PINIO_SPI | 2)},
gustavatmel 1:9c5af431a1f1 71 {NC, NC, 0}
gustavatmel 1:9c5af431a1f1 72 };
gustavatmel 1:9c5af431a1f1 73
gustavatmel 1:9c5af431a1f1 74 static inline int ssp_disable(spi_t *obj);
gustavatmel 1:9c5af431a1f1 75 static inline int ssp_enable(spi_t *obj);
gustavatmel 1:9c5af431a1f1 76
gustavatmel 1:9c5af431a1f1 77 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
gustavatmel 1:9c5af431a1f1 78 // determine the SPI to use
gustavatmel 1:9c5af431a1f1 79 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
gustavatmel 1:9c5af431a1f1 80 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
gustavatmel 1:9c5af431a1f1 81 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
gustavatmel 1:9c5af431a1f1 82 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
gustavatmel 1:9c5af431a1f1 83 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
gustavatmel 1:9c5af431a1f1 84 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
gustavatmel 1:9c5af431a1f1 85
gustavatmel 1:9c5af431a1f1 86 obj->spi = (LPC_SSP_T*)pinmap_merge(spi_data, spi_cntl);
gustavatmel 1:9c5af431a1f1 87 MBED_ASSERT((int)obj->spi != NC);
gustavatmel 1:9c5af431a1f1 88
gustavatmel 1:9c5af431a1f1 89 // enable clocking
gustavatmel 1:9c5af431a1f1 90 switch ((int)obj->spi) {
gustavatmel 1:9c5af431a1f1 91 case SPI_0: LPC_CGU->BASE_CLK[CLK_BASE_SSP0] = (1 << 11) | (CLKIN_MAINPLL << 24); break;
gustavatmel 1:9c5af431a1f1 92 case SPI_1: LPC_CGU->BASE_CLK[CLK_BASE_SSP1] = (1 << 11) | (CLKIN_MAINPLL << 24); break;
gustavatmel 1:9c5af431a1f1 93 }
gustavatmel 1:9c5af431a1f1 94
gustavatmel 1:9c5af431a1f1 95 // pin out the spi pins
gustavatmel 1:9c5af431a1f1 96 pinmap_pinout(mosi, PinMap_SPI_MOSI);
gustavatmel 1:9c5af431a1f1 97 pinmap_pinout(miso, PinMap_SPI_MISO);
gustavatmel 1:9c5af431a1f1 98 pinmap_pinout(sclk, PinMap_SPI_SCLK);
gustavatmel 1:9c5af431a1f1 99 if (ssel != NC) {
gustavatmel 1:9c5af431a1f1 100 pinmap_pinout(ssel, PinMap_SPI_SSEL);
gustavatmel 1:9c5af431a1f1 101 }
gustavatmel 1:9c5af431a1f1 102 }
gustavatmel 1:9c5af431a1f1 103
gustavatmel 1:9c5af431a1f1 104 void spi_free(spi_t *obj) {}
gustavatmel 1:9c5af431a1f1 105
gustavatmel 1:9c5af431a1f1 106 void spi_format(spi_t *obj, int bits, int mode, int slave) {
gustavatmel 1:9c5af431a1f1 107 MBED_ASSERT(((bits >= 4) && (bits <= 16)) || ((mode >= 0) && (mode <= 3)));
gustavatmel 1:9c5af431a1f1 108 ssp_disable(obj);
gustavatmel 1:9c5af431a1f1 109
gustavatmel 1:9c5af431a1f1 110 int polarity = (mode & 0x2) ? 1 : 0;
gustavatmel 1:9c5af431a1f1 111 int phase = (mode & 0x1) ? 1 : 0;
gustavatmel 1:9c5af431a1f1 112
gustavatmel 1:9c5af431a1f1 113 // set it up
gustavatmel 1:9c5af431a1f1 114 int DSS = bits - 1; // DSS (data select size)
gustavatmel 1:9c5af431a1f1 115 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
gustavatmel 1:9c5af431a1f1 116 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
gustavatmel 1:9c5af431a1f1 117
gustavatmel 1:9c5af431a1f1 118 int FRF = 0; // FRF (frame format) = SPI
gustavatmel 1:9c5af431a1f1 119 uint32_t tmp = obj->spi->CR0;
gustavatmel 1:9c5af431a1f1 120 tmp &= ~(0x00FF); // Clear DSS, FRF, CPOL and CPHA [7:0]
gustavatmel 1:9c5af431a1f1 121 tmp |= DSS << 0
gustavatmel 1:9c5af431a1f1 122 | FRF << 4
gustavatmel 1:9c5af431a1f1 123 | SPO << 6
gustavatmel 1:9c5af431a1f1 124 | SPH << 7;
gustavatmel 1:9c5af431a1f1 125 obj->spi->CR0 = tmp;
gustavatmel 1:9c5af431a1f1 126
gustavatmel 1:9c5af431a1f1 127 tmp = obj->spi->CR1;
gustavatmel 1:9c5af431a1f1 128 tmp &= ~(0xD);
gustavatmel 1:9c5af431a1f1 129 tmp |= 0 << 0 // LBM - loop back mode - off
gustavatmel 1:9c5af431a1f1 130 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
gustavatmel 1:9c5af431a1f1 131 | 0 << 3; // SOD - slave output disable - na
gustavatmel 1:9c5af431a1f1 132 obj->spi->CR1 = tmp;
gustavatmel 1:9c5af431a1f1 133 ssp_enable(obj);
gustavatmel 1:9c5af431a1f1 134 }
gustavatmel 1:9c5af431a1f1 135
gustavatmel 1:9c5af431a1f1 136 void spi_frequency(spi_t *obj, int hz) {
gustavatmel 1:9c5af431a1f1 137 ssp_disable(obj);
gustavatmel 1:9c5af431a1f1 138
gustavatmel 1:9c5af431a1f1 139 uint32_t PCLK = SystemCoreClock;
gustavatmel 1:9c5af431a1f1 140
gustavatmel 1:9c5af431a1f1 141 int prescaler;
gustavatmel 1:9c5af431a1f1 142
gustavatmel 1:9c5af431a1f1 143 for (prescaler = 2; prescaler <= 254; prescaler += 2) {
gustavatmel 1:9c5af431a1f1 144 int prescale_hz = PCLK / prescaler;
gustavatmel 1:9c5af431a1f1 145
gustavatmel 1:9c5af431a1f1 146 // calculate the divider
gustavatmel 1:9c5af431a1f1 147 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
gustavatmel 1:9c5af431a1f1 148
gustavatmel 1:9c5af431a1f1 149 // check we can support the divider
gustavatmel 1:9c5af431a1f1 150 if (divider < 256) {
gustavatmel 1:9c5af431a1f1 151 // prescaler
gustavatmel 1:9c5af431a1f1 152 obj->spi->CPSR = prescaler;
gustavatmel 1:9c5af431a1f1 153
gustavatmel 1:9c5af431a1f1 154 // divider
gustavatmel 1:9c5af431a1f1 155 obj->spi->CR0 &= ~(0xFF00); // Clear SCR: Serial clock rate [15:8]
gustavatmel 1:9c5af431a1f1 156 obj->spi->CR0 |= (divider - 1) << 8;
gustavatmel 1:9c5af431a1f1 157 ssp_enable(obj);
gustavatmel 1:9c5af431a1f1 158 return;
gustavatmel 1:9c5af431a1f1 159 }
gustavatmel 1:9c5af431a1f1 160 }
gustavatmel 1:9c5af431a1f1 161 error("Couldn't setup requested SPI frequency");
gustavatmel 1:9c5af431a1f1 162 }
gustavatmel 1:9c5af431a1f1 163
gustavatmel 1:9c5af431a1f1 164 static inline int ssp_disable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 165 return obj->spi->CR1 &= ~(1 << 1);
gustavatmel 1:9c5af431a1f1 166 }
gustavatmel 1:9c5af431a1f1 167
gustavatmel 1:9c5af431a1f1 168 static inline int ssp_enable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 169 return obj->spi->CR1 |= (1 << 1);
gustavatmel 1:9c5af431a1f1 170 }
gustavatmel 1:9c5af431a1f1 171
gustavatmel 1:9c5af431a1f1 172 static inline int ssp_readable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 173 return obj->spi->SR & (1 << 2);
gustavatmel 1:9c5af431a1f1 174 }
gustavatmel 1:9c5af431a1f1 175
gustavatmel 1:9c5af431a1f1 176 static inline int ssp_writeable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 177 return obj->spi->SR & (1 << 1);
gustavatmel 1:9c5af431a1f1 178 }
gustavatmel 1:9c5af431a1f1 179
gustavatmel 1:9c5af431a1f1 180 static inline void ssp_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 181 while (!ssp_writeable(obj));
gustavatmel 1:9c5af431a1f1 182 obj->spi->DR = value;
gustavatmel 1:9c5af431a1f1 183 }
gustavatmel 1:9c5af431a1f1 184
gustavatmel 1:9c5af431a1f1 185 static inline int ssp_read(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 186 while (!ssp_readable(obj));
gustavatmel 1:9c5af431a1f1 187 return obj->spi->DR;
gustavatmel 1:9c5af431a1f1 188 }
gustavatmel 1:9c5af431a1f1 189
gustavatmel 1:9c5af431a1f1 190 static inline int ssp_busy(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 191 return (obj->spi->SR & (1 << 4)) ? (1) : (0);
gustavatmel 1:9c5af431a1f1 192 }
gustavatmel 1:9c5af431a1f1 193
gustavatmel 1:9c5af431a1f1 194 int spi_master_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 195 ssp_write(obj, value);
gustavatmel 1:9c5af431a1f1 196 return ssp_read(obj);
gustavatmel 1:9c5af431a1f1 197 }
gustavatmel 1:9c5af431a1f1 198
gustavatmel 1:9c5af431a1f1 199 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
gustavatmel 1:9c5af431a1f1 200 char *rx_buffer, int rx_length, char write_fill) {
gustavatmel 1:9c5af431a1f1 201 int total = (tx_length > rx_length) ? tx_length : rx_length;
gustavatmel 1:9c5af431a1f1 202
gustavatmel 1:9c5af431a1f1 203 for (int i = 0; i < total; i++) {
gustavatmel 1:9c5af431a1f1 204 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
gustavatmel 1:9c5af431a1f1 205 char in = spi_master_write(obj, out);
gustavatmel 1:9c5af431a1f1 206 if (i < rx_length) {
gustavatmel 1:9c5af431a1f1 207 rx_buffer[i] = in;
gustavatmel 1:9c5af431a1f1 208 }
gustavatmel 1:9c5af431a1f1 209 }
gustavatmel 1:9c5af431a1f1 210
gustavatmel 1:9c5af431a1f1 211 return total;
gustavatmel 1:9c5af431a1f1 212 }
gustavatmel 1:9c5af431a1f1 213
gustavatmel 1:9c5af431a1f1 214 int spi_slave_receive(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 215 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
gustavatmel 1:9c5af431a1f1 216 }
gustavatmel 1:9c5af431a1f1 217
gustavatmel 1:9c5af431a1f1 218 int spi_slave_read(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 219 return obj->spi->DR;
gustavatmel 1:9c5af431a1f1 220 }
gustavatmel 1:9c5af431a1f1 221
gustavatmel 1:9c5af431a1f1 222 void spi_slave_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 223 while (ssp_writeable(obj) == 0) ;
gustavatmel 1:9c5af431a1f1 224 obj->spi->DR = value;
gustavatmel 1:9c5af431a1f1 225 }
gustavatmel 1:9c5af431a1f1 226
gustavatmel 1:9c5af431a1f1 227 int spi_busy(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 228 return ssp_busy(obj);
gustavatmel 1:9c5af431a1f1 229 }