]> git.gir.st - tmk_keyboard.git/blob - tool/mbed/mbed-sdk/libraries/mbed/targets/hal/TARGET_Freescale/TARGET_KLXX/TARGET_KL05Z/spi_api.c
Squashed 'tmk_core/' changes from 7967731..b9e0ea0
[tmk_keyboard.git] / tool / mbed / mbed-sdk / libraries / mbed / targets / hal / TARGET_Freescale / TARGET_KLXX / TARGET_KL05Z / spi_api.c
1 /* mbed Microcontroller Library
2 * Copyright (c) 2006-2013 ARM Limited
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16 #include "spi_api.h"
17
18 #include <math.h>
19
20 #include "cmsis.h"
21 #include "pinmap.h"
22
23 static const PinMap PinMap_SPI_SCLK[] = {
24 {PTB0, SPI_0, 3},
25 {NC , NC , 0}
26 };
27
28 static const PinMap PinMap_SPI_MOSI[] = {
29 {PTA7, SPI_0, 3},
30 {NC , NC , 0}
31 };
32
33 static const PinMap PinMap_SPI_MISO[] = {
34 {PTA6, SPI_0, 3},
35 {NC , NC , 0}
36 };
37
38 static const PinMap PinMap_SPI_SSEL[] = {
39 {PTA5, SPI_0, 3},
40 {NC , NC , 0}
41 };
42
43 void spi_init(spi_t *obj, PinName mosi, PinName miso, PinName sclk, PinName ssel) {
44 // determine the SPI to use
45 SPIName spi_mosi = (SPIName)pinmap_peripheral(mosi, PinMap_SPI_MOSI);
46 SPIName spi_miso = (SPIName)pinmap_peripheral(miso, PinMap_SPI_MISO);
47 SPIName spi_sclk = (SPIName)pinmap_peripheral(sclk, PinMap_SPI_SCLK);
48 SPIName spi_ssel = (SPIName)pinmap_peripheral(ssel, PinMap_SPI_SSEL);
49 SPIName spi_data = (SPIName)pinmap_merge(spi_mosi, spi_miso);
50 SPIName spi_cntl = (SPIName)pinmap_merge(spi_sclk, spi_ssel);
51
52 obj->spi = (SPI_Type*)pinmap_merge(spi_data, spi_cntl);
53 MBED_ASSERT((int)obj->spi != NC);
54
55 // enable power and clocking
56 switch ((int)obj->spi) {
57 case SPI_0:
58 SIM->SCGC5 |= (SIM_SCGC5_PORTA_MASK | SIM_SCGC5_PORTB_MASK);
59 SIM->SCGC4 |= SIM_SCGC4_SPI0_MASK;
60 break;
61 }
62
63 // set default format and frequency
64 if (ssel == NC) {
65 spi_format(obj, 8, 0, 0); // 8 bits, mode 0, master
66 } else {
67 spi_format(obj, 8, 0, 1); // 8 bits, mode 0, slave
68 }
69 spi_frequency(obj, 1000000);
70
71 // enable SPI
72 obj->spi->C1 |= SPI_C1_SPE_MASK;
73
74 // pin out the spi pins
75 pinmap_pinout(mosi, PinMap_SPI_MOSI);
76 pinmap_pinout(miso, PinMap_SPI_MISO);
77 pinmap_pinout(sclk, PinMap_SPI_SCLK);
78 if (ssel != NC) {
79 pinmap_pinout(ssel, PinMap_SPI_SSEL);
80 }
81 }
82
83 void spi_free(spi_t *obj) {
84 // [TODO]
85 }
86 void spi_format(spi_t *obj, int bits, int mode, int slave) {
87 MBED_ASSERT(bits == 8);
88 MBED_ASSERT((mode >= 0) && (mode <= 3));
89
90 uint8_t polarity = (mode & 0x2) ? 1 : 0;
91 uint8_t phase = (mode & 0x1) ? 1 : 0;
92 uint8_t c1_data = ((!slave) << 4) | (polarity << 3) | (phase << 2);
93
94 // clear MSTR, CPOL and CPHA bits
95 obj->spi->C1 &= ~(0x7 << 2);
96
97 // write new value
98 obj->spi->C1 |= c1_data;
99 }
100
101 void spi_frequency(spi_t *obj, int hz) {
102 uint32_t error = 0;
103 uint32_t p_error = 0xffffffff;
104 uint32_t ref = 0;
105 uint8_t spr = 0;
106 uint8_t ref_spr = 0;
107 uint8_t ref_prescaler = 0;
108
109 // bus clk
110 uint32_t PCLK = SystemCoreClock / (((SIM->CLKDIV1 & SIM_CLKDIV1_OUTDIV4_MASK) >> SIM_CLKDIV1_OUTDIV4_SHIFT) + 1);
111 uint8_t prescaler = 1;
112 uint8_t divisor = 2;
113
114 for (prescaler = 1; prescaler <= 8; prescaler++) {
115 divisor = 2;
116 for (spr = 0; spr <= 8; spr++) {
117 ref = PCLK / (prescaler*divisor);
118 if (ref > (uint32_t)hz)
119 continue;
120 error = hz - ref;
121 if (error < p_error) {
122 ref_spr = spr;
123 ref_prescaler = prescaler - 1;
124 p_error = error;
125 }
126 divisor *= 2;
127 }
128 }
129
130 // set SPPR and SPR
131 obj->spi->BR = ((ref_prescaler & 0x7) << 4) | (ref_spr & 0xf);
132 }
133
134 static inline int spi_writeable(spi_t * obj) {
135 return (obj->spi->S & SPI_S_SPTEF_MASK) ? 1 : 0;
136 }
137
138 static inline int spi_readable(spi_t * obj) {
139 return (obj->spi->S & SPI_S_SPRF_MASK) ? 1 : 0;
140 }
141
142 int spi_master_write(spi_t *obj, int value) {
143 // wait tx buffer empty
144 while(!spi_writeable(obj));
145 obj->spi->D = (value & 0xff);
146
147 // wait rx buffer full
148 while (!spi_readable(obj));
149 return obj->spi->D & 0xff;
150 }
151
152 int spi_slave_receive(spi_t *obj) {
153 return spi_readable(obj);
154 }
155
156 int spi_slave_read(spi_t *obj) {
157 return obj->spi->D;
158 }
159
160 void spi_slave_write(spi_t *obj, int value) {
161 while (!spi_writeable(obj));
162 obj->spi->D = value;
163 }
Imprint / Impressum