streaming server for AM/FM radio via UDP connection.

Dependencies:   mbed EthernetNetIf

Committer:
soramimi
Date:
Mon Feb 28 11:49:39 2011 +0000
Revision:
0:bd865e5a3df3
Child:
1:3357273c97f8

        

Who changed what in which revision?

UserRevisionLine numberNew contents of line
soramimi 0:bd865e5a3df3 1 #include "mbed.h"
soramimi 0:bd865e5a3df3 2 #include "EthernetNetIf.h"
soramimi 0:bd865e5a3df3 3 #include "UDPSocket.h"
soramimi 0:bd865e5a3df3 4 #include "TextLCD.h"
soramimi 0:bd865e5a3df3 5 #include "crc32.h"
soramimi 0:bd865e5a3df3 6 #include "ns9542.h"
soramimi 0:bd865e5a3df3 7 #include <vector>
soramimi 0:bd865e5a3df3 8
soramimi 0:bd865e5a3df3 9 DigitalOut led1(LED1);
soramimi 0:bd865e5a3df3 10 DigitalOut led2(LED2);
soramimi 0:bd865e5a3df3 11 TextLCD lcd(p21, p22, p23, p24, p25, p26);
soramimi 0:bd865e5a3df3 12
soramimi 0:bd865e5a3df3 13 Ticker ticker;
soramimi 0:bd865e5a3df3 14
soramimi 0:bd865e5a3df3 15 SPI spi(p5, p6, p7); // mosi, miso, sclk
soramimi 0:bd865e5a3df3 16 DigitalOut spi_cs(p8);
soramimi 0:bd865e5a3df3 17
soramimi 0:bd865e5a3df3 18 EthernetNetIf eth(IpAddr(192,168,0,100), //IP Address
soramimi 0:bd865e5a3df3 19 IpAddr(255,255,255,0), //Network Mask
soramimi 0:bd865e5a3df3 20 IpAddr(192,168,0,1), //Gateway
soramimi 0:bd865e5a3df3 21 IpAddr(192,168,0,1) //DNS
soramimi 0:bd865e5a3df3 22 );
soramimi 0:bd865e5a3df3 23
soramimi 0:bd865e5a3df3 24 UDPSocket udpsocket;
soramimi 0:bd865e5a3df3 25
soramimi 0:bd865e5a3df3 26 unsigned short sample_l;
soramimi 0:bd865e5a3df3 27 unsigned short sample_r;
soramimi 0:bd865e5a3df3 28
soramimi 0:bd865e5a3df3 29 unsigned short sample_left()
soramimi 0:bd865e5a3df3 30 {
soramimi 0:bd865e5a3df3 31 spi_cs = 0;
soramimi 0:bd865e5a3df3 32 int v = spi.write(0x6800) & 0x03ff;
soramimi 0:bd865e5a3df3 33 spi_cs = 1;
soramimi 0:bd865e5a3df3 34 return (v << 6) | (v >> 4);
soramimi 0:bd865e5a3df3 35 }
soramimi 0:bd865e5a3df3 36
soramimi 0:bd865e5a3df3 37 unsigned short sample_right()
soramimi 0:bd865e5a3df3 38 {
soramimi 0:bd865e5a3df3 39 spi_cs = 0;
soramimi 0:bd865e5a3df3 40 int v = spi.write(0x7800) & 0x03ff;
soramimi 0:bd865e5a3df3 41 spi_cs = 1;
soramimi 0:bd865e5a3df3 42 return (v << 6) | (v >> 4);
soramimi 0:bd865e5a3df3 43 }
soramimi 0:bd865e5a3df3 44
soramimi 0:bd865e5a3df3 45 struct host_info_t {
soramimi 0:bd865e5a3df3 46 Host host;
soramimi 0:bd865e5a3df3 47 int timer;
soramimi 0:bd865e5a3df3 48 host_info_t()
soramimi 0:bd865e5a3df3 49 {
soramimi 0:bd865e5a3df3 50 }
soramimi 0:bd865e5a3df3 51 host_info_t(Host h)
soramimi 0:bd865e5a3df3 52 : host(h)
soramimi 0:bd865e5a3df3 53 , timer(0)
soramimi 0:bd865e5a3df3 54 {
soramimi 0:bd865e5a3df3 55 }
soramimi 0:bd865e5a3df3 56 };
soramimi 0:bd865e5a3df3 57
soramimi 0:bd865e5a3df3 58 std::vector<host_info_t> hostlist;
soramimi 0:bd865e5a3df3 59
soramimi 0:bd865e5a3df3 60 void on_udp_socket_event(UDPSocketEvent e)
soramimi 0:bd865e5a3df3 61 {
soramimi 0:bd865e5a3df3 62 if (e == UDPSOCKET_READABLE) {
soramimi 0:bd865e5a3df3 63 char buf[64] = {0};
soramimi 0:bd865e5a3df3 64 Host host;
soramimi 0:bd865e5a3df3 65 while (int len = udpsocket.recvfrom(buf, 63, &host)) {
soramimi 0:bd865e5a3df3 66 if (len <= 0) {
soramimi 0:bd865e5a3df3 67 break;
soramimi 0:bd865e5a3df3 68 }
soramimi 0:bd865e5a3df3 69 if (len == 7 && memcmp(buf, "request", len) == 0) {
soramimi 0:bd865e5a3df3 70 __disable_irq();
soramimi 0:bd865e5a3df3 71 size_t i, n;
soramimi 0:bd865e5a3df3 72 n = hostlist.size();
soramimi 0:bd865e5a3df3 73 for (i = 0; i < n; i++) {
soramimi 0:bd865e5a3df3 74 if (memcmp(&host, &hostlist[i].host, sizeof(Host)) == 0) {
soramimi 0:bd865e5a3df3 75 hostlist[i].timer = 0;
soramimi 0:bd865e5a3df3 76 break;
soramimi 0:bd865e5a3df3 77 }
soramimi 0:bd865e5a3df3 78 }
soramimi 0:bd865e5a3df3 79 if (i == n) {
soramimi 0:bd865e5a3df3 80 hostlist.push_back(host_info_t(host));
soramimi 0:bd865e5a3df3 81 }
soramimi 0:bd865e5a3df3 82 __enable_irq();
soramimi 0:bd865e5a3df3 83 continue;
soramimi 0:bd865e5a3df3 84 }
soramimi 0:bd865e5a3df3 85 if (len > 2 && memcmp(buf, "am", 2) == 0) {
soramimi 0:bd865e5a3df3 86 buf[len] = 0;
soramimi 0:bd865e5a3df3 87 int f = atoi(buf + 2);
soramimi 0:bd865e5a3df3 88 ns9542_tune_am9(f);
soramimi 0:bd865e5a3df3 89 continue;
soramimi 0:bd865e5a3df3 90 }
soramimi 0:bd865e5a3df3 91 if (len > 2 && memcmp(buf, "fm", 2) == 0) {
soramimi 0:bd865e5a3df3 92 buf[len] = 0;
soramimi 0:bd865e5a3df3 93 int f = atoi(buf + 2);
soramimi 0:bd865e5a3df3 94 ns9542_tune_fm(f);
soramimi 0:bd865e5a3df3 95 continue;
soramimi 0:bd865e5a3df3 96 }
soramimi 0:bd865e5a3df3 97 if (len > 4 && memcmp(buf, "mute", 4) == 0) {
soramimi 0:bd865e5a3df3 98 ns9542_mute(true);
soramimi 0:bd865e5a3df3 99 continue;
soramimi 0:bd865e5a3df3 100 }
soramimi 0:bd865e5a3df3 101 }
soramimi 0:bd865e5a3df3 102 }
soramimi 0:bd865e5a3df3 103 }
soramimi 0:bd865e5a3df3 104
soramimi 0:bd865e5a3df3 105 static inline void store(unsigned short *p, unsigned short n)
soramimi 0:bd865e5a3df3 106 {
soramimi 0:bd865e5a3df3 107 ((unsigned char *)p)[0] = n >> 8;
soramimi 0:bd865e5a3df3 108 ((unsigned char *)p)[1] = n & 0xff;
soramimi 0:bd865e5a3df3 109 }
soramimi 0:bd865e5a3df3 110
soramimi 0:bd865e5a3df3 111 static inline void store(unsigned long *p, unsigned long n)
soramimi 0:bd865e5a3df3 112 {
soramimi 0:bd865e5a3df3 113 ((unsigned char *)p)[0] = n >> 24;
soramimi 0:bd865e5a3df3 114 ((unsigned char *)p)[1] = n >> 16;
soramimi 0:bd865e5a3df3 115 ((unsigned char *)p)[2] = n >> 8;
soramimi 0:bd865e5a3df3 116 ((unsigned char *)p)[3] = n & 0xff;
soramimi 0:bd865e5a3df3 117 }
soramimi 0:bd865e5a3df3 118
soramimi 0:bd865e5a3df3 119 class Sampler {
soramimi 0:bd865e5a3df3 120 private:
soramimi 0:bd865e5a3df3 121 unsigned long buffer_a[257];
soramimi 0:bd865e5a3df3 122 unsigned long buffer_b[257];
soramimi 0:bd865e5a3df3 123 unsigned long *in_ptr;
soramimi 0:bd865e5a3df3 124 unsigned long *out_ptr;
soramimi 0:bd865e5a3df3 125 bool output_available;
soramimi 0:bd865e5a3df3 126 unsigned long crc;
soramimi 0:bd865e5a3df3 127 int offset;
soramimi 0:bd865e5a3df3 128 public:
soramimi 0:bd865e5a3df3 129 Sampler()
soramimi 0:bd865e5a3df3 130 {
soramimi 0:bd865e5a3df3 131 in_ptr = buffer_a;
soramimi 0:bd865e5a3df3 132 out_ptr = buffer_b;
soramimi 0:bd865e5a3df3 133 output_available = false;
soramimi 0:bd865e5a3df3 134 offset = 0;
soramimi 0:bd865e5a3df3 135 crc = 0;
soramimi 0:bd865e5a3df3 136 }
soramimi 0:bd865e5a3df3 137
soramimi 0:bd865e5a3df3 138 void on_tick()
soramimi 0:bd865e5a3df3 139 {
soramimi 0:bd865e5a3df3 140 if (output_available) {
soramimi 0:bd865e5a3df3 141 return;
soramimi 0:bd865e5a3df3 142 }
soramimi 0:bd865e5a3df3 143 unsigned short *p = (unsigned short *)in_ptr;
soramimi 0:bd865e5a3df3 144 p += offset * 2;
soramimi 0:bd865e5a3df3 145 store(p + 0, sample_l);
soramimi 0:bd865e5a3df3 146 store(p + 1, sample_r);
soramimi 0:bd865e5a3df3 147 crc = crc32(crc, (unsigned char *)p, 4);
soramimi 0:bd865e5a3df3 148 offset++;
soramimi 0:bd865e5a3df3 149 if (offset >= 256) {
soramimi 0:bd865e5a3df3 150 std::swap(in_ptr, out_ptr);
soramimi 0:bd865e5a3df3 151 store(&out_ptr[256], crc);
soramimi 0:bd865e5a3df3 152 output_available = true;
soramimi 0:bd865e5a3df3 153 offset = 0;
soramimi 0:bd865e5a3df3 154 crc = 0;
soramimi 0:bd865e5a3df3 155 }
soramimi 0:bd865e5a3df3 156 }
soramimi 0:bd865e5a3df3 157
soramimi 0:bd865e5a3df3 158 char const *output_buffer()
soramimi 0:bd865e5a3df3 159 {
soramimi 0:bd865e5a3df3 160 return output_available ? (char const *)out_ptr : 0;
soramimi 0:bd865e5a3df3 161 }
soramimi 0:bd865e5a3df3 162
soramimi 0:bd865e5a3df3 163 void output_done()
soramimi 0:bd865e5a3df3 164 {
soramimi 0:bd865e5a3df3 165 output_available = false;
soramimi 0:bd865e5a3df3 166 }
soramimi 0:bd865e5a3df3 167 };
soramimi 0:bd865e5a3df3 168
soramimi 0:bd865e5a3df3 169 Sampler sampler;
soramimi 0:bd865e5a3df3 170
soramimi 0:bd865e5a3df3 171 void on_tick()
soramimi 0:bd865e5a3df3 172 {
soramimi 0:bd865e5a3df3 173 sampler.on_tick();
soramimi 0:bd865e5a3df3 174 }
soramimi 0:bd865e5a3df3 175
soramimi 0:bd865e5a3df3 176 int main()
soramimi 0:bd865e5a3df3 177 {
soramimi 0:bd865e5a3df3 178 spi_cs = 1;
soramimi 0:bd865e5a3df3 179 spi.format(16, 0);
soramimi 0:bd865e5a3df3 180 spi.frequency(3000000);
soramimi 0:bd865e5a3df3 181
soramimi 0:bd865e5a3df3 182 ns9542_init();
soramimi 0:bd865e5a3df3 183
soramimi 0:bd865e5a3df3 184 eth.setup();
soramimi 0:bd865e5a3df3 185 Host host(IpAddr(), 2000);
soramimi 0:bd865e5a3df3 186 udpsocket.bind(host);
soramimi 0:bd865e5a3df3 187 udpsocket.setOnEvent(&on_udp_socket_event);
soramimi 0:bd865e5a3df3 188
soramimi 0:bd865e5a3df3 189 led1 = 0;
soramimi 0:bd865e5a3df3 190 ticker.attach(&on_tick, 1.0 / 32000);
soramimi 0:bd865e5a3df3 191
soramimi 0:bd865e5a3df3 192 int led1_timer = 0;
soramimi 0:bd865e5a3df3 193
soramimi 0:bd865e5a3df3 194 while (1) {
soramimi 0:bd865e5a3df3 195 sample_l = sample_left();
soramimi 0:bd865e5a3df3 196 sample_r = sample_right();
soramimi 0:bd865e5a3df3 197
soramimi 0:bd865e5a3df3 198 Net::poll();
soramimi 0:bd865e5a3df3 199
soramimi 0:bd865e5a3df3 200 char const *p = sampler.output_buffer();
soramimi 0:bd865e5a3df3 201 if (p) {
soramimi 0:bd865e5a3df3 202 for (std::vector<host_info_t>::iterator it = hostlist.begin(); it != hostlist.end(); it++) {
soramimi 0:bd865e5a3df3 203 udpsocket.sendto(p, 1028, (Host *)&it->host);
soramimi 0:bd865e5a3df3 204 }
soramimi 0:bd865e5a3df3 205 sampler.output_done();
soramimi 0:bd865e5a3df3 206
soramimi 0:bd865e5a3df3 207 __disable_irq();
soramimi 0:bd865e5a3df3 208 int i = hostlist.size();
soramimi 0:bd865e5a3df3 209 while (i > 0) {
soramimi 0:bd865e5a3df3 210 i--;
soramimi 0:bd865e5a3df3 211 hostlist[i].timer++;
soramimi 0:bd865e5a3df3 212 if (hostlist[i].timer > 125) {
soramimi 0:bd865e5a3df3 213 hostlist.erase(hostlist.begin() + i);
soramimi 0:bd865e5a3df3 214 }
soramimi 0:bd865e5a3df3 215 }
soramimi 0:bd865e5a3df3 216 __enable_irq();
soramimi 0:bd865e5a3df3 217
soramimi 0:bd865e5a3df3 218 led1_timer++;
soramimi 0:bd865e5a3df3 219 if (led1_timer >= 125) {
soramimi 0:bd865e5a3df3 220 led1 = !led1;
soramimi 0:bd865e5a3df3 221 led1_timer = 0;
soramimi 0:bd865e5a3df3 222 }
soramimi 0:bd865e5a3df3 223 }
soramimi 0:bd865e5a3df3 224 }
soramimi 0:bd865e5a3df3 225
soramimi 0:bd865e5a3df3 226 return 0;
soramimi 0:bd865e5a3df3 227 }