streaming server for AM/FM radio via UDP connection.
Dependencies: mbed EthernetNetIf
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 }
Generated on Fri Jul 15 2022 13:48:29 by 1.7.2