Nut/OS  4.10.3
API Reference
sbbif0.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2007 by egnite Software GmbH. All rights reserved.
00003  *
00004  * Redistribution and use in source and binary forms, with or without
00005  * modification, are permitted provided that the following conditions
00006  * are met:
00007  *
00008  * 1. Redistributions of source code must retain the above copyright
00009  *    notice, this list of conditions and the following disclaimer.
00010  * 2. Redistributions in binary form must reproduce the above copyright
00011  *    notice, this list of conditions and the following disclaimer in the
00012  *    documentation and/or other materials provided with the distribution.
00013  * 3. Neither the name of the copyright holders nor the names of
00014  *    contributors may be used to endorse or promote products derived
00015  *    from this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY EGNITE SOFTWARE GMBH AND CONTRIBUTORS
00018  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00019  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00020  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL EGNITE
00021  * SOFTWARE GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00022  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00023  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00024  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00025  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00026  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00027  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00028  * SUCH DAMAGE.
00029  *
00030  * For additional information see http://www.ethernut.de/
00031  *
00032  */
00033 
00034 /*
00035  * $Log$
00036  * Revision 1.4  2009/01/18 16:46:47  haraldkipp
00037  * GPIO header file changed.
00038  *
00039  * Revision 1.3  2008/10/23 08:54:07  haraldkipp
00040  * Include the correct header file.
00041  *
00042  * Revision 1.2  2008/08/11 06:59:42  haraldkipp
00043  * BSD types replaced by stdint types (feature request #1282721).
00044  *
00045  * Revision 1.1  2007/04/12 09:07:54  haraldkipp
00046  * Configurable SPI added.
00047  *
00048  */
00049 
00050 #include <sys/timer.h>
00051 
00052 #include <dev/gpio.h>
00053 #include <dev/sbbif0.h>
00054 
00055 /* SPI modes of all devices. */
00056 static ureg_t sbbi0_mode[SBBI0_MAX_DEVICES];
00057 
00058 /* SPI mode of the currently selected device. */
00059 static ureg_t sel_mode;
00060 
00061 /* SPI bit delay of all devices. */
00062 static ureg_t sbbi0_delay[SBBI0_MAX_DEVICES];
00063 
00064 /* SPI bit delay of the currently selected device. */
00065 static ureg_t sel_delay;
00066 
00084 int Sbbi0SetMode(ureg_t ix, ureg_t mode)
00085 {
00086     if (ix < SBBI0_MAX_DEVICES && mode <= 3) {
00087         sbbi0_mode[ix] = mode;
00088         return 0;
00089     }
00090     return -1;
00091 }
00092 
00102 void Sbbi0SetSpeed(ureg_t ix, uint32_t rate)
00103 {
00104     uint32_t fosc = NutGetCpuClock() / 16;
00105 
00106     if (rate) {
00107         fosc /= rate;
00108     }
00109     if (fosc < 5) {
00110         sbbi0_delay[ix] = 0;
00111     }
00112     else if (fosc < 255) {
00113         sbbi0_delay[ix] = (ureg_t)fosc;
00114     } else {
00115         sbbi0_delay[ix] = 255;
00116     }
00117 }
00118 
00119 static INLINE void Sbbi0Delay(void)
00120 {
00121     if (sel_delay) {
00122         ureg_t d;
00123 
00124         for (d = sel_delay; d; d--) {
00125             _NOP();
00126         }
00127     }
00128 }
00129 
00138 void Sbbi0Enable(ureg_t ix)
00139 {
00140     sel_mode = sbbi0_mode[ix];
00141     sel_delay = sbbi0_delay[ix];
00142 
00143     SBBI0_MOSI_CLR();
00144     SBBI0_MOSI_ENA();
00145     SBBI0_MISO_ENA();
00146     if (sel_mode == 0 || sel_mode == 1) {
00147         SBBI0_SCK_CLR();
00148     }
00149     else {
00150         SBBI0_SCK_SET();
00151     }
00152     SBBI0_SCK_ENA();
00153 }
00154 
00165 void Sbbi0ChipReset(ureg_t ix, ureg_t hi)
00166 {
00167 #if defined(SBBI0_RST0_BIT)
00168     if (ix == 0) {
00169         if (hi) {
00170             SBBI0_RST0_SET();
00171         } else {
00172             SBBI0_RST0_CLR();
00173         }
00174         SBBI0_RST0_ENA();
00175     }
00176 #endif
00177 #if defined(SBBI0_RST1_BIT)
00178     if (ix == 1) {
00179         if (hi) {
00180             SBBI0_RST1_SET();
00181         } else {
00182             SBBI0_RST1_CLR();
00183         }
00184         SBBI0_RST1_ENA();
00185     }
00186 #endif
00187 #if defined(SBBI0_RST2_BIT)
00188     if (ix == 2) {
00189         if (hi) {
00190             SBBI0_RST2_SET();
00191         } else {
00192             SBBI0_RST2_CLR();
00193         }
00194         SBBI0_RST2_ENA();
00195     }
00196 #endif
00197 #if defined(SBBI0_RST3_BIT)
00198     if (ix == 3) {
00199         if (hi) {
00200             SBBI0_RST3_SET();
00201         } else {
00202             SBBI0_RST3_CLR();
00203         }
00204         SBBI0_RST3_ENA();
00205     }
00206 #endif
00207 }
00208 
00220 void Sbbi0ChipSelect(ureg_t ix, ureg_t hi)
00221 {
00222 #if defined(SBBI0_CS0_BIT)
00223     if (ix == 0) {
00224         if (hi) {
00225             SBBI0_CS0_SET();
00226         } else {
00227             SBBI0_CS0_CLR();
00228         }
00229         SBBI0_CS0_ENA();
00230     }
00231 #endif
00232 #if defined(SBBI0_CS1_BIT)
00233     if (ix == 1) {
00234         if (hi) {
00235             SBBI0_CS1_SET();
00236         } else {
00237             SBBI0_CS1_CLR();
00238         }
00239         SBBI0_CS1_ENA();
00240     }
00241 #endif
00242 #if defined(SBBI0_CS2_BIT)
00243     if (ix == 2) {
00244         if (hi) {
00245             SBBI0_CS2_SET();
00246         } else {
00247             SBBI0_CS2_CLR();
00248         }
00249         SBBI0_CS2_ENA();
00250     }
00251 #endif
00252 #if defined(SBBI0_CS3_BIT)
00253     if (ix == 3) {
00254         if (hi) {
00255             SBBI0_CS3_SET();
00256         } else {
00257             SBBI0_CS3_CLR();
00258         }
00259         SBBI0_CS3_ENA();
00260     }
00261 #endif
00262 }
00263 
00275 void Sbbi0SelectDevice(ureg_t ix)
00276 {
00277     Sbbi0Enable(ix);
00278     Sbbi0ChipSelect(ix, 1);
00279 }
00280 
00289 void Sbbi0DeselectDevice(ureg_t ix)
00290 {
00291     Sbbi0ChipSelect(ix, 0);
00292 }
00293 
00305 void Sbbi0NegSelectDevice(ureg_t ix)
00306 {
00307     Sbbi0Enable(ix);
00308     Sbbi0ChipSelect(ix, 0);
00309 }
00310 
00319 void Sbbi0NegDeselectDevice(ureg_t ix)
00320 {
00321     Sbbi0ChipSelect(ix, 1);
00322 }
00323 
00331 uint8_t Sbbi0Byte(uint8_t data)
00332 {
00333     ureg_t mask;
00334 
00335     if (sel_mode == 3) {
00336         /* Mode 3: Leading edge is falling, data sampled on rising edge. */
00337         for (mask = 0x80; mask; mask >>= 1) {
00338             SBBI0_SCK_CLR();
00339             if (data & mask) {
00340                 SBBI0_MOSI_SET();
00341             } else {
00342                 SBBI0_MOSI_CLR();
00343             }
00344             Sbbi0Delay();
00345             SBBI0_SCK_SET();
00346             if (SBBI0_MISO_TST()) {
00347                 data |= mask;
00348             }
00349             else {
00350                 data &= ~mask;
00351             }
00352             Sbbi0Delay();
00353         }
00354     }
00355     else if (sel_mode == 2) {
00356         /* Mode 2: Leading edge is falling, data sampled on falling edge. */
00357         for (mask = 0x80; mask; mask >>= 1) {
00358             SBBI0_SCK_SET();
00359             if (data & mask) {
00360                 SBBI0_MOSI_SET();
00361             } else {
00362                 SBBI0_MOSI_CLR();
00363             }
00364             Sbbi0Delay();
00365             SBBI0_SCK_CLR();
00366             if (SBBI0_MISO_TST()) {
00367                 data |= mask;
00368             }
00369             else {
00370                 data &= ~mask;
00371             }
00372             Sbbi0Delay();
00373         }
00374         SBBI0_SCK_SET();
00375     }
00376     else if (sel_mode == 1) {
00377         /* Mode 1: Leading edge is rising, data sampled on falling edge. */
00378         for (mask = 0x80; mask; mask >>= 1) {
00379             SBBI0_SCK_SET();
00380             if (data & mask) {
00381                 SBBI0_MOSI_SET();
00382             } else {
00383                 SBBI0_MOSI_CLR();
00384             }
00385             Sbbi0Delay();
00386             SBBI0_SCK_CLR();
00387             if (SBBI0_MISO_TST()) {
00388                 data |= mask;
00389             }
00390             else {
00391                 data &= ~mask;
00392             }
00393             Sbbi0Delay();
00394         }
00395     }
00396     else {
00397         /* Mode 0: Leading edge is rising, data sampled on rising edge. */
00398         for (mask = 0x80; mask; mask >>= 1) {
00399             SBBI0_SCK_CLR();
00400             if (data & mask) {
00401                 SBBI0_MOSI_SET();
00402             } else {
00403                 SBBI0_MOSI_CLR();
00404             }
00405             Sbbi0Delay();
00406             SBBI0_SCK_SET();
00407             if (SBBI0_MISO_TST()) {
00408                 data |= mask;
00409             }
00410             else {
00411                 data &= ~mask;
00412             }
00413             Sbbi0Delay();
00414         }
00415         SBBI0_SCK_CLR();
00416     }
00417     return data;
00418 }
00419 
00436 void Sbbi0Transact(CONST void *wdata, void *rdata, size_t len)
00437 {
00438     CONST uint8_t *wp = (CONST uint8_t *)wdata;
00439 
00440     if (rdata) {
00441         uint8_t *rp = (uint8_t *)rdata;
00442 
00443         while(len--) {
00444             *rp++ = Sbbi0Byte(*wp);
00445             wp++;
00446         }
00447     } else {
00448         while(len--) {
00449             Sbbi0Byte(*wp);
00450             wp++;
00451         }
00452     }
00453 }
00454