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: sbbif0.c,v $
00036  * Revision 1.3  2008/10/23 08:54:07  haraldkipp
00037  * Include the correct header file.
00038  *
00039  * Revision 1.2  2008/08/11 06:59:42  haraldkipp
00040  * BSD types replaced by stdint types (feature request #1282721).
00041  *
00042  * Revision 1.1  2007/04/12 09:07:54  haraldkipp
00043  * Configurable SPI added.
00044  *
00045  */
00046 
00047 #include <sys/timer.h>
00048 
00049 #include <cfg/arch/gpio.h>
00050 #include <dev/sbbif0.h>
00051 
00052 /* SPI modes of all devices. */
00053 static ureg_t sbbi0_mode[SBBI0_MAX_DEVICES];
00054 
00055 /* SPI mode of the currently selected device. */
00056 static ureg_t sel_mode;
00057 
00058 /* SPI bit delay of all devices. */
00059 static ureg_t sbbi0_delay[SBBI0_MAX_DEVICES];
00060 
00061 /* SPI bit delay of the currently selected device. */
00062 static ureg_t sel_delay;
00063 
00081 int Sbbi0SetMode(ureg_t ix, ureg_t mode)
00082 {
00083     if (ix < SBBI0_MAX_DEVICES && mode <= 3) {
00084         sbbi0_mode[ix] = mode;
00085         return 0;
00086     }
00087     return -1;
00088 }
00089 
00099 void Sbbi0SetSpeed(ureg_t ix, uint32_t rate)
00100 {
00101     uint32_t fosc = NutGetCpuClock() / 16;
00102 
00103     if (rate) {
00104         fosc /= rate;
00105     }
00106     if (fosc < 5) {
00107         sbbi0_delay[ix] = 0;
00108     }
00109     else if (fosc < 255) {
00110         sbbi0_delay[ix] = (ureg_t)fosc;
00111     } else {
00112         sbbi0_delay[ix] = 255;
00113     }
00114 }
00115 
00116 static INLINE void Sbbi0Delay(void)
00117 {
00118     if (sel_delay) {
00119         ureg_t d;
00120 
00121         for (d = sel_delay; d; d--) {
00122             _NOP();
00123         }
00124     }
00125 }
00126 
00135 void Sbbi0Enable(ureg_t ix)
00136 {
00137     sel_mode = sbbi0_mode[ix];
00138     sel_delay = sbbi0_delay[ix];
00139 
00140     SBBI0_MOSI_CLR();
00141     SBBI0_MOSI_ENA();
00142     SBBI0_MISO_ENA();
00143     if (sel_mode == 0 || sel_mode == 1) {
00144         SBBI0_SCK_CLR();
00145     }
00146     else {
00147         SBBI0_SCK_SET();
00148     }
00149     SBBI0_SCK_ENA();
00150 }
00151 
00162 void Sbbi0ChipReset(ureg_t ix, ureg_t hi)
00163 {
00164 #if defined(SBBI0_RST0_BIT)
00165     if (ix == 0) {
00166         if (hi) {
00167             SBBI0_RST0_SET();
00168         } else {
00169             SBBI0_RST0_CLR();
00170         }
00171         SBBI0_RST0_ENA();
00172     }
00173 #endif
00174 #if defined(SBBI0_RST1_BIT)
00175     if (ix == 1) {
00176         if (hi) {
00177             SBBI0_RST1_SET();
00178         } else {
00179             SBBI0_RST1_CLR();
00180         }
00181         SBBI0_RST1_ENA();
00182     }
00183 #endif
00184 #if defined(SBBI0_RST2_BIT)
00185     if (ix == 2) {
00186         if (hi) {
00187             SBBI0_RST2_SET();
00188         } else {
00189             SBBI0_RST2_CLR();
00190         }
00191         SBBI0_RST2_ENA();
00192     }
00193 #endif
00194 #if defined(SBBI0_RST3_BIT)
00195     if (ix == 3) {
00196         if (hi) {
00197             SBBI0_RST3_SET();
00198         } else {
00199             SBBI0_RST3_CLR();
00200         }
00201         SBBI0_RST3_ENA();
00202     }
00203 #endif
00204 }
00205 
00217 void Sbbi0ChipSelect(ureg_t ix, ureg_t hi)
00218 {
00219 #if defined(SBBI0_CS0_BIT)
00220     if (ix == 0) {
00221         if (hi) {
00222             SBBI0_CS0_SET();
00223         } else {
00224             SBBI0_CS0_CLR();
00225         }
00226         SBBI0_CS0_ENA();
00227     }
00228 #endif
00229 #if defined(SBBI0_CS1_BIT)
00230     if (ix == 1) {
00231         if (hi) {
00232             SBBI0_CS1_SET();
00233         } else {
00234             SBBI0_CS1_CLR();
00235         }
00236         SBBI0_CS1_ENA();
00237     }
00238 #endif
00239 #if defined(SBBI0_CS2_BIT)
00240     if (ix == 2) {
00241         if (hi) {
00242             SBBI0_CS2_SET();
00243         } else {
00244             SBBI0_CS2_CLR();
00245         }
00246         SBBI0_CS2_ENA();
00247     }
00248 #endif
00249 #if defined(SBBI0_CS3_BIT)
00250     if (ix == 3) {
00251         if (hi) {
00252             SBBI0_CS3_SET();
00253         } else {
00254             SBBI0_CS3_CLR();
00255         }
00256         SBBI0_CS3_ENA();
00257     }
00258 #endif
00259 }
00260 
00272 void Sbbi0SelectDevice(ureg_t ix)
00273 {
00274     Sbbi0Enable(ix);
00275     Sbbi0ChipSelect(ix, 1);
00276 }
00277 
00286 void Sbbi0DeselectDevice(ureg_t ix)
00287 {
00288     Sbbi0ChipSelect(ix, 0);
00289 }
00290 
00302 void Sbbi0NegSelectDevice(ureg_t ix)
00303 {
00304     Sbbi0Enable(ix);
00305     Sbbi0ChipSelect(ix, 0);
00306 }
00307 
00316 void Sbbi0NegDeselectDevice(ureg_t ix)
00317 {
00318     Sbbi0ChipSelect(ix, 1);
00319 }
00320 
00328 uint8_t Sbbi0Byte(uint8_t data)
00329 {
00330     ureg_t mask;
00331 
00332     if (sel_mode == 3) {
00333         /* Mode 3: Leading edge is falling, data sampled on rising edge. */
00334         for (mask = 0x80; mask; mask >>= 1) {
00335             SBBI0_SCK_CLR();
00336             if (data & mask) {
00337                 SBBI0_MOSI_SET();
00338             } else {
00339                 SBBI0_MOSI_CLR();
00340             }
00341             Sbbi0Delay();
00342             SBBI0_SCK_SET();
00343             if (SBBI0_MISO_TST()) {
00344                 data |= mask;
00345             }
00346             else {
00347                 data &= ~mask;
00348             }
00349             Sbbi0Delay();
00350         }
00351     }
00352     else if (sel_mode == 2) {
00353         /* Mode 2: Leading edge is falling, data sampled on falling edge. */
00354         for (mask = 0x80; mask; mask >>= 1) {
00355             SBBI0_SCK_SET();
00356             if (data & mask) {
00357                 SBBI0_MOSI_SET();
00358             } else {
00359                 SBBI0_MOSI_CLR();
00360             }
00361             Sbbi0Delay();
00362             SBBI0_SCK_CLR();
00363             if (SBBI0_MISO_TST()) {
00364                 data |= mask;
00365             }
00366             else {
00367                 data &= ~mask;
00368             }
00369             Sbbi0Delay();
00370         }
00371         SBBI0_SCK_SET();
00372     }
00373     else if (sel_mode == 1) {
00374         /* Mode 1: Leading edge is rising, data sampled on falling edge. */
00375         for (mask = 0x80; mask; mask >>= 1) {
00376             SBBI0_SCK_SET();
00377             if (data & mask) {
00378                 SBBI0_MOSI_SET();
00379             } else {
00380                 SBBI0_MOSI_CLR();
00381             }
00382             Sbbi0Delay();
00383             SBBI0_SCK_CLR();
00384             if (SBBI0_MISO_TST()) {
00385                 data |= mask;
00386             }
00387             else {
00388                 data &= ~mask;
00389             }
00390             Sbbi0Delay();
00391         }
00392     }
00393     else {
00394         /* Mode 0: Leading edge is rising, data sampled on rising edge. */
00395         for (mask = 0x80; mask; mask >>= 1) {
00396             SBBI0_SCK_CLR();
00397             if (data & mask) {
00398                 SBBI0_MOSI_SET();
00399             } else {
00400                 SBBI0_MOSI_CLR();
00401             }
00402             Sbbi0Delay();
00403             SBBI0_SCK_SET();
00404             if (SBBI0_MISO_TST()) {
00405                 data |= mask;
00406             }
00407             else {
00408                 data &= ~mask;
00409             }
00410             Sbbi0Delay();
00411         }
00412         SBBI0_SCK_CLR();
00413     }
00414     return data;
00415 }
00416 
00433 void Sbbi0Transact(CONST void *wdata, void *rdata, size_t len)
00434 {
00435     CONST uint8_t *wp = (CONST uint8_t *)wdata;
00436 
00437     if (rdata) {
00438         uint8_t *rp = (uint8_t *)rdata;
00439 
00440         while(len--) {
00441             *rp++ = Sbbi0Byte(*wp);
00442             wp++;
00443         }
00444     } else {
00445         while(len--) {
00446             Sbbi0Byte(*wp);
00447             wp++;
00448         }
00449     }
00450 }
00451 

© 2000-2007 by egnite Software GmbH - visit http://www.ethernut.de/