Color Oled(SSD1331) connect to STMicroelectronics Nucleo-F466

Dependencies:   ssd1331

Committer:
kadonotakashi
Date:
Thu Oct 11 02:27:46 2018 +0000
Revision:
3:f3764f852aa8
Parent:
0:8fdf9a60065b
Nucreo 446 + SSD1331 test version;

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kadonotakashi 0:8fdf9a60065b 1 /* mbed Microcontroller Library
kadonotakashi 0:8fdf9a60065b 2 * Copyright (c) 2006-2013 ARM Limited
kadonotakashi 0:8fdf9a60065b 3 *
kadonotakashi 0:8fdf9a60065b 4 * Licensed under the Apache License, Version 2.0 (the "License");
kadonotakashi 0:8fdf9a60065b 5 * you may not use this file except in compliance with the License.
kadonotakashi 0:8fdf9a60065b 6 * You may obtain a copy of the License at
kadonotakashi 0:8fdf9a60065b 7 *
kadonotakashi 0:8fdf9a60065b 8 * http://www.apache.org/licenses/LICENSE-2.0
kadonotakashi 0:8fdf9a60065b 9 *
kadonotakashi 0:8fdf9a60065b 10 * Unless required by applicable law or agreed to in writing, software
kadonotakashi 0:8fdf9a60065b 11 * distributed under the License is distributed on an "AS IS" BASIS,
kadonotakashi 0:8fdf9a60065b 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
kadonotakashi 0:8fdf9a60065b 13 * See the License for the specific language governing permissions and
kadonotakashi 0:8fdf9a60065b 14 * limitations under the License.
kadonotakashi 0:8fdf9a60065b 15 */
kadonotakashi 0:8fdf9a60065b 16
kadonotakashi 0:8fdf9a60065b 17 #include "device.h"
kadonotakashi 0:8fdf9a60065b 18 #include "dma_api.h"
kadonotakashi 0:8fdf9a60065b 19 #include "buffer.h"
kadonotakashi 0:8fdf9a60065b 20 #include "spi_api.h"
kadonotakashi 0:8fdf9a60065b 21 #include "pinmap.h"
kadonotakashi 0:8fdf9a60065b 22 #include "spi_driver.h"
kadonotakashi 0:8fdf9a60065b 23 #include "PeripheralPins.h"
kadonotakashi 0:8fdf9a60065b 24 #include "pdc.h"
kadonotakashi 0:8fdf9a60065b 25
kadonotakashi 0:8fdf9a60065b 26
kadonotakashi 0:8fdf9a60065b 27 /* Chip select. */
kadonotakashi 0:8fdf9a60065b 28 #define SPI_CHIP_SEL 0
kadonotakashi 0:8fdf9a60065b 29
kadonotakashi 0:8fdf9a60065b 30 /* Clock polarity. */
kadonotakashi 0:8fdf9a60065b 31 #define SPI_CLK_POLARITY 0
kadonotakashi 0:8fdf9a60065b 32
kadonotakashi 0:8fdf9a60065b 33 /* Clock phase. */
kadonotakashi 0:8fdf9a60065b 34 #define SPI_CLK_PHASE 0
kadonotakashi 0:8fdf9a60065b 35
kadonotakashi 0:8fdf9a60065b 36 /* Last data */
kadonotakashi 0:8fdf9a60065b 37 #define SPI_LAST 0
kadonotakashi 0:8fdf9a60065b 38
kadonotakashi 0:8fdf9a60065b 39
kadonotakashi 0:8fdf9a60065b 40 /* Delay before SPCK. */
kadonotakashi 0:8fdf9a60065b 41 #define SPI_DLYBS 0x40
kadonotakashi 0:8fdf9a60065b 42
kadonotakashi 0:8fdf9a60065b 43 /* Delay between consecutive transfers. */
kadonotakashi 0:8fdf9a60065b 44 #define SPI_DLYBCT 0x10
kadonotakashi 0:8fdf9a60065b 45
kadonotakashi 0:8fdf9a60065b 46 #define MAX_SPI 8
kadonotakashi 0:8fdf9a60065b 47
kadonotakashi 0:8fdf9a60065b 48 /* SPI clock setting (Hz). */
kadonotakashi 0:8fdf9a60065b 49 uint32_t gSPI_clock=500000;
kadonotakashi 0:8fdf9a60065b 50
kadonotakashi 0:8fdf9a60065b 51 extern uint8_t g_sys_init;
kadonotakashi 0:8fdf9a60065b 52
kadonotakashi 0:8fdf9a60065b 53
kadonotakashi 0:8fdf9a60065b 54
kadonotakashi 0:8fdf9a60065b 55 void pinmap_find_spi_info(Spi *sercombase, spi_t *obj)
kadonotakashi 0:8fdf9a60065b 56 {
kadonotakashi 0:8fdf9a60065b 57 if(sercombase==SPI0) {
kadonotakashi 0:8fdf9a60065b 58 obj->spi.flexcom=FLEXCOM0;
kadonotakashi 0:8fdf9a60065b 59 obj->spi.module_number=0;
kadonotakashi 0:8fdf9a60065b 60 obj->spi.pdc =PDC_SPI0;
kadonotakashi 0:8fdf9a60065b 61 obj->spi.irq_type=FLEXCOM0_IRQn;
kadonotakashi 0:8fdf9a60065b 62 } else if(sercombase==SPI1) {
kadonotakashi 0:8fdf9a60065b 63 obj->spi.flexcom=FLEXCOM1;
kadonotakashi 0:8fdf9a60065b 64 obj->spi.module_number=1;
kadonotakashi 0:8fdf9a60065b 65 obj->spi.pdc =PDC_SPI1;
kadonotakashi 0:8fdf9a60065b 66 obj->spi.irq_type=FLEXCOM1_IRQn;
kadonotakashi 0:8fdf9a60065b 67 } else if(sercombase==SPI2) {
kadonotakashi 0:8fdf9a60065b 68 obj->spi.flexcom=FLEXCOM2;
kadonotakashi 0:8fdf9a60065b 69 obj->spi.module_number=2;
kadonotakashi 0:8fdf9a60065b 70 obj->spi.pdc =PDC_SPI2;
kadonotakashi 0:8fdf9a60065b 71 obj->spi.irq_type=FLEXCOM2_IRQn;
kadonotakashi 0:8fdf9a60065b 72 } else if(sercombase==SPI3) {
kadonotakashi 0:8fdf9a60065b 73 obj->spi.flexcom=FLEXCOM3;
kadonotakashi 0:8fdf9a60065b 74 obj->spi.module_number=3;
kadonotakashi 0:8fdf9a60065b 75 obj->spi.pdc =PDC_SPI3;
kadonotakashi 0:8fdf9a60065b 76 obj->spi.irq_type=FLEXCOM3_IRQn;
kadonotakashi 0:8fdf9a60065b 77 } else if(sercombase==SPI4) {
kadonotakashi 0:8fdf9a60065b 78 obj->spi.flexcom=FLEXCOM4;
kadonotakashi 0:8fdf9a60065b 79 obj->spi.module_number=4;
kadonotakashi 0:8fdf9a60065b 80 obj->spi.pdc =PDC_SPI4;
kadonotakashi 0:8fdf9a60065b 81 obj->spi.irq_type=FLEXCOM4_IRQn;
kadonotakashi 0:8fdf9a60065b 82 } else if(sercombase==SPI5) {
kadonotakashi 0:8fdf9a60065b 83 obj->spi.flexcom=FLEXCOM5;
kadonotakashi 0:8fdf9a60065b 84 obj->spi.module_number=5;
kadonotakashi 0:8fdf9a60065b 85 obj->spi.pdc =PDC_SPI5;
kadonotakashi 0:8fdf9a60065b 86 obj->spi.irq_type=FLEXCOM5_IRQn;
kadonotakashi 0:8fdf9a60065b 87 } else if(sercombase==SPI6) {
kadonotakashi 0:8fdf9a60065b 88 obj->spi.flexcom=FLEXCOM6;
kadonotakashi 0:8fdf9a60065b 89 obj->spi.module_number=6;
kadonotakashi 0:8fdf9a60065b 90 obj->spi.pdc =PDC_SPI6;
kadonotakashi 0:8fdf9a60065b 91 obj->spi.irq_type=FLEXCOM6_IRQn;
kadonotakashi 0:8fdf9a60065b 92 } else if(sercombase==SPI7) {
kadonotakashi 0:8fdf9a60065b 93 obj->spi.flexcom=FLEXCOM7;
kadonotakashi 0:8fdf9a60065b 94 obj->spi.module_number=7;
kadonotakashi 0:8fdf9a60065b 95 obj->spi.pdc =PDC_SPI7;
kadonotakashi 0:8fdf9a60065b 96 obj->spi.irq_type=FLEXCOM7_IRQn;
kadonotakashi 0:8fdf9a60065b 97 } else {
kadonotakashi 0:8fdf9a60065b 98 obj->spi.flexcom=(Flexcom *)NC;
kadonotakashi 0:8fdf9a60065b 99 obj->spi.module_number=0;
kadonotakashi 0:8fdf9a60065b 100 obj->spi.pdc =(Pdc *) NC;
kadonotakashi 0:8fdf9a60065b 101 }
kadonotakashi 0:8fdf9a60065b 102 }
kadonotakashi 0:8fdf9a60065b 103
kadonotakashi 0:8fdf9a60065b 104 Spi* pinmap_find_sercom(PinName mosi, PinName miso, PinName sclk)
kadonotakashi 0:8fdf9a60065b 105 {
kadonotakashi 0:8fdf9a60065b 106 Spi* sercomIndex=(Spi*)pinmap_peripheral (mosi,PinMap_SPI_MOSI);
kadonotakashi 0:8fdf9a60065b 107 if(sercomIndex== (Spi*)pinmap_peripheral (miso, PinMap_SPI_MISO) &&
kadonotakashi 0:8fdf9a60065b 108 sercomIndex == (Spi*)pinmap_peripheral (sclk, PinMap_SPI_SCLK))
kadonotakashi 0:8fdf9a60065b 109 return sercomIndex;
kadonotakashi 0:8fdf9a60065b 110
kadonotakashi 0:8fdf9a60065b 111 return (Spi*)NC;
kadonotakashi 0:8fdf9a60065b 112 }
kadonotakashi 0:8fdf9a60065b 113
kadonotakashi 0:8fdf9a60065b 114
kadonotakashi 0:8fdf9a60065b 115 /** Initialize the SPI peripheral
kadonotakashi 0:8fdf9a60065b 116 *
kadonotakashi 0:8fdf9a60065b 117 * Configures the pins used by SPI, sets a default format and frequency, and enables the peripheral
kadonotakashi 0:8fdf9a60065b 118 * @param[out] obj The SPI object to initialize
kadonotakashi 0:8fdf9a60065b 119 * @param[in] mosi The pin to use for MOSI
kadonotakashi 0:8fdf9a60065b 120 * @param[in] miso The pin to use for MISO
kadonotakashi 0:8fdf9a60065b 121 * @param[in] sclk The pin to use for SCLK
kadonotakashi 0:8fdf9a60065b 122 * @param[in] ssel The pin to use for SSEL <Not Used>
kadonotakashi 0:8fdf9a60065b 123 */
kadonotakashi 0:8fdf9a60065b 124 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel /*Not Used*/)
kadonotakashi 0:8fdf9a60065b 125 {
kadonotakashi 0:8fdf9a60065b 126 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 127 MBED_ASSERT(mosi !=NC && miso!=NC && sclk !=NC );
kadonotakashi 0:8fdf9a60065b 128
kadonotakashi 0:8fdf9a60065b 129 if (g_sys_init == 0) {
kadonotakashi 0:8fdf9a60065b 130 sysclk_init();
kadonotakashi 0:8fdf9a60065b 131 system_board_init();
kadonotakashi 0:8fdf9a60065b 132 g_sys_init = 1;
kadonotakashi 0:8fdf9a60065b 133 }
kadonotakashi 0:8fdf9a60065b 134
kadonotakashi 0:8fdf9a60065b 135 Spi *sercombase = pinmap_find_sercom(mosi,miso,sclk);
kadonotakashi 0:8fdf9a60065b 136 MBED_ASSERT(sercombase!=NC);
kadonotakashi 0:8fdf9a60065b 137
kadonotakashi 0:8fdf9a60065b 138 pinmap_find_spi_info(sercombase, obj);
kadonotakashi 0:8fdf9a60065b 139 MBED_ASSERT(obj->spi.flexcom!=NC);
kadonotakashi 0:8fdf9a60065b 140 MBED_ASSERT(obj->spi.pdc!=NC);
kadonotakashi 0:8fdf9a60065b 141
kadonotakashi 0:8fdf9a60065b 142 /* Configure SPI pins */
kadonotakashi 0:8fdf9a60065b 143 pin_function(mosi, pinmap_find_function(mosi, PinMap_SPI_MOSI));
kadonotakashi 0:8fdf9a60065b 144 ioport_disable_pin(mosi);
kadonotakashi 0:8fdf9a60065b 145
kadonotakashi 0:8fdf9a60065b 146 pin_function(miso, pinmap_find_function(miso, PinMap_SPI_MISO));
kadonotakashi 0:8fdf9a60065b 147 ioport_disable_pin(miso);
kadonotakashi 0:8fdf9a60065b 148
kadonotakashi 0:8fdf9a60065b 149 pin_function(sclk, pinmap_find_function(sclk, PinMap_SPI_SCLK));
kadonotakashi 0:8fdf9a60065b 150 ioport_disable_pin(sclk);
kadonotakashi 0:8fdf9a60065b 151
kadonotakashi 0:8fdf9a60065b 152 #if (SAMG55)
kadonotakashi 0:8fdf9a60065b 153 /* Enable the peripheral and set SPI mode. */
kadonotakashi 0:8fdf9a60065b 154 flexcom_enable(obj->spi.flexcom);
kadonotakashi 0:8fdf9a60065b 155 flexcom_set_opmode(obj->spi.flexcom, FLEXCOM_SPI);
kadonotakashi 0:8fdf9a60065b 156 #else
kadonotakashi 0:8fdf9a60065b 157 /* Configure an SPI peripheral. */
kadonotakashi 0:8fdf9a60065b 158 spi_enable_clock(sercombase);
kadonotakashi 0:8fdf9a60065b 159 #endif
kadonotakashi 0:8fdf9a60065b 160 spi_disable(sercombase);
kadonotakashi 0:8fdf9a60065b 161 spi_reset(sercombase);
kadonotakashi 0:8fdf9a60065b 162 spi_set_lastxfer(sercombase);
kadonotakashi 0:8fdf9a60065b 163 spi_set_master_mode(sercombase);
kadonotakashi 0:8fdf9a60065b 164 spi_disable_mode_fault_detect(sercombase);
kadonotakashi 0:8fdf9a60065b 165 spi_set_peripheral_chip_select_value(sercombase, SPI_CHIP_SEL);
kadonotakashi 0:8fdf9a60065b 166 spi_set_clock_polarity(sercombase, SPI_CHIP_SEL, SPI_CLK_POLARITY);
kadonotakashi 0:8fdf9a60065b 167 spi_set_clock_phase(sercombase, SPI_CHIP_SEL, SPI_CLK_PHASE);
kadonotakashi 0:8fdf9a60065b 168 spi_set_bits_per_transfer(sercombase, SPI_CHIP_SEL, SPI_CSR_BITS_8_BIT);
kadonotakashi 0:8fdf9a60065b 169 spi_set_baudrate_div(sercombase, SPI_CHIP_SEL,(sysclk_get_cpu_hz() / gSPI_clock));
kadonotakashi 0:8fdf9a60065b 170 spi_set_transfer_delay(sercombase, SPI_CHIP_SEL, SPI_DLYBS,SPI_DLYBCT);
kadonotakashi 0:8fdf9a60065b 171
kadonotakashi 0:8fdf9a60065b 172 spi_enable(sercombase);
kadonotakashi 0:8fdf9a60065b 173
kadonotakashi 0:8fdf9a60065b 174 pdc_disable_transfer(obj->spi.pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
kadonotakashi 0:8fdf9a60065b 175
kadonotakashi 0:8fdf9a60065b 176 obj->spi.spi_base=sercombase;
kadonotakashi 0:8fdf9a60065b 177 obj->spi.cs= SPI_CHIP_SEL;
kadonotakashi 0:8fdf9a60065b 178 obj->spi.polarity=SPI_CLK_POLARITY;
kadonotakashi 0:8fdf9a60065b 179 obj->spi.phase=SPI_CLK_PHASE;
kadonotakashi 0:8fdf9a60065b 180 obj->spi.transferrate=SPI_CSR_BITS_8_BIT;
kadonotakashi 0:8fdf9a60065b 181 obj->spi.is_slave=0;
kadonotakashi 0:8fdf9a60065b 182 }
kadonotakashi 0:8fdf9a60065b 183
kadonotakashi 0:8fdf9a60065b 184 /** Release a SPI object
kadonotakashi 0:8fdf9a60065b 185 *
kadonotakashi 0:8fdf9a60065b 186 * TODO: spi_free is currently unimplemented
kadonotakashi 0:8fdf9a60065b 187 * This will require reference counting at the C++ level to be safe
kadonotakashi 0:8fdf9a60065b 188 *
kadonotakashi 0:8fdf9a60065b 189 * Return the pins owned by the SPI object to their reset state
kadonotakashi 0:8fdf9a60065b 190 * Disable the SPI peripheral
kadonotakashi 0:8fdf9a60065b 191 * Disable the SPI clock
kadonotakashi 0:8fdf9a60065b 192 * @param[in] obj The SPI object to deinitialize
kadonotakashi 0:8fdf9a60065b 193 */
kadonotakashi 0:8fdf9a60065b 194 void spi_free(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 195 {
kadonotakashi 0:8fdf9a60065b 196 MBED_ASSERT(obj);
kadonotakashi 0:8fdf9a60065b 197 spi_disable(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 198 spi_reset(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 199 flexcom_disable((Flexcom *)obj->spi.flexcom);
kadonotakashi 0:8fdf9a60065b 200 }
kadonotakashi 0:8fdf9a60065b 201
kadonotakashi 0:8fdf9a60065b 202 uint32_t get_transfer_rate(int bits)
kadonotakashi 0:8fdf9a60065b 203 {
kadonotakashi 0:8fdf9a60065b 204 switch(bits) {
kadonotakashi 0:8fdf9a60065b 205 case 8:
kadonotakashi 0:8fdf9a60065b 206 return SPI_CSR_BITS_8_BIT;
kadonotakashi 0:8fdf9a60065b 207 case 9:
kadonotakashi 0:8fdf9a60065b 208 return SPI_CSR_BITS_9_BIT;
kadonotakashi 0:8fdf9a60065b 209 case 10:
kadonotakashi 0:8fdf9a60065b 210 return SPI_CSR_BITS_10_BIT;
kadonotakashi 0:8fdf9a60065b 211 case 11:
kadonotakashi 0:8fdf9a60065b 212 return SPI_CSR_BITS_11_BIT;
kadonotakashi 0:8fdf9a60065b 213 case 12:
kadonotakashi 0:8fdf9a60065b 214 return SPI_CSR_BITS_12_BIT;
kadonotakashi 0:8fdf9a60065b 215 case 13:
kadonotakashi 0:8fdf9a60065b 216 return SPI_CSR_BITS_13_BIT;
kadonotakashi 0:8fdf9a60065b 217 case 14:
kadonotakashi 0:8fdf9a60065b 218 return SPI_CSR_BITS_14_BIT;
kadonotakashi 0:8fdf9a60065b 219 case 15:
kadonotakashi 0:8fdf9a60065b 220 return SPI_CSR_BITS_15_BIT;
kadonotakashi 0:8fdf9a60065b 221 case 16:
kadonotakashi 0:8fdf9a60065b 222 return SPI_CSR_BITS_16_BIT;
kadonotakashi 0:8fdf9a60065b 223 default:
kadonotakashi 0:8fdf9a60065b 224 return NC;
kadonotakashi 0:8fdf9a60065b 225 }
kadonotakashi 0:8fdf9a60065b 226 }
kadonotakashi 0:8fdf9a60065b 227
kadonotakashi 0:8fdf9a60065b 228 /** Configure the SPI format
kadonotakashi 0:8fdf9a60065b 229 *
kadonotakashi 0:8fdf9a60065b 230 * Set the number of bits per frame, configure clock polarity and phase, shift order and master/slave mode
kadonotakashi 0:8fdf9a60065b 231 * @param[in,out] obj The SPI object to configure
kadonotakashi 0:8fdf9a60065b 232 * @param[in] bits The number of bits per frame
kadonotakashi 0:8fdf9a60065b 233 * @param[in] mode The SPI mode (clock polarity, phase, and shift direction)
kadonotakashi 0:8fdf9a60065b 234 * @param[in] slave Zero for master mode or non-zero for slave mode
kadonotakashi 0:8fdf9a60065b 235 */
kadonotakashi 0:8fdf9a60065b 236 void spi_format(spi_t *obj, int bits, int mode, int slave)
kadonotakashi 0:8fdf9a60065b 237 {
kadonotakashi 0:8fdf9a60065b 238 uint32_t transferrate= get_transfer_rate(bits);
kadonotakashi 0:8fdf9a60065b 239 MBED_ASSERT(transferrate!=NC);
kadonotakashi 0:8fdf9a60065b 240
kadonotakashi 0:8fdf9a60065b 241 spi_disable(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 242 obj->spi.transferrate=transferrate;
kadonotakashi 0:8fdf9a60065b 243 if(slave) {
kadonotakashi 0:8fdf9a60065b 244 spi_set_slave_mode(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 245 obj->spi.is_slave=1;
kadonotakashi 0:8fdf9a60065b 246 } else {
kadonotakashi 0:8fdf9a60065b 247 spi_set_master_mode(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 248 obj->spi.is_slave=0;
kadonotakashi 0:8fdf9a60065b 249 }
kadonotakashi 0:8fdf9a60065b 250 spi_set_bits_per_transfer(obj->spi.spi_base, obj->spi.cs, obj->spi.transferrate);
kadonotakashi 0:8fdf9a60065b 251 spi_set_clock_phase(obj->spi.spi_base, SPI_CHIP_SEL, (mode & 0x01));
kadonotakashi 0:8fdf9a60065b 252 spi_set_clock_polarity(obj->spi.spi_base, SPI_CHIP_SEL, (mode & 0x02));
kadonotakashi 0:8fdf9a60065b 253
kadonotakashi 0:8fdf9a60065b 254 obj->spi.phase=(mode & 0x01);
kadonotakashi 0:8fdf9a60065b 255 obj->spi.polarity=(mode & 0x02);
kadonotakashi 0:8fdf9a60065b 256 spi_enable(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 257 }
kadonotakashi 0:8fdf9a60065b 258
kadonotakashi 0:8fdf9a60065b 259 /** Set the SPI baud rate
kadonotakashi 0:8fdf9a60065b 260 *
kadonotakashi 0:8fdf9a60065b 261 * Actual frequency may differ from the desired frequency due to available dividers and bus clock
kadonotakashi 0:8fdf9a60065b 262 * Configures the SPI peripheral's baud rate
kadonotakashi 0:8fdf9a60065b 263 * @param[in,out] obj The SPI object to configure
kadonotakashi 0:8fdf9a60065b 264 * @param[in] hz The baud rate in Hz
kadonotakashi 0:8fdf9a60065b 265 */
kadonotakashi 0:8fdf9a60065b 266
kadonotakashi 0:8fdf9a60065b 267 void spi_frequency(spi_t *obj, int hz)
kadonotakashi 0:8fdf9a60065b 268 {
kadonotakashi 0:8fdf9a60065b 269 spi_disable(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 270 int16_t baudrate_div=spi_calc_baudrate_div(hz, sysclk_get_cpu_hz());
kadonotakashi 0:8fdf9a60065b 271 spi_set_baudrate_div(obj->spi.spi_base,obj->spi.cs,(uint8_t)baudrate_div);
kadonotakashi 0:8fdf9a60065b 272 spi_enable(obj->spi.spi_base);
kadonotakashi 0:8fdf9a60065b 273 }
kadonotakashi 0:8fdf9a60065b 274
kadonotakashi 0:8fdf9a60065b 275 /**@}*/
kadonotakashi 0:8fdf9a60065b 276 /**
kadonotakashi 0:8fdf9a60065b 277 * \defgroup SynchSPI Synchronous SPI Hardware Abstraction Layer
kadonotakashi 0:8fdf9a60065b 278 * @{
kadonotakashi 0:8fdf9a60065b 279 */
kadonotakashi 0:8fdf9a60065b 280
kadonotakashi 0:8fdf9a60065b 281 /** Write a byte out in master mode and receive a value
kadonotakashi 0:8fdf9a60065b 282 *
kadonotakashi 0:8fdf9a60065b 283 * @param[in] obj The SPI peripheral to use for sending
kadonotakashi 0:8fdf9a60065b 284 * @param[in] value The value to send
kadonotakashi 0:8fdf9a60065b 285 * @return Returns the value received during send
kadonotakashi 0:8fdf9a60065b 286 */
kadonotakashi 0:8fdf9a60065b 287 int spi_master_write(spi_t *obj, int value)
kadonotakashi 0:8fdf9a60065b 288 {
kadonotakashi 0:8fdf9a60065b 289 spi_status_t status=spi_write(obj->spi.spi_base,(uint16_t)value,obj->spi.cs,SPI_LAST);
kadonotakashi 0:8fdf9a60065b 290 if(status ==SPI_OK) {
kadonotakashi 0:8fdf9a60065b 291 uint16_t data;
kadonotakashi 0:8fdf9a60065b 292 status =spi_read(obj->spi.spi_base,&data,&obj->spi.cs);
kadonotakashi 0:8fdf9a60065b 293 if(status == SPI_OK)
kadonotakashi 0:8fdf9a60065b 294 return data;
kadonotakashi 0:8fdf9a60065b 295 }
kadonotakashi 0:8fdf9a60065b 296 return 0;
kadonotakashi 0:8fdf9a60065b 297 }
kadonotakashi 0:8fdf9a60065b 298
kadonotakashi 0:8fdf9a60065b 299 int spi_master_block_write(spi_t *obj, const char *tx_buffer, int tx_length,
kadonotakashi 0:8fdf9a60065b 300 char *rx_buffer, int rx_length, char _write_fill) {
kadonotakashi 0:8fdf9a60065b 301 int total = (tx_length > rx_length) ? tx_length : rx_length;
kadonotakashi 0:8fdf9a60065b 302
kadonotakashi 0:8fdf9a60065b 303 for (int i = 0; i < total; i++) {
kadonotakashi 0:8fdf9a60065b 304 char out = (i < tx_length) ? tx_buffer[i] : _write_fill;
kadonotakashi 0:8fdf9a60065b 305 char in = spi_master_write(obj, out);
kadonotakashi 0:8fdf9a60065b 306 if (i < rx_length) {
kadonotakashi 0:8fdf9a60065b 307 rx_buffer[i] = in;
kadonotakashi 0:8fdf9a60065b 308 }
kadonotakashi 0:8fdf9a60065b 309 }
kadonotakashi 0:8fdf9a60065b 310
kadonotakashi 0:8fdf9a60065b 311 return total;
kadonotakashi 0:8fdf9a60065b 312 }
kadonotakashi 0:8fdf9a60065b 313
kadonotakashi 0:8fdf9a60065b 314 /** Check if a value is available to read
kadonotakashi 0:8fdf9a60065b 315 *
kadonotakashi 0:8fdf9a60065b 316 * @param[in] obj The SPI peripheral to check
kadonotakashi 0:8fdf9a60065b 317 * @return non-zero if a value is available
kadonotakashi 0:8fdf9a60065b 318 */
kadonotakashi 0:8fdf9a60065b 319 int spi_slave_receive(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 320 {
kadonotakashi 0:8fdf9a60065b 321 if(obj->spi.spi_base->SPI_SR & SPI_SR_RDRF)
kadonotakashi 0:8fdf9a60065b 322 return 1;
kadonotakashi 0:8fdf9a60065b 323 return 0;
kadonotakashi 0:8fdf9a60065b 324 }
kadonotakashi 0:8fdf9a60065b 325
kadonotakashi 0:8fdf9a60065b 326 /** Get a received value out of the SPI receive buffer in slave mode
kadonotakashi 0:8fdf9a60065b 327 *
kadonotakashi 0:8fdf9a60065b 328 * Blocks until a value is available
kadonotakashi 0:8fdf9a60065b 329 * @param[in] obj The SPI peripheral to read
kadonotakashi 0:8fdf9a60065b 330 * @return The value received
kadonotakashi 0:8fdf9a60065b 331 */
kadonotakashi 0:8fdf9a60065b 332 int spi_slave_read(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 333 {
kadonotakashi 0:8fdf9a60065b 334 uint16_t data;
kadonotakashi 0:8fdf9a60065b 335 spi_status_t status =spi_read(obj->spi.spi_base, &data, &obj->spi.cs);
kadonotakashi 0:8fdf9a60065b 336 if(status == SPI_OK)
kadonotakashi 0:8fdf9a60065b 337 return data;
kadonotakashi 0:8fdf9a60065b 338 return 0;
kadonotakashi 0:8fdf9a60065b 339 }
kadonotakashi 0:8fdf9a60065b 340
kadonotakashi 0:8fdf9a60065b 341 /** Write a value to the SPI peripheral in slave mode
kadonotakashi 0:8fdf9a60065b 342 *
kadonotakashi 0:8fdf9a60065b 343 * Blocks until the SPI peripheral can be written to
kadonotakashi 0:8fdf9a60065b 344 * @param[in] obj The SPI peripheral to write
kadonotakashi 0:8fdf9a60065b 345 * @param[in] value The value to write
kadonotakashi 0:8fdf9a60065b 346 */
kadonotakashi 0:8fdf9a60065b 347 void spi_slave_write(spi_t *obj, int value)
kadonotakashi 0:8fdf9a60065b 348 {
kadonotakashi 0:8fdf9a60065b 349 spi_write(obj->spi.spi_base,(uint16_t)value,obj->spi.cs,SPI_LAST);
kadonotakashi 0:8fdf9a60065b 350 }
kadonotakashi 0:8fdf9a60065b 351
kadonotakashi 0:8fdf9a60065b 352 /** Checks if the specified SPI peripheral is in use
kadonotakashi 0:8fdf9a60065b 353 *
kadonotakashi 0:8fdf9a60065b 354 * @param[in] obj The SPI peripheral to check
kadonotakashi 0:8fdf9a60065b 355 * @return non-zero if the peripheral is currently transmitting
kadonotakashi 0:8fdf9a60065b 356 */
kadonotakashi 0:8fdf9a60065b 357 int spi_busy(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 358 {
kadonotakashi 0:8fdf9a60065b 359 if(obj->spi.spi_base->SPI_SR & SPI_SR_TDRE) //Transmit Data Register Empty
kadonotakashi 0:8fdf9a60065b 360 return 0;
kadonotakashi 0:8fdf9a60065b 361 return 1;
kadonotakashi 0:8fdf9a60065b 362 }
kadonotakashi 0:8fdf9a60065b 363
kadonotakashi 0:8fdf9a60065b 364 /** Get the module number
kadonotakashi 0:8fdf9a60065b 365 *
kadonotakashi 0:8fdf9a60065b 366 * @param[in] obj The SPI peripheral to check
kadonotakashi 0:8fdf9a60065b 367 * @return The module number
kadonotakashi 0:8fdf9a60065b 368 */
kadonotakashi 0:8fdf9a60065b 369 uint8_t spi_get_module(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 370 {
kadonotakashi 0:8fdf9a60065b 371 return obj->spi.module_number;
kadonotakashi 0:8fdf9a60065b 372 }
kadonotakashi 0:8fdf9a60065b 373
kadonotakashi 0:8fdf9a60065b 374
kadonotakashi 0:8fdf9a60065b 375 /**@}*/
kadonotakashi 0:8fdf9a60065b 376 #if DEVICE_SPI_ASYNCH
kadonotakashi 0:8fdf9a60065b 377 /**
kadonotakashi 0:8fdf9a60065b 378 * \defgroup AsynchSPI Asynchronous SPI Hardware Abstraction Layer
kadonotakashi 0:8fdf9a60065b 379 * @{
kadonotakashi 0:8fdf9a60065b 380 */
kadonotakashi 0:8fdf9a60065b 381
kadonotakashi 0:8fdf9a60065b 382 /** Begin the SPI transfer. Buffer pointers and lengths are specified in tx_buff and rx_buff
kadonotakashi 0:8fdf9a60065b 383 *
kadonotakashi 0:8fdf9a60065b 384 * @param[in] obj The SPI object which holds the transfer information
kadonotakashi 0:8fdf9a60065b 385 * @param[in] tx The buffer to send
kadonotakashi 0:8fdf9a60065b 386 * @param[in] tx_length The number of words to transmit
kadonotakashi 0:8fdf9a60065b 387 * @param[in] rx The buffer to receive
kadonotakashi 0:8fdf9a60065b 388 * @param[in] rx_length The number of words to receive
kadonotakashi 0:8fdf9a60065b 389 * @param[in] bit_width The bit width of buffer words
kadonotakashi 0:8fdf9a60065b 390 * @param[in] event The logical OR of events to be registered
kadonotakashi 0:8fdf9a60065b 391 * @param[in] handler SPI interrupt handler
kadonotakashi 0:8fdf9a60065b 392 * @param[in] hint A suggestion for how to use DMA with this transfer
kadonotakashi 0:8fdf9a60065b 393 */
kadonotakashi 0:8fdf9a60065b 394 #warning "Only DMA async supported by SPI master transfer"
kadonotakashi 0:8fdf9a60065b 395
kadonotakashi 0:8fdf9a60065b 396 void spi_master_transfer(spi_t *obj, const void *tx, size_t tx_length, void *rx, size_t rx_length, uint8_t bit_width, uint32_t handler, uint32_t event, DMAUsage hint)
kadonotakashi 0:8fdf9a60065b 397 {
kadonotakashi 0:8fdf9a60065b 398 uint32_t pdcenable=0;
kadonotakashi 0:8fdf9a60065b 399
kadonotakashi 0:8fdf9a60065b 400 if(bit_width) {
kadonotakashi 0:8fdf9a60065b 401 uint32_t transferrate= get_transfer_rate(bit_width);
kadonotakashi 0:8fdf9a60065b 402 spi_set_bits_per_transfer(obj->spi.spi_base, obj->spi.cs, transferrate);
kadonotakashi 0:8fdf9a60065b 403 }
kadonotakashi 0:8fdf9a60065b 404
kadonotakashi 0:8fdf9a60065b 405 if(tx) {
kadonotakashi 0:8fdf9a60065b 406 pdc_packet_t pdc_packet_tx;
kadonotakashi 0:8fdf9a60065b 407 pdc_packet_tx.ul_addr=(uint32_t)tx;
kadonotakashi 0:8fdf9a60065b 408 pdc_packet_tx.ul_size=tx_length;
kadonotakashi 0:8fdf9a60065b 409
kadonotakashi 0:8fdf9a60065b 410 pdcenable|=PERIPH_PTCR_TXTEN;
kadonotakashi 0:8fdf9a60065b 411 /* Configure PDC for data send */
kadonotakashi 0:8fdf9a60065b 412 pdc_tx_init(obj->spi.pdc, &pdc_packet_tx, NULL);
kadonotakashi 0:8fdf9a60065b 413 }
kadonotakashi 0:8fdf9a60065b 414
kadonotakashi 0:8fdf9a60065b 415 if(rx) {
kadonotakashi 0:8fdf9a60065b 416 pdc_rx_clear_cnt(obj->spi.pdc);
kadonotakashi 0:8fdf9a60065b 417 pdc_packet_t pdc_packet_rx;
kadonotakashi 0:8fdf9a60065b 418 pdc_packet_rx.ul_addr=(uint32_t)rx;
kadonotakashi 0:8fdf9a60065b 419 pdc_packet_rx.ul_size=rx_length;
kadonotakashi 0:8fdf9a60065b 420 pdcenable|=PERIPH_PTCR_RXTEN;
kadonotakashi 0:8fdf9a60065b 421 char *rxbuffer=(char *)rx;
kadonotakashi 0:8fdf9a60065b 422 for(uint8_t index=0; index<rx_length; index++, rxbuffer++)
kadonotakashi 0:8fdf9a60065b 423 *rxbuffer=SPI_FILL_WORD;
kadonotakashi 0:8fdf9a60065b 424
kadonotakashi 0:8fdf9a60065b 425 /* Configure PDC for data receive */
kadonotakashi 0:8fdf9a60065b 426 pdc_rx_init(obj->spi.pdc, &pdc_packet_rx, NULL);
kadonotakashi 0:8fdf9a60065b 427 }
kadonotakashi 0:8fdf9a60065b 428
kadonotakashi 0:8fdf9a60065b 429 obj->spi.dma_usage=hint;
kadonotakashi 0:8fdf9a60065b 430 obj->spi.event=event;
kadonotakashi 0:8fdf9a60065b 431
kadonotakashi 0:8fdf9a60065b 432 NVIC_ClearPendingIRQ(obj->spi.irq_type);
kadonotakashi 0:8fdf9a60065b 433 NVIC_DisableIRQ(obj->spi.irq_type);
kadonotakashi 0:8fdf9a60065b 434 NVIC_SetVector(obj->spi.irq_type,handler);
kadonotakashi 0:8fdf9a60065b 435 NVIC_EnableIRQ(obj->spi.irq_type);
kadonotakashi 0:8fdf9a60065b 436
kadonotakashi 0:8fdf9a60065b 437 /* Enable SPI IRQ */
kadonotakashi 0:8fdf9a60065b 438 spi_enable_interrupt(obj->spi.spi_base, SPI_IER_RXBUFF| SPI_IER_TXBUFE | SPI_IER_MODF | SPI_IER_OVRES);
kadonotakashi 0:8fdf9a60065b 439
kadonotakashi 0:8fdf9a60065b 440 /* Enable PDC transfers */
kadonotakashi 0:8fdf9a60065b 441 pdc_enable_transfer(obj->spi.pdc, pdcenable );
kadonotakashi 0:8fdf9a60065b 442
kadonotakashi 0:8fdf9a60065b 443 }
kadonotakashi 0:8fdf9a60065b 444
kadonotakashi 0:8fdf9a60065b 445 /** The asynchronous IRQ handler
kadonotakashi 0:8fdf9a60065b 446 *
kadonotakashi 0:8fdf9a60065b 447 * Reads the received values out of the RX FIFO, writes values into the TX FIFO and checks for transfer termination
kadonotakashi 0:8fdf9a60065b 448 * conditions, such as buffer overflows or transfer complete.
kadonotakashi 0:8fdf9a60065b 449 * @param[in] obj The SPI object which holds the transfer information
kadonotakashi 0:8fdf9a60065b 450 * @return event flags if a transfer termination condition was met or 0 otherwise.
kadonotakashi 0:8fdf9a60065b 451 */
kadonotakashi 0:8fdf9a60065b 452 uint32_t spi_irq_handler_asynch(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 453 {
kadonotakashi 0:8fdf9a60065b 454 uint32_t event=0;
kadonotakashi 0:8fdf9a60065b 455
kadonotakashi 0:8fdf9a60065b 456 // Data transferred via DMA
kadonotakashi 0:8fdf9a60065b 457 if((obj->spi.spi_base->SPI_SR & SPI_IER_TXBUFE)) {
kadonotakashi 0:8fdf9a60065b 458 spi_disable_interrupt(obj->spi.spi_base, SPI_IDR_TXBUFE | SPI_IDR_MODF | SPI_IDR_OVRES);
kadonotakashi 0:8fdf9a60065b 459 if(obj->spi.event | SPI_EVENT_COMPLETE)
kadonotakashi 0:8fdf9a60065b 460 event |=SPI_EVENT_COMPLETE;
kadonotakashi 0:8fdf9a60065b 461 }
kadonotakashi 0:8fdf9a60065b 462
kadonotakashi 0:8fdf9a60065b 463 if((obj->spi.spi_base->SPI_SR & SPI_IER_RXBUFF)) {
kadonotakashi 0:8fdf9a60065b 464 spi_disable_interrupt(obj->spi.spi_base, SPI_IDR_RXBUFF | SPI_IDR_MODF | SPI_IDR_OVRES);
kadonotakashi 0:8fdf9a60065b 465 if(obj->spi.event | SPI_EVENT_COMPLETE)
kadonotakashi 0:8fdf9a60065b 466 event |=SPI_EVENT_COMPLETE;
kadonotakashi 0:8fdf9a60065b 467 }
kadonotakashi 0:8fdf9a60065b 468
kadonotakashi 0:8fdf9a60065b 469 if(obj->spi.spi_base->SPI_SR & SPI_SR_MODF) {
kadonotakashi 0:8fdf9a60065b 470 if(obj->spi.event | SPI_EVENT_ERROR)
kadonotakashi 0:8fdf9a60065b 471 event |=SPI_EVENT_ERROR;
kadonotakashi 0:8fdf9a60065b 472 }
kadonotakashi 0:8fdf9a60065b 473
kadonotakashi 0:8fdf9a60065b 474 if(obj->spi.spi_base->SPI_SR & SPI_SR_OVRES) {
kadonotakashi 0:8fdf9a60065b 475 if(obj->spi.event | SPI_EVENT_RX_OVERFLOW)
kadonotakashi 0:8fdf9a60065b 476 event |=SPI_EVENT_RX_OVERFLOW;
kadonotakashi 0:8fdf9a60065b 477 }
kadonotakashi 0:8fdf9a60065b 478
kadonotakashi 0:8fdf9a60065b 479 return event;
kadonotakashi 0:8fdf9a60065b 480 }
kadonotakashi 0:8fdf9a60065b 481
kadonotakashi 0:8fdf9a60065b 482 /** Attempts to determine if the SPI peripheral is already in use.
kadonotakashi 0:8fdf9a60065b 483 *
kadonotakashi 0:8fdf9a60065b 484 * If a temporary DMA channel has been allocated, peripheral is in use.
kadonotakashi 0:8fdf9a60065b 485 * If a permanent DMA channel has been allocated, check if the DMA channel is in use. If not, proceed as though no DMA
kadonotakashi 0:8fdf9a60065b 486 * channel were allocated.
kadonotakashi 0:8fdf9a60065b 487 * If no DMA channel is allocated, check whether tx and rx buffers have been assigned. For each assigned buffer, check
kadonotakashi 0:8fdf9a60065b 488 * if the corresponding buffer position is less than the buffer length. If buffers do not indicate activity, check if
kadonotakashi 0:8fdf9a60065b 489 * there are any bytes in the FIFOs.
kadonotakashi 0:8fdf9a60065b 490 * @param[in] obj The SPI object to check for activity
kadonotakashi 0:8fdf9a60065b 491 * @return non-zero if the SPI port is active or zero if it is not.
kadonotakashi 0:8fdf9a60065b 492 */
kadonotakashi 0:8fdf9a60065b 493
kadonotakashi 0:8fdf9a60065b 494 uint8_t spi_active(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 495 {
kadonotakashi 0:8fdf9a60065b 496 if(obj->spi.spi_base->SPI_SR & SPI_SR_ENDTX && obj->spi.spi_base->SPI_SR & SPI_SR_ENDRX)
kadonotakashi 0:8fdf9a60065b 497 return 0;
kadonotakashi 0:8fdf9a60065b 498 return 1;
kadonotakashi 0:8fdf9a60065b 499 }
kadonotakashi 0:8fdf9a60065b 500
kadonotakashi 0:8fdf9a60065b 501 /** Abort an SPI transfer
kadonotakashi 0:8fdf9a60065b 502 *
kadonotakashi 0:8fdf9a60065b 503 * @param obj The SPI peripheral to stop
kadonotakashi 0:8fdf9a60065b 504 */
kadonotakashi 0:8fdf9a60065b 505 void spi_abort_asynch(spi_t *obj)
kadonotakashi 0:8fdf9a60065b 506 {
kadonotakashi 0:8fdf9a60065b 507 /* Disable PDC transfers */
kadonotakashi 0:8fdf9a60065b 508 pdc_disable_transfer(obj->spi.pdc, PERIPH_PTCR_RXTDIS | PERIPH_PTCR_TXTDIS);
kadonotakashi 0:8fdf9a60065b 509
kadonotakashi 0:8fdf9a60065b 510 /* Clear PDC buffer receive counter */
kadonotakashi 0:8fdf9a60065b 511 pdc_rx_clear_cnt(obj->spi.pdc);
kadonotakashi 0:8fdf9a60065b 512
kadonotakashi 0:8fdf9a60065b 513 /* Disable SPI IRQ */
kadonotakashi 0:8fdf9a60065b 514 spi_disable_interrupt(obj->spi.spi_base, SPI_IDR_TXBUFE);
kadonotakashi 0:8fdf9a60065b 515 spi_disable_interrupt(obj->spi.spi_base, SPI_IDR_RXBUFF);
kadonotakashi 0:8fdf9a60065b 516
kadonotakashi 0:8fdf9a60065b 517 /* Disable SPI interrupt */
kadonotakashi 0:8fdf9a60065b 518 NVIC_DisableIRQ(obj->spi.irq_type);
kadonotakashi 0:8fdf9a60065b 519 }
kadonotakashi 0:8fdf9a60065b 520
kadonotakashi 0:8fdf9a60065b 521 #endif