streaming server for AM/FM radio via UDP connection.
Dependencies: mbed EthernetNetIf
RadioServer.cpp
- Committer:
- soramimi
- Date:
- 2011-02-28
- Revision:
- 0:bd865e5a3df3
- Child:
- 1:3357273c97f8
File content as of revision 0:bd865e5a3df3:
#include "mbed.h" #include "EthernetNetIf.h" #include "UDPSocket.h" #include "TextLCD.h" #include "crc32.h" #include "ns9542.h" #include <vector> DigitalOut led1(LED1); DigitalOut led2(LED2); TextLCD lcd(p21, p22, p23, p24, p25, p26); Ticker ticker; SPI spi(p5, p6, p7); // mosi, miso, sclk DigitalOut spi_cs(p8); EthernetNetIf eth(IpAddr(192,168,0,100), //IP Address IpAddr(255,255,255,0), //Network Mask IpAddr(192,168,0,1), //Gateway IpAddr(192,168,0,1) //DNS ); UDPSocket udpsocket; unsigned short sample_l; unsigned short sample_r; unsigned short sample_left() { spi_cs = 0; int v = spi.write(0x6800) & 0x03ff; spi_cs = 1; return (v << 6) | (v >> 4); } unsigned short sample_right() { spi_cs = 0; int v = spi.write(0x7800) & 0x03ff; spi_cs = 1; return (v << 6) | (v >> 4); } struct host_info_t { Host host; int timer; host_info_t() { } host_info_t(Host h) : host(h) , timer(0) { } }; std::vector<host_info_t> hostlist; void on_udp_socket_event(UDPSocketEvent e) { if (e == UDPSOCKET_READABLE) { char buf[64] = {0}; Host host; while (int len = udpsocket.recvfrom(buf, 63, &host)) { if (len <= 0) { break; } if (len == 7 && memcmp(buf, "request", len) == 0) { __disable_irq(); size_t i, n; n = hostlist.size(); for (i = 0; i < n; i++) { if (memcmp(&host, &hostlist[i].host, sizeof(Host)) == 0) { hostlist[i].timer = 0; break; } } if (i == n) { hostlist.push_back(host_info_t(host)); } __enable_irq(); continue; } if (len > 2 && memcmp(buf, "am", 2) == 0) { buf[len] = 0; int f = atoi(buf + 2); ns9542_tune_am9(f); continue; } if (len > 2 && memcmp(buf, "fm", 2) == 0) { buf[len] = 0; int f = atoi(buf + 2); ns9542_tune_fm(f); continue; } if (len > 4 && memcmp(buf, "mute", 4) == 0) { ns9542_mute(true); continue; } } } } static inline void store(unsigned short *p, unsigned short n) { ((unsigned char *)p)[0] = n >> 8; ((unsigned char *)p)[1] = n & 0xff; } static inline void store(unsigned long *p, unsigned long n) { ((unsigned char *)p)[0] = n >> 24; ((unsigned char *)p)[1] = n >> 16; ((unsigned char *)p)[2] = n >> 8; ((unsigned char *)p)[3] = n & 0xff; } class Sampler { private: unsigned long buffer_a[257]; unsigned long buffer_b[257]; unsigned long *in_ptr; unsigned long *out_ptr; bool output_available; unsigned long crc; int offset; public: Sampler() { in_ptr = buffer_a; out_ptr = buffer_b; output_available = false; offset = 0; crc = 0; } void on_tick() { if (output_available) { return; } unsigned short *p = (unsigned short *)in_ptr; p += offset * 2; store(p + 0, sample_l); store(p + 1, sample_r); crc = crc32(crc, (unsigned char *)p, 4); offset++; if (offset >= 256) { std::swap(in_ptr, out_ptr); store(&out_ptr[256], crc); output_available = true; offset = 0; crc = 0; } } char const *output_buffer() { return output_available ? (char const *)out_ptr : 0; } void output_done() { output_available = false; } }; Sampler sampler; void on_tick() { sampler.on_tick(); } int main() { spi_cs = 1; spi.format(16, 0); spi.frequency(3000000); ns9542_init(); eth.setup(); Host host(IpAddr(), 2000); udpsocket.bind(host); udpsocket.setOnEvent(&on_udp_socket_event); led1 = 0; ticker.attach(&on_tick, 1.0 / 32000); int led1_timer = 0; while (1) { sample_l = sample_left(); sample_r = sample_right(); Net::poll(); char const *p = sampler.output_buffer(); if (p) { for (std::vector<host_info_t>::iterator it = hostlist.begin(); it != hostlist.end(); it++) { udpsocket.sendto(p, 1028, (Host *)&it->host); } sampler.output_done(); __disable_irq(); int i = hostlist.size(); while (i > 0) { i--; hostlist[i].timer++; if (hostlist[i].timer > 125) { hostlist.erase(hostlist.begin() + i); } } __enable_irq(); led1_timer++; if (led1_timer >= 125) { led1 = !led1; led1_timer = 0; } } } return 0; }