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

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