summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorBertrik Sikken <bertrik@sikken.nl>2010-06-15 20:57:48 +0000
committerBertrik Sikken <bertrik@sikken.nl>2010-06-15 20:57:48 +0000
commitfcea117d21102383b35124a9e2513a51971a3fb5 (patch)
treeed21491ee9b061dedd07908a939a2e3eff2f0149 /firmware
parent267a446887dbeafe02a4e1991af4489979fbb044 (diff)
downloadrockbox-fcea117d21102383b35124a9e2513a51971a3fb5.tar.gz
rockbox-fcea117d21102383b35124a9e2513a51971a3fb5.zip
Support for mystery FM chip in some Sansa Clip+, FS #11403 by me
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@26864 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/SOURCES4
-rw-r--r--firmware/drivers/tuner/fmclipplus.c328
-rw-r--r--firmware/drivers/tuner/si4700.c29
-rw-r--r--firmware/export/config.h1
-rw-r--r--firmware/export/config/sansaclipplus.h2
-rw-r--r--firmware/export/fmclipplus.h54
-rw-r--r--firmware/export/si4700.h1
-rw-r--r--firmware/export/tuner.h6
-rw-r--r--firmware/target/arm/as3525/sansa-clipplus/tuner-clipplus.c38
-rw-r--r--firmware/tuner.c18
10 files changed, 470 insertions, 11 deletions
diff --git a/firmware/SOURCES b/firmware/SOURCES
index c716b78432..b49382a0e9 100644
--- a/firmware/SOURCES
+++ b/firmware/SOURCES
@@ -248,6 +248,9 @@ drivers/tuner/si4700.c
#if (CONFIG_TUNER & IPOD_REMOTE_TUNER)
drivers/tuner/ipod_remote_tuner.c
#endif /* (CONFIG_TUNER & IPOD_REMOTE_TUNER) */
+#if (CONFIG_TUNER & FMCLIPPLUS)
+drivers/tuner/fmclipplus.c
+#endif /* (CONFIG_TUNER & FMCLIPPLUS) */
#endif /*SIMULATOR */
#endif /* CONFIG_TUNER */
#endif /* BOOTLOADER */
@@ -1251,6 +1254,7 @@ target/arm/as3525/sansa-clipplus/backlight-clip.c
target/arm/powermgmt-ascodec.c
target/arm/as3525/sansa-clipplus/powermgmt-clipplus.c
target/arm/as3525/sansa-clipplus/lcd-as-clip-plus.S
+target/arm/as3525/sansa-clipplus/tuner-clipplus.c
#endif /* !BOOTLOADER */
#endif /* !SIMULATOR */
#endif /* SANSA_CLIPPLUS */
diff --git a/firmware/drivers/tuner/fmclipplus.c b/firmware/drivers/tuner/fmclipplus.c
new file mode 100644
index 0000000000..4badfba08f
--- /dev/null
+++ b/firmware/drivers/tuner/fmclipplus.c
@@ -0,0 +1,328 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Tuner "middleware" for unidentified Silicon Labs chip present in some
+ * Sansa Clip+ players
+ *
+ * Copyright (C) 2010 Bertrik Sikken
+ * Copyright (C) 2008 Nils Wallménius (si4700 code that this was based on)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include <stdbool.h>
+#include <string.h>
+#include <stdlib.h>
+#include "kernel.h"
+#include "tuner.h" /* tuner abstraction interface */
+#include "fmradio.h"
+#include "fmradio_i2c.h" /* physical interface driver */
+
+#define SEEK_THRESHOLD 0x10
+
+#define I2C_ADR 0x20
+
+/** Registers and bits **/
+#define POWERCFG 0x2
+#define CHANNEL 0x3
+#define SYSCONFIG1 0x4
+#define SYSCONFIG2 0x5
+#define SYSCONFIG3 0x6
+
+#define READCHAN 0xA
+#define STATUSRSSI 0xB
+#define IDENT 0xC
+
+
+/* POWERCFG (0x2) */
+#define POWERCFG_DMUTE (0x1 << 14)
+#define POWERCFG_MONO (0x1 << 13)
+#define POWERCFG_ENABLE (0x1 << 0)
+
+/* CHANNEL (0x3) */
+#define CHANNEL_CHAN (0x3ff << 6)
+ #define CHANNEL_CHANw(x) (((x) << 6) & CHANNEL_CHAN)
+#define CHANNEL_TUNE (0x1 << 4)
+#define CHANNEL_BAND (0x3 << 2)
+ #define CHANNEL_BANDw(x) (((x) << 2) & CHANNEL_BAND)
+ #define CHANNEL_BANDr(x) (((x) & CHANNEL_BAND) >> 2)
+ #define CHANNEL_BAND_875_1080 (0x0 << 2) /* tenth-megahertz */
+ #define CHANNEL_BAND_760_1080 (0x1 << 2)
+ #define CHANNEL_BAND_760_900 (0x2 << 2)
+#define CHANNEL_SPACE (0x3 << 0)
+ #define CHANNEL_SPACEw(x) (((x) << 0) & CHANNEL_SPACE)
+ #define CHANNEL_SPACEr(x) (((x) & CHANNEL_SPACE) >> 0)
+ #define CHANNEL_SPACE_200KHZ (0x0 << 0)
+ #define CHANNEL_SPACE_100KHZ (0x1 << 0)
+ #define CHANNEL_SPACE_50KHZ (0x2 << 0)
+
+/* SYSCONFIG1 (0x4) */
+#define SYSCONFIG1_DE (0x1 << 11)
+
+/* READCHAN (0xA) */
+#define READCHAN_READCHAN (0x3ff << 0)
+ #define READCHAN_READCHANr(x) (((x) & READCHAN_READCHAN) >> 0)
+#define READCHAN_STC (0x1 << 14)
+
+/* STATUSRSSI (0xB) */
+#define STATUSRSSI_RSSI (0x3F << 10)
+ #define STATUSRSSI_RSSIr(x) (((x) & STATUSRSSI_RSSI) >> 10)
+#define STATUSRSSI_AFCRL (0x1 << 8)
+
+static const uint16_t initvals[32] = {
+ 0x8110, 0x4580, 0xC401, 0x1B90,
+ 0x0400, 0x866F, 0x8000, 0x4712,
+ 0x5EC6, 0x0000, 0x406E, 0x2D80,
+ 0x5803, 0x5804, 0x5804, 0x5804,
+
+ 0x0047, 0x9000, 0xF587, 0x0009,
+ 0x00F1, 0x41C0, 0x41E0, 0x506F,
+ 0x5592, 0x007D, 0x10A0, 0x0780,
+ 0x311D, 0x4006, 0x1F9B, 0x4C2B
+};
+
+static bool tuner_present = false;
+static int curr_frequency = 87500000; /* Current station frequency (HZ) */
+static uint16_t cache[32];
+
+/* reads <len> registers from radio at offset 0x0A into cache */
+static void fmclipplus_read(int len)
+{
+ int i;
+ unsigned char buf[64];
+ unsigned char *ptr = buf;
+ uint16_t data;
+
+ fmradio_i2c_read(I2C_ADR, buf, len * 2);
+ for (i = 0; i < len; i++) {
+ data = ptr[0] << 8 | ptr[1];
+ cache[(i + READCHAN) & 0x1F] = data;
+ ptr += 2;
+ }
+}
+
+/* writes <len> registers from cache to radio at offset 0x02 */
+static void fmclipplus_write(int len)
+{
+ int i;
+ unsigned char buf[64];
+ unsigned char *ptr = buf;
+ uint16_t data;
+
+ for (i = 0; i < len; i++) {
+ data = cache[(i + POWERCFG) & 0x1F];
+ *ptr++ = (data >> 8) & 0xFF;
+ *ptr++ = data & 0xFF;
+ }
+ fmradio_i2c_write(I2C_ADR, buf, len * 2);
+}
+
+static uint16_t fmclipplus_read_reg(int reg)
+{
+ fmclipplus_read(((reg - READCHAN) & 0x1F) + 1);
+ return cache[reg];
+}
+
+static void fmclipplus_write_reg(int reg, uint16_t value)
+{
+ cache[reg] = value;
+}
+
+static void fmclipplus_write_cache(void)
+{
+ fmclipplus_write(5);
+}
+
+static void fmclipplus_write_masked(int reg, uint16_t bits, uint16_t mask)
+{
+ fmclipplus_write_reg(reg, (cache[reg] & ~mask) | (bits & mask));
+}
+
+static void fmclipplus_write_clear(int reg, uint16_t mask)
+{
+ fmclipplus_write_reg(reg, cache[reg] & ~mask);
+}
+
+static void fmclipplus_sleep(int snooze)
+{
+ if (snooze) {
+ fmclipplus_write_masked(POWERCFG, 0, 0xFF);
+ }
+ else {
+ fmclipplus_write_masked(POWERCFG, 1, 0xFF);
+ }
+ fmclipplus_write_cache();
+}
+
+bool fmclipplus_detect(void)
+{
+ return ((fmclipplus_read_reg(IDENT) & 0xFF00) == 0x5800);
+ }
+
+void fmclipplus_init(void)
+{
+ if (fmclipplus_detect()) {
+ tuner_present = true;
+
+ // send pre-initialisation value
+ fmclipplus_write_reg(POWERCFG, 0x200);
+ fmclipplus_write(2);
+ sleep(HZ * 10 / 100);
+
+ // write initialisation values
+ memcpy(cache, initvals, sizeof(cache));
+ fmclipplus_write(32);
+ sleep(HZ * 70 / 1000);
+ }
+}
+
+static void fmclipplus_set_frequency(int freq)
+{
+ int i;
+
+ /* check BAND and spacings */
+ fmclipplus_read_reg(STATUSRSSI);
+ int start = CHANNEL_BANDr(cache[CHANNEL]) & 1 ? 76000000 : 87000000;
+ int chan = (freq - start) / 50000;
+
+ curr_frequency = freq;
+
+ for (i = 0; i < 5; i++) {
+ /* tune and wait a bit */
+ fmclipplus_write_masked(CHANNEL, CHANNEL_CHANw(chan) | CHANNEL_TUNE,
+ CHANNEL_CHAN | CHANNEL_TUNE);
+ fmclipplus_write_cache();
+ sleep(HZ * 70 / 1000);
+ fmclipplus_write_clear(CHANNEL, CHANNEL_TUNE);
+ fmclipplus_write_cache();
+
+ /* check if tuning was successful */
+ fmclipplus_read_reg(STATUSRSSI);
+ if (cache[READCHAN] & READCHAN_STC) {
+ if (READCHAN_READCHANr(cache[READCHAN]) == chan) {
+ break;
+ }
+ }
+ }
+}
+
+static int fmclipplus_tuned(void)
+{
+ /* Primitive tuning check: sufficient level and AFC not railed */
+ uint16_t status = fmclipplus_read_reg(STATUSRSSI);
+ if (STATUSRSSI_RSSIr(status) >= SEEK_THRESHOLD &&
+ (status & STATUSRSSI_AFCRL) == 0) {
+ return 1;
+ }
+
+ return 0;
+}
+
+static void fmclipplus_set_region(int region)
+{
+ const struct fmclipplus_region_data *rd = &fmclipplus_region_data[region];
+ uint16_t bandspacing = CHANNEL_BANDw(rd->band) |
+ CHANNEL_SPACEw(CHANNEL_SPACE_50KHZ);
+ uint16_t oldbs = cache[CHANNEL] & (CHANNEL_BAND | CHANNEL_SPACE);
+
+ fmclipplus_write_masked(SYSCONFIG1, rd->deemphasis ? SYSCONFIG1_DE : 0,
+ SYSCONFIG1_DE);
+ fmclipplus_write_masked(CHANNEL, bandspacing, CHANNEL_BAND | CHANNEL_SPACE);
+ fmclipplus_write_cache();
+
+ /* Retune if this region change would change the channel number. */
+ if (oldbs != bandspacing) {
+ fmclipplus_set_frequency(curr_frequency);
+ }
+}
+
+static bool fmclipplus_st(void)
+{
+ /* TODO not implemented yet */
+ return false;
+}
+
+/* tuner abstraction layer: set something to the tuner */
+int fmclipplus_set(int setting, int value)
+{
+ switch (setting) {
+ case RADIO_SLEEP:
+ if (value != 2) {
+ fmclipplus_sleep(value);
+ }
+ break;
+
+ case RADIO_FREQUENCY:
+ fmclipplus_set_frequency(value);
+ break;
+
+ case RADIO_SCAN_FREQUENCY:
+ fmclipplus_set_frequency(value);
+ return fmclipplus_tuned();
+
+ case RADIO_MUTE:
+ fmclipplus_write_masked(POWERCFG, value ? 0 : POWERCFG_DMUTE,
+ POWERCFG_DMUTE);
+ fmclipplus_write_masked(SYSCONFIG1, (3 << 9), (3 << 9));
+ fmclipplus_write_masked(SYSCONFIG2, (0xF << 0), (0xF << 0));
+ fmclipplus_write_cache();
+ break;
+
+ case RADIO_REGION:
+ fmclipplus_set_region(value);
+ break;
+
+ case RADIO_FORCE_MONO:
+ fmclipplus_write_masked(POWERCFG, value ? POWERCFG_MONO : 0,
+ POWERCFG_MONO);
+ fmclipplus_write_cache();
+ break;
+
+ default:
+ return -1;
+ }
+
+ return 1;
+}
+
+/* tuner abstraction layer: read something from the tuner */
+int fmclipplus_get(int setting)
+{
+ int val = -1; /* default for unsupported query */
+
+ switch (setting) {
+ case RADIO_PRESENT:
+ val = tuner_present ? 1 : 0;
+ break;
+
+ case RADIO_TUNED:
+ val = fmclipplus_tuned();
+ break;
+
+ case RADIO_STEREO:
+ val = fmclipplus_st();
+ break;
+ }
+
+ return val;
+}
+
+void fmclipplus_dbg_info(struct fmclipplus_dbg_info *nfo)
+{
+ fmclipplus_read(32);
+ memcpy(nfo->regs, cache, sizeof (nfo->regs));
+}
+
diff --git a/firmware/drivers/tuner/si4700.c b/firmware/drivers/tuner/si4700.c
index 985659b77b..8e43fe6acc 100644
--- a/firmware/drivers/tuner/si4700.c
+++ b/firmware/drivers/tuner/si4700.c
@@ -316,30 +316,39 @@ static void si4700_sleep(int snooze)
}
}
-void si4700_init(void)
+bool si4700_detect(void)
{
+ bool detected;
+
tuner_power(true);
+ detected = (si4700_read_reg(DEVICEID) == 0x1242);
+ tuner_power(false);
- /* read all registers */
- si4700_read(16);
- si4700_sleep(0);
+ return detected;
+}
+void si4700_init(void)
+{
/* check device id */
- if (cache[DEVICEID] == 0x1242)
- {
+ if (si4700_detect()) {
tuner_present = true;
+ tuner_power(true);
+
+ /* read all registers */
+ si4700_read(16);
+ si4700_sleep(0);
+
#ifdef USE_INTERNAL_OSCILLATOR
/* Enable the internal oscillator
(Si4702-16 needs this register to be initialised to 0x100) */
si4700_write_set(TEST1, TEST1_XOSCEN | 0x100);
sleep(HZ/2);
#endif
- }
- si4700_sleep(1);
-
- tuner_power(false);
+ si4700_sleep(1);
+ tuner_power(false);
+ }
}
static void si4700_set_frequency(int freq)
diff --git a/firmware/export/config.h b/firmware/export/config.h
index a2ba3f9f98..7f77514116 100644
--- a/firmware/export/config.h
+++ b/firmware/export/config.h
@@ -41,6 +41,7 @@
#define TEA5760 0x10 /* Philips */
#define LV240000 0x20 /* Sanyo */
#define IPOD_REMOTE_TUNER 0x40 /* Apple */
+#define FMCLIPPLUS 0x80 /* Mystery SiLabs FM tuner in some clip+ */
/* CONFIG_CODEC */
#define MAS3587F 3587
diff --git a/firmware/export/config/sansaclipplus.h b/firmware/export/config/sansaclipplus.h
index 9382b22cbd..883a71ea21 100644
--- a/firmware/export/config/sansaclipplus.h
+++ b/firmware/export/config/sansaclipplus.h
@@ -123,7 +123,7 @@
#define AB_REPEAT_ENABLE 1
/* FM Tuner */
-#define CONFIG_TUNER SI4700 /* in fact SI4702 */
+#define CONFIG_TUNER (SI4700|FMCLIPPLUS) /* in fact SI4702 */
//#define HAVE_TUNER_PWR_CTRL
/* Define this for LCD backlight available */
diff --git a/firmware/export/fmclipplus.h b/firmware/export/fmclipplus.h
new file mode 100644
index 0000000000..20961f47be
--- /dev/null
+++ b/firmware/export/fmclipplus.h
@@ -0,0 +1,54 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ *
+ * $Id$
+ *
+ * Tuner header for the Silicon Labs Mystery radio chip in some Sansa Clip+
+ *
+ * Copyright (C) 2010 Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#ifndef _FMCLIPPLUS_H_
+#define _FMCLIPPLUS_H_
+
+#define HAVE_RADIO_REGION
+
+struct fmclipplus_region_data
+{
+ unsigned char deemphasis; /* 0: 75us, 1: 50us */
+ unsigned char band; /* 0: us/europe, 1: japan */
+} __attribute__((packed));
+
+extern const struct fmclipplus_region_data fmclipplus_region_data[TUNER_NUM_REGIONS];
+
+struct fmclipplus_dbg_info
+{
+ uint16_t regs[32]; /* Read registers */
+};
+
+bool fmclipplus_detect(void);
+void fmclipplus_init(void);
+int fmclipplus_set(int setting, int value);
+int fmclipplus_get(int setting);
+void fmclipplus_dbg_info(struct fmclipplus_dbg_info *nfo);
+
+#ifndef CONFIG_TUNER_MULTI
+#define tuner_set fmclipplus_set
+#define tuner_get fmclipplus_get
+#endif
+
+#endif /* _FMCLIPPLUS_H_ */
diff --git a/firmware/export/si4700.h b/firmware/export/si4700.h
index fcc71cb282..d6c4e73b6e 100644
--- a/firmware/export/si4700.h
+++ b/firmware/export/si4700.h
@@ -41,6 +41,7 @@ struct si4700_dbg_info
uint16_t regs[16]; /* Read registers */
};
+bool si4700_detect(void);
void si4700_init(void);
int si4700_set(int setting, int value);
int si4700_get(int setting);
diff --git a/firmware/export/tuner.h b/firmware/export/tuner.h
index 03b6bd79d1..9101bb9241 100644
--- a/firmware/export/tuner.h
+++ b/firmware/export/tuner.h
@@ -99,6 +99,7 @@ char* tuner_get_rds_info(int setting);
#else
#ifdef CONFIG_TUNER_MULTI
+extern int tuner_detect_type(void);
extern int (*tuner_set)(int setting, int value);
extern int (*tuner_get)(int setting);
#endif /* CONFIG_TUNER_MULTI */
@@ -131,6 +132,11 @@ extern int (*tuner_get)(int setting);
#include "si4700.h"
#endif
+/* Silicon Labs mystery radio chip in some Sansa Clip+ */
+#if (CONFIG_TUNER & FMCLIPPLUS)
+#include "fmclipplus.h"
+#endif
+
/* Apple remote tuner */
#if (CONFIG_TUNER & IPOD_REMOTE_TUNER)
#include "ipod_remote_tuner.h"
diff --git a/firmware/target/arm/as3525/sansa-clipplus/tuner-clipplus.c b/firmware/target/arm/as3525/sansa-clipplus/tuner-clipplus.c
new file mode 100644
index 0000000000..6bc1294eb4
--- /dev/null
+++ b/firmware/target/arm/as3525/sansa-clipplus/tuner-clipplus.c
@@ -0,0 +1,38 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Multi-tuner detection module to select between the si4700 and a yet
+ * unidentified Silicon Labs FM tuner chip found in some Sansa Clip+ players.
+ *
+ * Copyright (C) 2010 Bertrik Sikken
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#include "config.h"
+#include <stdint.h>
+#include "tuner.h"
+
+int tuner_detect_type(void)
+{
+ if (si4700_detect()) {
+ return SI4700;
+ } else if (fmclipplus_detect()) {
+ return FMCLIPPLUS;
+ } else {
+ return 0;
+ }
+}
+
diff --git a/firmware/tuner.c b/firmware/tuner.c
index cca5cf2491..4d3866dc8e 100644
--- a/firmware/tuner.c
+++ b/firmware/tuner.c
@@ -89,6 +89,18 @@ const struct si4700_region_data si4700_region_data[TUNER_NUM_REGIONS] =
};
#endif /* (CONFIG_TUNER & SI4700) */
+#if (CONFIG_TUNER & FMCLIPPLUS)
+const struct fmclipplus_region_data fmclipplus_region_data[TUNER_NUM_REGIONS] =
+{
+ [REGION_EUROPE] = { 1, 0 }, /* 50uS, US/Europe band */
+ [REGION_US_CANADA] = { 0, 0 }, /* 75uS, US/Europe band */
+ [REGION_JAPAN] = { 1, 1 }, /* 50uS, Japanese band */
+ [REGION_KOREA] = { 1, 0 }, /* 50uS, US/Europe band */
+ [REGION_ITALY] = { 1, 0 }, /* 50uS, US/Europe band */
+ [REGION_OTHER] = { 1, 0 }, /* 50uS, US/Europe band */
+};
+#endif /* (CONFIG_TUNER & FMCLIPPLUS) */
+
#if (CONFIG_TUNER & IPOD_REMOTE_TUNER)
const struct rmt_tuner_region_data
rmt_tuner_region_data[TUNER_NUM_REGIONS] =
@@ -151,6 +163,12 @@ void tuner_init(void)
si4700_get,
si4700_init())
#endif
+ #if (CONFIG_TUNER & FMCLIPPLUS)
+ TUNER_TYPE_CASE(FMCLIPPLUS,
+ fmclipplus_set,
+ fmclipplus_get,
+ fmclipplus_init())
+ #endif
}
}
#endif /* SIMULATOR */