webradio/config.c

Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2006-2007 by egnite Software GmbH. All rights reserved.
00003  * Copyright (C) 2008 by egnite GmbH. All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions
00007  * are met:
00008  *
00009  * 1. Redistributions of source code must retain the above copyright
00010  *    notice, this list of conditions and the following disclaimer.
00011  * 2. Redistributions in binary form must reproduce the above copyright
00012  *    notice, this list of conditions and the following disclaimer in the
00013  *    documentation and/or other materials provided with the distribution.
00014  * 3. Neither the name of the copyright holders nor the names of
00015  *    contributors may be used to endorse or promote products derived
00016  *    from this software without specific prior written permission.
00017  *
00018  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00019  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00020  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00021  * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00022  * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00023  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00024  * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
00025  * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
00026  * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
00027  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
00028  * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
00029  * SUCH DAMAGE.
00030  *
00031  * For additional information see http://www.ethernut.de/
00032  */
00033 
00043 #include <cfg/clock.h>
00044 
00045 #include <dev/board.h>
00046 #include <dev/at45db.h>
00047 
00048 #include <sys/confos.h>
00049 #include <sys/confnet.h>
00050 
00051 #include <string.h>
00052 #include <stdlib.h>
00053 
00054 #include <arpa/inet.h>
00055 
00056 #include "config.h"
00057 #include "logmsg.h"
00058 #include "favlist.h"
00059 #include "webradio.h"
00060 
00061 #define CONFIG_MAGIC    "ir1"
00062 #define CONFOS_SECTOR   0
00063 #define CONFNET_SECTOR  1
00064 #define CONFIG_SECTOR   2
00065 
00066 static int at45db;
00067 static u_int page_size;
00068 
00072 HTTP_PROXY proxy;
00073 
00074 #define DF_WRITE_POLLS        1000
00075 
00076 #define DFCMD_READ_STATUS       0xD7
00077 #define DFCMD_CONT_READ         0xE8
00078 #define DFCMD_BUF1_WRITE        0x84
00079 #define DFCMD_BUF1_FLASH        0x83
00080 #define DFCMD_PAGE_ERASE        0x81
00081 
00082 #if defined(ELEKTOR_IR1)
00083 
00084 #define VS10XX_XCS_BIT          31
00085 #define VS10XX_XCS_PIO_ID       PIOA_ID
00086 #define VS10XX_XDCS_BIT         30
00087 #define VS10XX_XDCS_PIO_ID      PIOB_ID
00088 #define VS10XX_DREQ_BIT         30
00089 #define VS10XX_DREQ_PIO_ID      PIOA_ID
00090 #define VS10XX_SIGNAL           sig_INTERRUPT1
00091 #define VS_XRESET_BIT           31 /* PB31 */
00092 
00093 /*
00094  * Temporary hack to get the radio running with our incomplete system software.
00095  */
00096 int InitElektorHardware(void)
00097 {
00098     static int done;
00099 
00100     if (!done) {
00101         /* Enable peripherals. */
00102         outr(PIOA_ASR, inr(PIOA_ASR) 
00103             | _BV(PA12_SPI0_MISO_A) 
00104             | _BV(PA13_SPI0_MOSI_A)
00105             | _BV(PA14_SPI0_SPCK_A)
00106             | _BV(PA30_IRQ1_A));
00107 
00108         /* Disable PIO lines used for peripherals. */
00109         outr(PIOA_PDR, _BV(PA12_SPI0_MISO_A)
00110             | _BV(PA13_SPI0_MOSI_A)
00111             | _BV(PA14_SPI0_SPCK_A)
00112             | _BV(PA30_IRQ1_A));
00113 
00114         /* Chip selects are manually controlled. */
00115         /* Enable XCS control. */
00116         outr(PIOA_PER, _BV(VS10XX_XCS_BIT));
00117         outr(PIOA_SODR, _BV(VS10XX_XCS_BIT));
00118         outr(PIOA_OER, _BV(VS10XX_XCS_BIT));
00119 
00120         /* Enable XDCS control. */
00121         outr(PIOB_PER, _BV(VS10XX_XDCS_BIT));
00122         outr(PIOB_SODR, _BV(VS10XX_XDCS_BIT));
00123         outr(PIOB_OER, _BV(VS10XX_XDCS_BIT));
00124 
00125         /* Release reset line. */
00126         outr(PIOB_PER, _BV(VS_XRESET_BIT));
00127         outr(PIOB_SODR, _BV(VS_XRESET_BIT));
00128         outr(PIOB_OER, _BV(VS_XRESET_BIT));
00129 
00130         /* DataFlash chip select. */
00131         outr(PIOA_PER, _BV(PA11_SPI0_NPCS0_A));
00132         outr(PIOA_SODR, _BV(PA11_SPI0_NPCS0_A));
00133         outr(PIOA_OER, _BV(PA11_SPI0_NPCS0_A));
00134 
00135         /* Enable clocks. */
00136         outr(PMC_PCER, _BV(SPI0_ID) | _BV(IRQ1_ID) | _BV(PIOA_ID) | _BV(PIOB_ID) | _BV(PIOC_ID));
00137 
00138         /* SPI enable and reset. */
00139         outr(SPI0_CR, SPI_SPIEN | SPI_SWRST);
00140         outr(SPI0_CR, SPI_SPIEN);
00141 
00142         done = 1;
00143     }
00144     return 0;
00145 }
00146 #endif
00147 
00148 /*
00149  * No interlink available yet. Provide basic SPI routines.
00150  */
00151 
00152 int SpiSetMode(void)
00153 {
00154     /* Set SPI to master mode, fixed peripheral, fault detection disabled. */
00155     outr(SPI0_MR, SPI_MODFDIS | SPI_MSTR);
00156 
00157     /* Data changes during clock low and will be sampled on rising edges. */
00158     outr(SPI0_CSR0, (255 << SPI_SCBR_LSB) | SPI_NCPHA);
00159 
00160     return 0;
00161 }
00162 
00163 static u_char SpiByte(u_char val)
00164 {
00165     //printf("[%02x", val);
00166     /* Transmission is started by writing the transmit data. */
00167     outr(SPI0_TDR, val);
00168     /* Wait for receiver data register full. */
00169     while((inr(SPI0_SR) & SPI_RDRF) == 0);
00170     /* Read data. */
00171     val = (u_char)inr(SPI0_RDR);
00172     //printf(":%02x]", val);
00173 
00174     return val;
00175 }
00176 
00177 int At91SpiTransfer2(u_int base, u_int cs, CONST void *txbuf, void *rxbuf, int xlen, CONST void *txnbuf, void *rxnbuf, int xnlen)
00178 {
00179     u_char *txp;
00180     u_char *rxp;
00181     u_char b;
00182 
00183     //putchar('\n');
00184     SpiSetMode();
00185     outr(PIOA_CODR, _BV(PA11_SPI0_NPCS0_A));
00186     txp = (u_char *)txbuf;
00187     rxp = (u_char *)rxbuf;
00188     b = 0xff;
00189     while (xlen--) {
00190         if (txp) {
00191             b = *txp++;
00192         }
00193         b = SpiByte(b);
00194         if (rxp) {
00195             *rxp++ = b;
00196         }
00197     }
00198     txp = (u_char *)txnbuf;
00199     rxp = (u_char *)rxnbuf;
00200     b = 0xff;
00201     while (xnlen--) {
00202         if (txp) {
00203             b = *txp++;
00204         }
00205         b = SpiByte(b);
00206         if (rxp) {
00207             *rxp++ = b;
00208         }
00209     }
00210     outr(PIOA_SODR, _BV(PA11_SPI0_NPCS0_A));
00211 
00212     return 0;
00213 }
00214 
00215 
00223 size_t ConfigSize(void)
00224 {
00225     size_t rc = 0;
00226     int idx;
00227     int i;
00228     RADIOSTATION *flp;
00229 
00230     for (idx = 1; idx < MAX_FAVORITES; idx++) {
00231         flp = &favlist[idx];
00232         if (flp->rs_name) {
00233             rc += strlen(flp->rs_name) + 1;
00234             for (i = 0; i < flp->rs_streams; i++) {
00235                 if (flp->rs_uri[i]) {
00236                     rc += strlen(flp->rs_uri[i]) + 1;
00237                 }
00238             }
00239         }
00240     }
00241     return rc + 1;
00242 }
00243 
00244 static u_long pgnum;
00245 static int pgpos = -1;
00246 static u_char pgbuf[1056];
00247 
00248 void ConfigFlush(void)
00249 {
00250     if (pgpos > 0) {
00251         At45dbPageErase(at45db, pgnum);
00252         At45dbPageWrite(at45db, pgnum, pgbuf, page_size);
00253     }
00254 }
00255 
00256 static void ConfigPut(u_char ch)
00257 {
00258     if (pgpos < 0) {
00259         memset(pgbuf, 0xFF, page_size);
00260         pgpos = 0;
00261     }
00262     pgbuf[pgpos++] = ch;
00263     if (pgpos >= page_size) {
00264         ConfigFlush();
00265         pgnum++;
00266         pgpos = 0;
00267     }
00268 }
00269 
00270 static u_char ConfigGet(void)
00271 {
00272     if (pgpos < 0 || pgpos >= page_size) {
00273         At45dbPageRead(at45db, pgnum, pgbuf, page_size);
00274         pgnum++;
00275         pgpos = 0;
00276     }
00277     return pgbuf[pgpos++];
00278 }
00279 
00280 void ConfigSaveString(char *str)
00281 {
00282     //printf("[Save'%s']", str);
00283     do {
00284         ConfigPut(*str);
00285     } while(*str++);
00286 }
00287 
00288 size_t ConfigLoadString(char * str, size_t size)
00289 {
00290     size_t rc = 0;
00291     u_char ch;
00292 
00293     while (rc < size && (ch = ConfigGet()) != 0) {
00294         str[rc++] = ch;
00295     }
00296     str[rc++] = 0;
00297     //printf("[Load'%s']", str);
00298 
00299     return rc;
00300 }
00301 
00302 void ConfigSaveBinary(void *data, size_t len)
00303 {
00304     u_char *dp = (u_char *)data;
00305 
00306     while (len--) {
00307         ConfigPut(*dp);
00308         dp++;
00309     }
00310 }
00311 
00312 void ConfigLoadBinary(void *data, size_t len)
00313 {
00314     u_char *dp = (u_char *)data;
00315 
00316     while (len--) {
00317         *dp++ = ConfigGet();
00318     }
00319 }
00320 
00321 void ConfigRewind(u_long pgn)
00322 {
00323     pgnum = pgn;
00324     pgpos = -1;
00325 }
00326 
00327 /*
00328  * No NvMem support for all platforms. Provide system configuration.
00329  */
00330 CONFOS confos;
00331 CONFNET confnet;
00332 
00341 int NutLoadConfig(void)
00342 {
00343     if (ConfigInit() == 0) {
00344         ConfigRewind(CONFOS_SECTOR);
00345         ConfigLoadBinary(&confos, sizeof(CONFOS));
00346         if (confos.size == sizeof(CONFOS) && confos.magic[0] == 'O' && confos.magic[1] == 'S') {
00347             return 0;
00348         }
00349     }
00350     memset(&confos, 0, sizeof(CONFOS));
00351     return -1;
00352 }
00353 
00359 int NutSaveConfig(void)
00360 {
00361     confos.size = sizeof(CONFOS);
00362     confos.magic[0] = 'O';
00363     confos.magic[1] = 'S';
00364     ConfigRewind(CONFOS_SECTOR);
00365     ConfigSaveBinary(&confos, sizeof(CONFOS));
00366     ConfigFlush();
00367 
00368     return 0;
00369 }
00370 
00383 int NutNetLoadConfig(CONST char *name)
00384 {
00385     if (ConfigInit() == 0) {
00386         ConfigRewind(CONFNET_SECTOR);
00387         ConfigLoadBinary(&confnet, sizeof(CONFNET));
00388         if (confnet.cd_size == sizeof(CONFNET) && strcmp(confnet.cd_name, name) == 0) {
00389             return 0;
00390         }
00391     }
00392     memset(&confnet, 0, sizeof(confnet));
00393     memset(confnet.cdn_mac, 0xFF, sizeof(confnet.cdn_mac));
00394 
00395     return -1;
00396 }
00397 
00403 int NutNetSaveConfig(void)
00404 {
00405     confnet.cd_size = sizeof(CONFNET);
00406     ConfigRewind(CONFNET_SECTOR);
00407     ConfigSaveBinary(&confnet, sizeof(CONFNET));
00408     ConfigFlush();
00409 
00410     return 0;
00411 }
00412 
00416 int ConfigSave(void)
00417 {
00418     /* Save our name. */
00419     ConfigRewind(CONFIG_SECTOR);
00420     ConfigSaveString(CONFIG_MAGIC);
00421 
00422     /* Save radio control. */
00423     ConfigSaveBinary(&webradio.wr_gain, sizeof(webradio.wr_gain));
00424     ConfigSaveBinary(&webradio.wr_pridns, sizeof(webradio.wr_pridns));
00425     ConfigSaveBinary(&webradio.wr_secdns, sizeof(webradio.wr_secdns));
00426     ConfigSaveString(proxy.proxy_host);
00427     ConfigSaveBinary(&proxy.proxy_port, sizeof(proxy.proxy_port));
00428     ConfigFlush();
00429     LogMsg(LOG_CONFIG, "Saved %d %s %s %s:%u\n", 
00430         webradio.wr_gain, 
00431         inet_ntoa(webradio.wr_pridns),
00432         inet_ntoa(webradio.wr_secdns),
00433         proxy.proxy_host, proxy.proxy_port);
00434 
00435     return 0;
00436 }
00437 
00438 int ConfigLoad(void)
00439 {
00440     int rc = -1;
00441     char *buf;
00442 
00443     buf = malloc(32);
00444 
00445     ConfigRewind(CONFIG_SECTOR);
00446     ConfigLoadString(buf, 32);
00447     if (strcmp(buf, CONFIG_MAGIC) == 0) {
00448         rc = 0;
00449         ConfigLoadBinary(&webradio.wr_gain, sizeof(webradio.wr_gain));
00450         ConfigLoadBinary(&webradio.wr_pridns, sizeof(webradio.wr_pridns));
00451         ConfigLoadBinary(&webradio.wr_secdns, sizeof(webradio.wr_secdns));
00452         ConfigLoadString(proxy.proxy_host, sizeof(proxy.proxy_host));
00453         ConfigLoadBinary(&proxy.proxy_port, sizeof(proxy.proxy_port));
00454         LogMsg(LOG_CONFIG, "Loaded %d %s %s %s:%u\n", 
00455             webradio.wr_gain, 
00456             inet_ntoa(webradio.wr_pridns),
00457             inet_ntoa(webradio.wr_secdns),
00458             proxy.proxy_host, proxy.proxy_port);
00459     } else {
00460         LogMsg(LOG_CONFIG, "No configuration\n");
00461     }
00462     free(buf);
00463 
00464     return rc;
00465 }
00466 
00470 void ConfigResetFactory(void)
00471 {
00472     LogMsg(LOG_CONFIG, "Factory reset\n");
00473     /* Initial radio control settings. */
00474     webradio.wr_gain = -12;
00475     webradio.wr_pridns = 0;
00476     webradio.wr_secdns = 0;
00477     memset(&proxy, 0, sizeof(proxy));
00478 }
00479 
00480 int ConfigInit(void)
00481 {
00482     if (page_size == 0) {
00483 #if defined(ELEKTOR_IR1)
00484         InitElektorHardware();
00485 #endif
00486         if ((at45db = At45dbInit(SPI0_BASE, 0)) == -1) {
00487             return -1;
00488         }
00489         page_size = At45dbPageSize(at45db);
00490     }
00491     return 0;
00492 }

© 2008 by egnite GmbH - visit www.ethernut.de