streaming server for AM/FM radio via UDP connection.

Dependencies:   mbed EthernetNetIf

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers RadioServer.cpp Source File

RadioServer.cpp

00001 #include "mbed.h"
00002 #include "EthernetNetIf.h"
00003 #include "UDPSocket.h"
00004 #include "crc32.h"
00005 #include "ns9542.h"
00006 #include <vector>
00007 
00008 DigitalOut led1(LED1);
00009 DigitalOut led2(LED2);
00010 
00011 Ticker ticker;
00012 
00013 SPI spi(p5, p6, p7); // mosi, miso, sclk
00014 DigitalOut spi_cs(p8);
00015 
00016 EthernetNetIf eth(IpAddr(192,168,0,77), //IP Address
00017                   IpAddr(255,255,255,0), //Network Mask
00018                   IpAddr(192,168,0,1), //Gateway
00019                   IpAddr(192,168,0,1)  //DNS
00020                  );
00021 
00022 UDPSocket udpsocket;
00023 
00024 unsigned short sample_l;
00025 unsigned short sample_r;
00026 
00027 unsigned short sample_left()
00028 {
00029     spi_cs = 0;
00030     int v = spi.write(0x6800) & 0x03ff;
00031     spi_cs = 1;
00032     return (v << 6) | (v >> 4);
00033 }
00034 
00035 unsigned short sample_right()
00036 {
00037     spi_cs = 0;
00038     int v = spi.write(0x7800) & 0x03ff;
00039     spi_cs = 1;
00040     return (v << 6) | (v >> 4);
00041 }
00042 
00043 struct host_info_t {
00044     Host host;
00045     int timer;
00046     host_info_t()
00047     {
00048     }
00049     host_info_t(Host h)
00050         : host(h)
00051         , timer(0)
00052     {
00053     }
00054 };
00055 
00056 std::vector<host_info_t> hostlist;
00057 
00058 void on_udp_socket_event(UDPSocketEvent e)
00059 {
00060     if (e == UDPSOCKET_READABLE) {
00061         char buf[64] = {0};
00062         Host host;
00063         while (int len = udpsocket.recvfrom(buf, 63, &host)) {
00064             if (len <= 0) {
00065                 break;
00066             }
00067             if (len == 4 && memcmp(buf, "wave", len) == 0) {
00068                 __disable_irq();
00069                 size_t i, n;
00070                 n = hostlist.size();
00071                 for (i = 0; i < n; i++) {
00072                     if (memcmp(&host, &hostlist[i].host, sizeof(Host)) == 0) {
00073                         hostlist[i].timer = 0;
00074                         break;
00075                     }
00076                 }
00077                 if (i == n) {
00078                     hostlist.push_back(host_info_t(host));
00079                 }
00080                 __enable_irq();
00081                 continue;
00082             }
00083             if (len > 2 && memcmp(buf, "am", 2) == 0) {
00084                 buf[len] = 0;
00085                 int f = atoi(buf + 2);
00086                 ns9542_tune_am9(f);
00087                 continue;
00088             }
00089             if (len > 2 && memcmp(buf, "fm", 2) == 0) {
00090                 buf[len] = 0;
00091                 int f = atoi(buf + 2);
00092                 ns9542_tune_fm(f);
00093                 continue;
00094             }
00095             if (len == 4 && memcmp(buf, "mute", len) == 0) {
00096                 ns9542_mute(true);
00097                 continue;
00098             }
00099         }
00100     }
00101 }
00102 
00103 static inline void store(unsigned short *p, unsigned short n)
00104 {
00105     ((unsigned char *)p)[0] = n >> 8;
00106     ((unsigned char *)p)[1] = n & 0xff;
00107 }
00108 
00109 static inline void store(unsigned long *p, unsigned long n)
00110 {
00111     ((unsigned char *)p)[0] = n >> 24;
00112     ((unsigned char *)p)[1] = n >> 16;
00113     ((unsigned char *)p)[2] = n >> 8;
00114     ((unsigned char *)p)[3] = n & 0xff;
00115 }
00116 
00117 class Sampler {
00118 private:
00119     unsigned long buffer_a[257];
00120     unsigned long buffer_b[257];
00121     unsigned long *in_ptr;
00122     unsigned long *out_ptr;
00123     bool output_available;
00124     unsigned long crc;
00125     int offset;
00126 public:
00127     Sampler()
00128     {
00129         in_ptr = buffer_a;
00130         out_ptr = buffer_b;
00131         output_available = false;
00132         offset = 0;
00133         crc = 0;
00134     }
00135 
00136     void on_tick()
00137     {
00138         if (output_available) {
00139             return;
00140         }
00141         unsigned short *p = (unsigned short *)in_ptr;
00142         p += offset * 2;
00143         store(p + 0, sample_l);
00144         store(p + 1, sample_r);
00145         crc = crc32(crc, (unsigned char *)p, 4);
00146         offset++;
00147         if (offset >= 256) {
00148             std::swap(in_ptr, out_ptr);
00149             store(&out_ptr[256], crc);
00150             output_available = true;
00151             offset = 0;
00152             crc = 0;
00153         }
00154     }
00155     
00156     char const *output_buffer()
00157     {
00158         return output_available ? (char const *)out_ptr : 0;
00159     }
00160 
00161     void output_done()
00162     {
00163         output_available = false;
00164     }
00165 };
00166 
00167 Sampler sampler;
00168 
00169 void on_tick()
00170 {
00171     sampler.on_tick();
00172 }
00173 
00174 int main()
00175 {
00176     spi_cs = 1;
00177     spi.format(16, 0);
00178     spi.frequency(3000000);
00179 
00180     ns9542_init();
00181 
00182     eth.setup();
00183     Host host(IpAddr(), 2000);
00184     udpsocket.bind(host);
00185     udpsocket.setOnEvent(&on_udp_socket_event);
00186 
00187     led1 = 0;
00188     ticker.attach(&on_tick, 1.0 / 32000);
00189 
00190     int led1_timer = 0;
00191 
00192     while (1) {
00193         sample_l = sample_left();
00194         sample_r = sample_right();
00195 
00196         Net::poll();
00197 
00198         char const *p = sampler.output_buffer();
00199         if (p) {
00200             for (std::vector<host_info_t>::iterator it = hostlist.begin(); it != hostlist.end(); it++) {
00201                 udpsocket.sendto(p, 1028, (Host *)&it->host);
00202             }
00203             sampler.output_done();
00204 
00205             __disable_irq();
00206             int i = hostlist.size();
00207             while (i > 0) {
00208                 i--;
00209                 hostlist[i].timer++;
00210                 if (hostlist[i].timer > 125) {
00211                     hostlist.erase(hostlist.begin() + i);
00212                 }
00213             }
00214             __enable_irq();
00215 
00216             led1_timer++;
00217             if (led1_timer >= 125) {
00218                 led1 = !led1;
00219                 led1_timer = 0;
00220             }
00221         }
00222     }
00223 
00224     return 0;
00225 }