BA / SerialCom

Fork of OmniWheels by Gustav Atmel

Committer:
gustavatmel
Date:
Tue May 01 15:55:34 2018 +0000
Revision:
2:798925c9e4a8
Parent:
1:9c5af431a1f1
bluetooth

Who changed what in which revision?

UserRevisionLine numberNew contents of line
gustavatmel 1:9c5af431a1f1 1 /* mbed Microcontroller Library
gustavatmel 1:9c5af431a1f1 2 *******************************************************************************
gustavatmel 1:9c5af431a1f1 3 * Copyright (c) 2015 WIZnet Co.,Ltd. All rights reserved.
gustavatmel 1:9c5af431a1f1 4 * All rights reserved.
gustavatmel 1:9c5af431a1f1 5 *
gustavatmel 1:9c5af431a1f1 6 * Redistribution and use in source and binary forms, with or without
gustavatmel 1:9c5af431a1f1 7 * modification, are permitted provided that the following conditions are met:
gustavatmel 1:9c5af431a1f1 8 *
gustavatmel 1:9c5af431a1f1 9 * 1. Redistributions of source code must retain the above copyright notice,
gustavatmel 1:9c5af431a1f1 10 * this list of conditions and the following disclaimer.
gustavatmel 1:9c5af431a1f1 11 * 2. Redistributions in binary form must reproduce the above copyright notice,
gustavatmel 1:9c5af431a1f1 12 * this list of conditions and the following disclaimer in the documentation
gustavatmel 1:9c5af431a1f1 13 * and/or other materials provided with the distribution.
gustavatmel 1:9c5af431a1f1 14 * 3. Neither the name of ARM Limited nor the names of its contributors
gustavatmel 1:9c5af431a1f1 15 * may be used to endorse or promote products derived from this software
gustavatmel 1:9c5af431a1f1 16 * without specific prior written permission.
gustavatmel 1:9c5af431a1f1 17 *
gustavatmel 1:9c5af431a1f1 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
gustavatmel 1:9c5af431a1f1 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
gustavatmel 1:9c5af431a1f1 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
gustavatmel 1:9c5af431a1f1 21 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
gustavatmel 1:9c5af431a1f1 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
gustavatmel 1:9c5af431a1f1 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
gustavatmel 1:9c5af431a1f1 24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
gustavatmel 1:9c5af431a1f1 25 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
gustavatmel 1:9c5af431a1f1 26 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
gustavatmel 1:9c5af431a1f1 27 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
gustavatmel 1:9c5af431a1f1 28 *******************************************************************************
gustavatmel 1:9c5af431a1f1 29 */
gustavatmel 1:9c5af431a1f1 30
gustavatmel 1:9c5af431a1f1 31 #include "mbed_assert.h"
gustavatmel 1:9c5af431a1f1 32 #include <math.h>
gustavatmel 1:9c5af431a1f1 33
gustavatmel 1:9c5af431a1f1 34 #include "spi_api.h"
gustavatmel 1:9c5af431a1f1 35 #include "cmsis.h"
gustavatmel 1:9c5af431a1f1 36 #include "pinmap.h"
gustavatmel 1:9c5af431a1f1 37 #include "mbed_error.h"
gustavatmel 1:9c5af431a1f1 38 #include "PeripheralPins.h"
gustavatmel 1:9c5af431a1f1 39
gustavatmel 1:9c5af431a1f1 40 static inline int ssp_disable(spi_t *obj);
gustavatmel 1:9c5af431a1f1 41 static inline int ssp_enable(spi_t *obj);
gustavatmel 1:9c5af431a1f1 42
gustavatmel 1:9c5af431a1f1 43 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
gustavatmel 1:9c5af431a1f1 44 // determine the SPI to use
gustavatmel 1:9c5af431a1f1 45 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
gustavatmel 1:9c5af431a1f1 46 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
gustavatmel 1:9c5af431a1f1 47 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
gustavatmel 1:9c5af431a1f1 48 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
gustavatmel 1:9c5af431a1f1 49 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
gustavatmel 1:9c5af431a1f1 50 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
gustavatmel 1:9c5af431a1f1 51 obj->spi = (SSP_TypeDef*)pinmap_merge(spi_data, spi_cntl);
gustavatmel 1:9c5af431a1f1 52 MBED_ASSERT((int)obj->spi != NC);
gustavatmel 1:9c5af431a1f1 53
gustavatmel 1:9c5af431a1f1 54 // enable power and clocking
gustavatmel 1:9c5af431a1f1 55 switch ((int)obj->spi) {
gustavatmel 1:9c5af431a1f1 56 case SPI_0: CRG->SSPCLK_SSR = CRG_SSPCLK_SSR_MCLK; break; //PLL output clock
gustavatmel 1:9c5af431a1f1 57 case SPI_1: CRG->SSPCLK_SSR = CRG_SSPCLK_SSR_MCLK; break;
gustavatmel 1:9c5af431a1f1 58 }
gustavatmel 1:9c5af431a1f1 59
gustavatmel 1:9c5af431a1f1 60 // set default format and frequency
gustavatmel 1:9c5af431a1f1 61 if (ssel == NC) {
gustavatmel 1:9c5af431a1f1 62 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
gustavatmel 1:9c5af431a1f1 63 } else {
gustavatmel 1:9c5af431a1f1 64 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
gustavatmel 1:9c5af431a1f1 65 }
gustavatmel 1:9c5af431a1f1 66 spi_frequency(obj, 1000000);
gustavatmel 1:9c5af431a1f1 67
gustavatmel 1:9c5af431a1f1 68 // enable the ssp channel
gustavatmel 1:9c5af431a1f1 69 ssp_enable(obj);
gustavatmel 1:9c5af431a1f1 70
gustavatmel 1:9c5af431a1f1 71 // pin out the spi pins
gustavatmel 1:9c5af431a1f1 72 pinmap_pinout(mosi, PinMap_SPI_MOSI);
gustavatmel 1:9c5af431a1f1 73 pinmap_pinout(miso, PinMap_SPI_MISO);
gustavatmel 1:9c5af431a1f1 74 pinmap_pinout(sclk, PinMap_SPI_SCLK);
gustavatmel 1:9c5af431a1f1 75 if (ssel != NC) {
gustavatmel 1:9c5af431a1f1 76 pinmap_pinout(ssel, PinMap_SPI_SSEL);
gustavatmel 1:9c5af431a1f1 77 }
gustavatmel 1:9c5af431a1f1 78 }
gustavatmel 1:9c5af431a1f1 79
gustavatmel 1:9c5af431a1f1 80 void spi_free(spi_t *obj) {}
gustavatmel 1:9c5af431a1f1 81
gustavatmel 1:9c5af431a1f1 82 void spi_format(spi_t *obj, int bits, int mode, int slave) {
gustavatmel 1:9c5af431a1f1 83 ssp_disable(obj);
gustavatmel 1:9c5af431a1f1 84 MBED_ASSERT(((bits >= 4) && (bits <= 16)) && (mode >= 0 && mode <= 3));
gustavatmel 1:9c5af431a1f1 85
gustavatmel 1:9c5af431a1f1 86 int polarity = (mode & 0x2) ? 1 : 0;
gustavatmel 1:9c5af431a1f1 87 int phase = (mode & 0x1) ? 1 : 0;
gustavatmel 1:9c5af431a1f1 88
gustavatmel 1:9c5af431a1f1 89 // set it up
gustavatmel 1:9c5af431a1f1 90 int DSS = bits - 1; // DSS (data select size)
gustavatmel 1:9c5af431a1f1 91 int SPO = (polarity) ? 1 : 0; // SPO - clock out polarity
gustavatmel 1:9c5af431a1f1 92 int SPH = (phase) ? 1 : 0; // SPH - clock out phase
gustavatmel 1:9c5af431a1f1 93
gustavatmel 1:9c5af431a1f1 94 int FRF = 0; // FRF (frame format) = SPI
gustavatmel 1:9c5af431a1f1 95 uint32_t tmp = obj->spi->CR0;
gustavatmel 1:9c5af431a1f1 96 tmp &= ~(0xFFFF);
gustavatmel 1:9c5af431a1f1 97 tmp |= DSS << 0
gustavatmel 1:9c5af431a1f1 98 | FRF << 4
gustavatmel 1:9c5af431a1f1 99 | SPO << 6
gustavatmel 1:9c5af431a1f1 100 | SPH << 7;
gustavatmel 1:9c5af431a1f1 101 obj->spi->CR0 = tmp;
gustavatmel 1:9c5af431a1f1 102
gustavatmel 1:9c5af431a1f1 103 tmp = obj->spi->CR1;
gustavatmel 1:9c5af431a1f1 104 tmp &= ~(0xD);
gustavatmel 1:9c5af431a1f1 105 tmp |= 0 << 0 // LBM - loop back mode - off
gustavatmel 1:9c5af431a1f1 106 | ((slave) ? 1 : 0) << 2 // MS - master slave mode, 1 = slave
gustavatmel 1:9c5af431a1f1 107 | 0 << 3; // SOD - slave output disable - na
gustavatmel 1:9c5af431a1f1 108 obj->spi->CR1 = tmp;
gustavatmel 1:9c5af431a1f1 109
gustavatmel 1:9c5af431a1f1 110 ssp_enable(obj);
gustavatmel 1:9c5af431a1f1 111 }
gustavatmel 1:9c5af431a1f1 112
gustavatmel 1:9c5af431a1f1 113 void spi_frequency(spi_t *obj, int hz) {
gustavatmel 1:9c5af431a1f1 114 ssp_disable(obj);
gustavatmel 1:9c5af431a1f1 115
gustavatmel 1:9c5af431a1f1 116 // setup the spi clock diveder to /1
gustavatmel 1:9c5af431a1f1 117 switch ((int)obj->spi) {
gustavatmel 1:9c5af431a1f1 118 case SPI_0:
gustavatmel 1:9c5af431a1f1 119 CRG->SSPCLK_PVSR = CRG_SSPCLK_PVSR_DIV1; //1/1 (bypass)
gustavatmel 1:9c5af431a1f1 120 break;
gustavatmel 1:9c5af431a1f1 121 case SPI_1:
gustavatmel 1:9c5af431a1f1 122 CRG->SSPCLK_PVSR = CRG_SSPCLK_PVSR_DIV1; //1/1 (bypass)
gustavatmel 1:9c5af431a1f1 123 break;
gustavatmel 1:9c5af431a1f1 124 }
gustavatmel 1:9c5af431a1f1 125
gustavatmel 1:9c5af431a1f1 126 uint32_t HCLK = SystemCoreClock;
gustavatmel 1:9c5af431a1f1 127
gustavatmel 1:9c5af431a1f1 128 int prescaler;
gustavatmel 1:9c5af431a1f1 129
gustavatmel 1:9c5af431a1f1 130 for (prescaler = 2; prescaler <= 254; prescaler += 2) {
gustavatmel 1:9c5af431a1f1 131 int prescale_hz = HCLK / prescaler;
gustavatmel 1:9c5af431a1f1 132
gustavatmel 1:9c5af431a1f1 133 // calculate the divider
gustavatmel 1:9c5af431a1f1 134 int divider = floor(((float)prescale_hz / (float)hz) + 0.5f);
gustavatmel 1:9c5af431a1f1 135
gustavatmel 1:9c5af431a1f1 136 // check we can support the divider
gustavatmel 1:9c5af431a1f1 137 if (divider < 256) {
gustavatmel 1:9c5af431a1f1 138 // prescaler
gustavatmel 1:9c5af431a1f1 139 obj->spi->CPSR = prescaler;
gustavatmel 1:9c5af431a1f1 140
gustavatmel 1:9c5af431a1f1 141 // divider
gustavatmel 1:9c5af431a1f1 142 obj->spi->CR0 &= ~(0xFFFF << 8);
gustavatmel 1:9c5af431a1f1 143 obj->spi->CR0 |= (divider - 1) << 8;
gustavatmel 1:9c5af431a1f1 144 ssp_enable(obj);
gustavatmel 1:9c5af431a1f1 145 return;
gustavatmel 1:9c5af431a1f1 146 }
gustavatmel 1:9c5af431a1f1 147 }
gustavatmel 1:9c5af431a1f1 148 error("Couldn't setup requested SPI frequency");
gustavatmel 1:9c5af431a1f1 149 }
gustavatmel 1:9c5af431a1f1 150
gustavatmel 1:9c5af431a1f1 151 static inline int ssp_disable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 152 return obj->spi->CR1 &= ~(1 << 1);
gustavatmel 1:9c5af431a1f1 153 }
gustavatmel 1:9c5af431a1f1 154
gustavatmel 1:9c5af431a1f1 155 static inline int ssp_enable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 156 return obj->spi->CR1 |= (1 << 1);
gustavatmel 1:9c5af431a1f1 157 }
gustavatmel 1:9c5af431a1f1 158
gustavatmel 1:9c5af431a1f1 159 static inline int ssp_readable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 160 return obj->spi->SR & (1 << 2);
gustavatmel 1:9c5af431a1f1 161 }
gustavatmel 1:9c5af431a1f1 162
gustavatmel 1:9c5af431a1f1 163 static inline int ssp_writeable(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 164 return obj->spi->SR & (1 << 1);
gustavatmel 1:9c5af431a1f1 165 }
gustavatmel 1:9c5af431a1f1 166
gustavatmel 1:9c5af431a1f1 167 static inline void ssp_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 168 while (!ssp_writeable(obj));
gustavatmel 1:9c5af431a1f1 169 obj->spi->DR = value;
gustavatmel 1:9c5af431a1f1 170 }
gustavatmel 1:9c5af431a1f1 171
gustavatmel 1:9c5af431a1f1 172 static inline int ssp_read(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 173 while (!ssp_readable(obj));
gustavatmel 1:9c5af431a1f1 174 return obj->spi->DR;
gustavatmel 1:9c5af431a1f1 175 }
gustavatmel 1:9c5af431a1f1 176
gustavatmel 1:9c5af431a1f1 177 static inline int ssp_busy(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 178 return (obj->spi->SR & (1 << 4)) ? (1) : (0);
gustavatmel 1:9c5af431a1f1 179 }
gustavatmel 1:9c5af431a1f1 180
gustavatmel 1:9c5af431a1f1 181 int spi_master_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 182 ssp_write(obj, value);
gustavatmel 1:9c5af431a1f1 183 return ssp_read(obj);
gustavatmel 1:9c5af431a1f1 184 }
gustavatmel 1:9c5af431a1f1 185
gustavatmel 1:9c5af431a1f1 186 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
gustavatmel 1:9c5af431a1f1 187 char *rx_buffer, int rx_length, char write_fill) {
gustavatmel 1:9c5af431a1f1 188 int total = (tx_length > rx_length) ? tx_length : rx_length;
gustavatmel 1:9c5af431a1f1 189
gustavatmel 1:9c5af431a1f1 190 for (int i = 0; i < total; i++) {
gustavatmel 1:9c5af431a1f1 191 char out = (i < tx_length) ? tx_buffer[i] : write_fill;
gustavatmel 1:9c5af431a1f1 192 char in = spi_master_write(obj, out);
gustavatmel 1:9c5af431a1f1 193 if (i < rx_length) {
gustavatmel 1:9c5af431a1f1 194 rx_buffer[i] = in;
gustavatmel 1:9c5af431a1f1 195 }
gustavatmel 1:9c5af431a1f1 196 }
gustavatmel 1:9c5af431a1f1 197
gustavatmel 1:9c5af431a1f1 198 return total;
gustavatmel 1:9c5af431a1f1 199 }
gustavatmel 1:9c5af431a1f1 200
gustavatmel 1:9c5af431a1f1 201 int spi_slave_receive(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 202 return (ssp_readable(obj) && !ssp_busy(obj)) ? (1) : (0);
gustavatmel 1:9c5af431a1f1 203 }
gustavatmel 1:9c5af431a1f1 204
gustavatmel 1:9c5af431a1f1 205 int spi_slave_read(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 206 return obj->spi->DR;
gustavatmel 1:9c5af431a1f1 207 }
gustavatmel 1:9c5af431a1f1 208
gustavatmel 1:9c5af431a1f1 209 void spi_slave_write(spi_t *obj, int value) {
gustavatmel 1:9c5af431a1f1 210 while (ssp_writeable(obj) == 0) ;
gustavatmel 1:9c5af431a1f1 211 obj->spi->DR = value;
gustavatmel 1:9c5af431a1f1 212 }
gustavatmel 1:9c5af431a1f1 213
gustavatmel 1:9c5af431a1f1 214 int spi_busy(spi_t *obj) {
gustavatmel 1:9c5af431a1f1 215 return ssp_busy(obj);
gustavatmel 1:9c5af431a1f1 216 }
gustavatmel 1:9c5af431a1f1 217