rtl_airband.cpp 59 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619
  1. /*
  2. * RTLSDR AM/NFM demodulator, mixer, streamer and recorder
  3. *
  4. * Copyright (c) 2014 Wong Man Hang <microtony@gmail.com>
  5. * Copyright (c) 2015-2021 Tomasz Lemiech <szpajder@gmail.com>
  6. *
  7. * This program is free software: you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation, either version 3 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. * You should have received a copy of the GNU General Public License
  18. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  19. */
  20. #include "config.h"
  21. #if defined WITH_BCM_VC && !defined __arm__
  22. #error Broadcom VideoCore support can only be enabled on ARM builds
  23. #endif
  24. // From this point we may safely assume that WITH_BCM_VC implies __arm__
  25. #ifdef WITH_BCM_VC
  26. #include "hello_fft/gpu_fft.h"
  27. #include "hello_fft/mailbox.h"
  28. #endif /* WITH_BCM_VC */
  29. //#define GPIOX
  30. #include <fcntl.h>
  31. #include <lame/lame.h>
  32. #include <ogg/ogg.h>
  33. #include <pthread.h>
  34. #include <shout/shout.h>
  35. #include <stdint.h> // uint8_t
  36. #include <sys/stat.h>
  37. #include <sys/time.h>
  38. #include <sys/types.h>
  39. #include <sys/wait.h>
  40. #include <syslog.h>
  41. #include <unistd.h>
  42. #include <vorbis/vorbisenc.h>
  43. #include <algorithm>
  44. #include <cassert>
  45. #include <cerrno>
  46. #include <cmath>
  47. #include <csignal>
  48. #include <cstdarg>
  49. #include <cstdio>
  50. #include <cstdlib>
  51. #include <cstring>
  52. #include <ctime>
  53. #include <iostream>
  54. #include <libconfig.h++>
  55. #include "input-common.h"
  56. #include "logging.h"
  57. #include "rtl_airband.h"
  58. #include "squelch.h"
  59. #include <semaphore.h>
  60. #ifdef WITH_PROFILING
  61. #include "gperftools/profiler.h"
  62. #endif /* WITH_PROFILING */
  63. #include <gpiod.h>
  64. /*#include <ncurses.h>*/
  65. #include <iomanip>
  66. #include <fstream>
  67. #include <string>
  68. #include <chrono>
  69. #include "mqtt/async_client.h"
  70. #include <ncurses.h>
  71. #include <curl/curl.h>
  72. #include <queue>
  73. #include <jsoncpp/json/json.h>
  74. #include <nlohmann/json.hpp>
  75. using namespace std;
  76. using namespace libconfig;
  77. struct gpiod_chip *chip;
  78. struct gpiod_line *led_squ;
  79. struct gpiod_line *led_vox;
  80. struct gpiod_line *led_control;
  81. struct gpiod_line *relay1;
  82. struct gpiod_line *relay2;
  83. #define MAX_BUFFERS 10
  84. #define GPIOX
  85. using json = nlohmann::json;
  86. sem_t mutex_lock_main_thread, mutex_unlock_main_thread;
  87. sem_t mutex_lock_main_thread_mqtt, mutex_unlock_main_thread_mqtt;
  88. pthread_mutex_t lock_data;
  89. pthread_mutex_t lock_mqtt_data;
  90. device_t* devices;
  91. mixer_t* mixers;
  92. long int start_time;
  93. long int stop_time;
  94. int bel_start_on_time = 0;
  95. int bel_open_time = 0;
  96. int bel_prolong_time = 0;
  97. float bel_wave_out_level = 0;
  98. float bel_wave_in_level = 0;
  99. int bel_blink_time = 0;
  100. bool mqtt_activate=false;
  101. char* bel_mqtt_server;
  102. char* bel_mqtt_client_id;
  103. char* bel_mqtt_user_id;
  104. char* bel_mqtt_password;
  105. int squelch_status = 0;
  106. int audio_status = 0;
  107. int status_data = 0;
  108. int status_data_old = 0;
  109. int device_count, mixer_count;
  110. static int devices_running = 0;
  111. int tui = 0; // do not display textual user interface
  112. int shout_metadata_delay = 3;
  113. volatile int do_exit = 0;
  114. bool use_localtime = false;
  115. bool multiple_demod_threads = false;
  116. bool multiple_output_threads = false;
  117. bool log_scan_activity = false;
  118. char* stats_filepath = NULL;
  119. size_t fft_size_log = DEFAULT_FFT_SIZE_LOG;
  120. size_t fft_size = 1 << fft_size_log;
  121. #ifdef NFM
  122. float alpha = exp(-1.0f / (WAVE_RATE * 2e-4));
  123. enum fm_demod_algo { FM_FAST_ATAN2, FM_QUADRI_DEMOD };
  124. enum fm_demod_algo fm_demod = FM_FAST_ATAN2;
  125. #endif /* NFM */
  126. #ifdef DEBUG
  127. char* debug_path;
  128. #endif /* DEBUG */
  129. void sighandler(int sig) {
  130. log(LOG_NOTICE, "Got signal %d, exiting\n", sig);
  131. do_exit = 1;
  132. }
  133. template <typename T>
  134. class TSQueue {
  135. private:
  136. // Underlying queue
  137. std::queue<T> m_queue;
  138. // mutex for thread synchronization
  139. std::mutex m_mutex;
  140. // Condition variable for signaling
  141. std::condition_variable m_cond;
  142. public:
  143. // Pushes an element to the queue
  144. void push(T item)
  145. {
  146. // Acquire lock
  147. std::unique_lock<std::mutex> lock(m_mutex);
  148. // Add item
  149. m_queue.push(item);
  150. // Notify one thread that
  151. // is waiting
  152. m_cond.notify_one();
  153. }
  154. // Pops an element off the queue
  155. T pop()
  156. {
  157. // acquire lock
  158. std::unique_lock<std::mutex> lock(m_mutex);
  159. // wait until queue is not empty
  160. m_cond.wait(lock,
  161. [this]() { return !m_queue.empty(); });
  162. // retrieve item
  163. T item = m_queue.front();
  164. m_queue.pop();
  165. // return item
  166. return item;
  167. }
  168. int size() { return m_queue.size(); }
  169. };
  170. TSQueue<mqtt_msg_t> mqtt_queue;
  171. void* controller_thread(void* params) {
  172. device_t* dev = (device_t*)params;
  173. int i = 0;
  174. int consecutive_squelch_off = 0;
  175. int new_centerfreq = 0;
  176. struct timeval tv;
  177. if (dev->channels[0].freq_count < 2)
  178. return 0;
  179. while (!do_exit) {
  180. SLEEP(200);
  181. if (dev->channels[0].axcindicate == NO_SIGNAL) {
  182. if (consecutive_squelch_off < 10) {
  183. consecutive_squelch_off++;
  184. } else {
  185. i++;
  186. i %= dev->channels[0].freq_count;
  187. dev->channels[0].freq_idx = i;
  188. new_centerfreq = dev->channels[0].freqlist[i].frequency + 20 * (double)(dev->input->sample_rate / fft_size);
  189. if (input_set_centerfreq(dev->input, new_centerfreq) < 0) {
  190. break;
  191. }
  192. }
  193. } else {
  194. if (consecutive_squelch_off == 10) {
  195. if (log_scan_activity)
  196. log(LOG_INFO, "Activity on %7.3f MHz\n", dev->channels[0].freqlist[i].frequency / 1000000.0);
  197. if (i != dev->last_frequency) {
  198. // squelch has just opened on a new frequency - we might need to update outputs' metadata
  199. gettimeofday(&tv, NULL);
  200. tag_queue_put(dev, i, tv);
  201. dev->last_frequency = i;
  202. }
  203. }
  204. consecutive_squelch_off = 0;
  205. }
  206. }
  207. return 0;
  208. }
  209. void multiply(float ar, float aj, float br, float bj, float* cr, float* cj) {
  210. *cr = ar * br - aj * bj;
  211. *cj = aj * br + ar * bj;
  212. }
  213. class PublisherCallback : public virtual mqtt::callback
  214. {
  215. public:
  216. void connection_lost(const std::string& cause) override
  217. {
  218. std::cout << "Connection lost: " << cause << std::endl;
  219. }
  220. void delivery_complete(mqtt::delivery_token_ptr token) override
  221. {
  222. token=token;
  223. std::cout << "Message delivered" << std::endl;
  224. }
  225. void message_arrived (mqtt::const_message_ptr msg) override
  226. {
  227. std::cout << "Message arrived: " << msg->get_payload_str() << std::endl;
  228. mqtt_activate=true;
  229. }
  230. };
  231. void* mqtt_control_thread(void*){
  232. string address = bel_mqtt_server,
  233. clientID = bel_mqtt_client_id,
  234. username = bel_mqtt_user_id,
  235. password = bel_mqtt_password;
  236. const std::string TOPIC1("device/"+username+"/sq");
  237. const std::string TOPIC2("device/"+username+"/light");
  238. const int QOS = 1;
  239. //const int TIMEOUT = 10000;
  240. mqtt::async_client client(address, clientID,mqtt::create_options(MQTTVERSION_5));
  241. mqtt::connect_options connOpts;
  242. mqtt::ssl_options ssl_options;
  243. connOpts.set_keep_alive_interval(20);
  244. connOpts.set_clean_session(true);
  245. connOpts.set_user_name(username);
  246. connOpts.set_password(password);
  247. connOpts.set_ssl(ssl_options);
  248. connOpts.set_automatic_reconnect(10, 40);
  249. try
  250. {
  251. PublisherCallback callback;
  252. client.set_callback(callback);
  253. mqtt::token_ptr connectionToken = client.connect(connOpts);
  254. connectionToken->wait();
  255. mqtt::token_ptr subToken = client.subscribe(TOPIC2, QOS);
  256. subToken->wait();
  257. while (true)
  258. {
  259. mqtt_msg_t temp_mess;
  260. //printf("Size %i\n",mqtt_queue.size());
  261. temp_mess=mqtt_queue.pop();
  262. Json::Value event;
  263. event["type"]=temp_mess.type;
  264. if (temp_mess.type==1){
  265. event["sq"]=temp_mess.sq;
  266. event["freq"]=temp_mess.freq;
  267. event["name"]=temp_mess.name;
  268. event["mountpoint"]=temp_mess.mountpoint;
  269. }
  270. if (temp_mess.type==2){
  271. event["bel_status"]=temp_mess.bel_status;
  272. }
  273. if (temp_mess.type==2){
  274. event["type"]=temp_mess.type;
  275. event["status"]="connect";
  276. }
  277. Json::StreamWriterBuilder builder;
  278. if (client.is_connected()){
  279. mqtt::message_ptr pubMessage = mqtt::make_message(TOPIC1,Json::writeString(builder, event), QOS, false);
  280. client.publish(pubMessage)->wait();
  281. }
  282. }
  283. mqtt::token_ptr disconnectionToken = client.disconnect();
  284. disconnectionToken->wait();
  285. }
  286. catch (const mqtt::exception& ex)
  287. {
  288. std::cerr << "MQTT Exception: " << ex.what() << std::endl;
  289. return 0;
  290. }
  291. printf("HEJ3");
  292. return 0;
  293. }
  294. void* belysning_control_thread(void*){
  295. struct timespec ts;
  296. struct timeval tv;
  297. long int sq_start_time=0;
  298. long int sq_stop_time=0;
  299. bool sq_status = false;
  300. long int audio_start_time=0;
  301. bool active=false;
  302. char *str ;
  303. memset(&str, 0, sizeof(str));
  304. mqtt_msg_t mqtt_msg;
  305. mqtt_msg.sq = 0;
  306. mqtt_msg.freq = 0;
  307. mqtt_msg.name = str;
  308. mqtt_msg.audio = 0;
  309. mqtt_msg.mountpoint = str;
  310. mqtt_msg.bel_status = -1;
  311. mqtt_msg.type=2;
  312. int status_data_temp=0;
  313. gettimeofday(&tv, 0);
  314. start_time=tv.tv_sec;
  315. stop_time=tv.tv_sec+1;
  316. while (!do_exit) {
  317. status_data=status_data;
  318. int sem_try=0;
  319. bool activate=false;
  320. bool prolong=false;
  321. if (clock_gettime(CLOCK_REALTIME, &ts) == -1 && tui)
  322. printf("clock_gettime");
  323. ts.tv_sec +=1;
  324. sem_try = sem_timedwait(&mutex_lock_main_thread, &ts);
  325. if (sem_try == 0){
  326. status_data_temp=status_data;
  327. sem_post(&mutex_unlock_main_thread);
  328. if (sq_status == false && (status_data_temp & 1)){
  329. sq_start_time = tv.tv_sec;
  330. sq_status = true;
  331. }
  332. if (sq_status == true && !(status_data_temp & 1)){
  333. sq_stop_time = tv.tv_sec;
  334. sq_status = false;
  335. }
  336. //printf("ST %u, %u ",(status_data & 1),(status_data >> 1));
  337. if ( (status_data_temp >> 1) ){
  338. audio_start_time = tv.tv_sec;
  339. }
  340. prolong = true;
  341. }
  342. if (sq_status && sq_start_time < tv.tv_sec){
  343. prolong = true;
  344. }else{
  345. prolong = false;
  346. }
  347. //printf("DATA %u, %ld, %ld, %ld %u %ld\n",sq_status,sq_start_time,audio_start_time,tv.tv_sec,prolong,stop_time);
  348. //Check if we should start
  349. if (sq_status == true && sq_start_time+bel_open_time < tv.tv_sec && audio_start_time+bel_open_time < tv.tv_sec){
  350. sq_start_time=sq_start_time;
  351. sq_stop_time=sq_stop_time;
  352. activate=true;
  353. }
  354. gettimeofday(&tv, 0);
  355. //First time activation
  356. if ((active==false && activate==true) || mqtt_activate){
  357. start_time=tv.tv_sec;
  358. stop_time=tv.tv_sec+bel_start_on_time;
  359. mqtt_activate=false;
  360. active=true;
  361. mqtt_msg.bel_status = 1;
  362. mqtt_queue.push(mqtt_msg);
  363. if (tui)
  364. printf("Start\n");
  365. }
  366. // Prolong
  367. if (active==true && prolong==true){
  368. if (tv.tv_sec+bel_prolong_time >= stop_time){
  369. stop_time=tv.tv_sec+bel_prolong_time;
  370. if (tui)
  371. printf("Prolong %u\n",bel_prolong_time);
  372. mqtt_msg.bel_status = 2;
  373. mqtt_queue.push(mqtt_msg);
  374. prolong = false;
  375. }
  376. }
  377. if (stop_time<=tv.tv_sec && active){
  378. active=false;
  379. start_time=start_time;
  380. mqtt_msg.bel_status = 0;
  381. mqtt_queue.push(mqtt_msg);
  382. if (tui)
  383. printf("Stop\n");
  384. }
  385. #ifdef GPIOX
  386. if (active)
  387. if ((stop_time<tv.tv_sec+bel_blink_time) && tv.tv_sec % 2 && bel_blink_time ){
  388. gpiod_line_set_value(led_control, 0);
  389. gpiod_line_set_value(relay1, 1);
  390. gpiod_line_set_value(relay2, 1);
  391. }else{
  392. gpiod_line_set_value(led_control, 1);
  393. gpiod_line_set_value(relay1, 0);
  394. gpiod_line_set_value(relay2, 0);
  395. }
  396. else{
  397. gpiod_line_set_value(led_control, 0);
  398. gpiod_line_set_value(relay1, 1);
  399. gpiod_line_set_value(relay2, 1);
  400. }
  401. #endif
  402. }
  403. return 0;
  404. }
  405. #ifdef NFM
  406. float fast_atan2(float y, float x) {
  407. float yabs, angle;
  408. float pi4 = M_PI_4, pi34 = 3 * M_PI_4;
  409. if (x == 0.0f && y == 0.0f) {
  410. return 0;
  411. }
  412. yabs = y;
  413. if (yabs < 0.0f) {
  414. yabs = -yabs;
  415. }
  416. if (x >= 0.0f) {
  417. angle = pi4 - pi4 * (x - yabs) / (x + yabs);
  418. } else {
  419. angle = pi34 - pi4 * (x + yabs) / (yabs - x);
  420. }
  421. if (y < 0.0f) {
  422. return -angle;
  423. }
  424. return angle;
  425. }
  426. float polar_disc_fast(float ar, float aj, float br, float bj) {
  427. float cr, cj;
  428. multiply(ar, aj, br, -bj, &cr, &cj);
  429. return (float)(fast_atan2(cj, cr) * M_1_PI);
  430. }
  431. float fm_quadri_demod(float ar, float aj, float br, float bj) {
  432. return (float)((br * aj - ar * bj) / (ar * ar + aj * aj + 1.0f) * M_1_PI);
  433. }
  434. #endif /* NFM */
  435. class AFC {
  436. const status _prev_axcindicate;
  437. #ifdef WITH_BCM_VC
  438. float square(const GPU_FFT_COMPLEX* fft_results, size_t index) {
  439. return fft_results[index].re * fft_results[index].re + fft_results[index].im * fft_results[index].im;
  440. }
  441. #else
  442. float square(const fftwf_complex* fft_results, size_t index) {
  443. return fft_results[index][0] * fft_results[index][0] + fft_results[index][1] * fft_results[index][1];
  444. }
  445. #endif /* WITH_BCM_VC */
  446. template <class FFT_RESULTS, int STEP>
  447. size_t check(const FFT_RESULTS* fft_results, const size_t base, const float base_value, unsigned char afc) {
  448. float threshold = 0;
  449. size_t bin;
  450. for (bin = base;; bin += STEP) {
  451. if (STEP < 0) {
  452. if (bin < -STEP)
  453. break;
  454. } else if ((size_t)(bin + STEP) >= fft_size)
  455. break;
  456. const float value = square(fft_results, (size_t)(bin + STEP));
  457. if (value <= base_value)
  458. break;
  459. if (base == (size_t)bin) {
  460. threshold = (value - base_value) / (float)afc;
  461. } else {
  462. if ((value - base_value) < threshold)
  463. break;
  464. threshold += threshold / 10.0;
  465. }
  466. }
  467. return bin;
  468. }
  469. public:
  470. AFC(device_t* dev, int index) : _prev_axcindicate(dev->channels[index].axcindicate) {}
  471. template <class FFT_RESULTS>
  472. void finalize(device_t* dev, int index, const FFT_RESULTS* fft_results) {
  473. channel_t* channel = &dev->channels[index];
  474. if (channel->afc == 0)
  475. return;
  476. const char axcindicate = channel->axcindicate;
  477. if (axcindicate != NO_SIGNAL && _prev_axcindicate == NO_SIGNAL) {
  478. const size_t base = dev->base_bins[index];
  479. const float base_value = square(fft_results, base);
  480. size_t bin = check<FFT_RESULTS, -1>(fft_results, base, base_value, channel->afc);
  481. if (bin == base)
  482. bin = check<FFT_RESULTS, 1>(fft_results, base, base_value, channel->afc);
  483. if (dev->bins[index] != bin) {
  484. #ifdef AFC_LOGGING
  485. log(LOG_INFO, "AFC device=%d channel=%d: base=%zu prev=%zu now=%zu\n", dev->device, index, base, dev->bins[index], bin);
  486. #endif /* AFC_LOGGING */
  487. dev->bins[index] = bin;
  488. if (bin > base)
  489. channel->axcindicate = AFC_UP;
  490. else if (bin < base)
  491. channel->axcindicate = AFC_DOWN;
  492. }
  493. } else if (axcindicate == NO_SIGNAL && _prev_axcindicate != NO_SIGNAL)
  494. dev->bins[index] = dev->base_bins[index];
  495. }
  496. };
  497. void init_demod(demod_params_t* params, Signal* signal, int device_start, int device_end) {
  498. assert(params != NULL);
  499. assert(signal != NULL);
  500. params->mp3_signal = signal;
  501. params->device_start = device_start;
  502. params->device_end = device_end;
  503. #ifndef WITH_BCM_VC
  504. params->fftin = fftwf_alloc_complex(fft_size);
  505. params->fftout = fftwf_alloc_complex(fft_size);
  506. params->fft = fftwf_plan_dft_1d(fft_size, params->fftin, params->fftout, FFTW_FORWARD, FFTW_MEASURE);
  507. #endif /* WITH_BCM_VC */
  508. }
  509. void init_output(output_params_t* params, int device_start, int device_end, int mixer_start, int mixer_end) {
  510. assert(params != NULL);
  511. params->mp3_signal = new Signal;
  512. params->device_start = device_start;
  513. params->device_end = device_end;
  514. params->mixer_start = mixer_start;
  515. params->mixer_end = mixer_end;
  516. }
  517. int next_device(demod_params_t* params, int current) {
  518. current++;
  519. if (current < params->device_end) {
  520. return current;
  521. }
  522. return params->device_start;
  523. }
  524. void* demodulate(void* params) {
  525. assert(params != NULL);
  526. demod_params_t* demod_params = (demod_params_t*)params;
  527. debug_print("Starting demod thread, devices %d:%d, signal %p\n", demod_params->device_start, demod_params->device_end, demod_params->mp3_signal);
  528. // initialize fft engine
  529. #ifdef WITH_BCM_VC
  530. int mb = mbox_open();
  531. struct GPU_FFT* fft;
  532. int ret = gpu_fft_prepare(mb, fft_size_log, GPU_FFT_FWD, FFT_BATCH, &fft);
  533. switch (ret) {
  534. case -1:
  535. log(LOG_CRIT, "Unable to enable V3D. Please check your firmware is up to date.\n");
  536. error();
  537. break;
  538. case -2:
  539. log(LOG_CRIT, "log2_N=%d not supported. Try between 8 and 17.\n", fft_size_log);
  540. error();
  541. break;
  542. case -3:
  543. log(LOG_CRIT, "Out of memory. Try a smaller batch or increase GPU memory.\n");
  544. error();
  545. break;
  546. }
  547. #else
  548. fftwf_complex* fftin = demod_params->fftin;
  549. fftwf_complex* fftout = demod_params->fftout;
  550. #endif /* WITH_BCM_VC */
  551. float ALIGNED32 levels_u8[256], levels_s8[256];
  552. float* levels_ptr = NULL;
  553. for (int i = 0; i < 256; i++) {
  554. levels_u8[i] = (i - 127.5f) / 127.5f;
  555. }
  556. for (int16_t i = -127; i < 128; i++) {
  557. levels_s8[(uint8_t)i] = i / 128.0f;
  558. }
  559. // initialize fft window
  560. // blackman 7
  561. // the whole matrix is computed
  562. #ifdef WITH_BCM_VC
  563. float ALIGNED32 window[fft_size * 2];
  564. #else
  565. float ALIGNED32 window[fft_size];
  566. #endif /* WITH_BCM_VC */
  567. const double a0 = 0.27105140069342f;
  568. const double a1 = 0.43329793923448f;
  569. const double a2 = 0.21812299954311f;
  570. const double a3 = 0.06592544638803f;
  571. const double a4 = 0.01081174209837f;
  572. const double a5 = 0.00077658482522f;
  573. const double a6 = 0.00001388721735f;
  574. for (size_t i = 0; i < fft_size; i++) {
  575. double x = a0 - (a1 * cos((2.0 * M_PI * i) / (fft_size - 1))) + (a2 * cos((4.0 * M_PI * i) / (fft_size - 1))) - (a3 * cos((6.0 * M_PI * i) / (fft_size - 1))) +
  576. (a4 * cos((8.0 * M_PI * i) / (fft_size - 1))) - (a5 * cos((10.0 * M_PI * i) / (fft_size - 1))) + (a6 * cos((12.0 * M_PI * i) / (fft_size - 1)));
  577. #ifdef WITH_BCM_VC
  578. window[i * 2] = window[i * 2 + 1] = (float)x;
  579. #else
  580. window[i] = (float)x;
  581. #endif /* WITH_BCM_VC */
  582. }
  583. #ifdef DEBUG
  584. struct timeval ts, te;
  585. gettimeofday(&ts, NULL);
  586. #endif /* DEBUG */
  587. size_t available;
  588. int device_num = demod_params->device_start;
  589. while (true) {
  590. if (do_exit) {
  591. #ifdef WITH_BCM_VC
  592. log(LOG_INFO, "Freeing GPU memory\n");
  593. gpu_fft_release(fft);
  594. #endif /* WITH_BCM_VC */
  595. return NULL;
  596. }
  597. device_t* dev = devices + device_num;
  598. pthread_mutex_lock(&dev->input->buffer_lock);
  599. if (dev->input->bufe >= dev->input->bufs)
  600. available = dev->input->bufe - dev->input->bufs;
  601. else
  602. available = dev->input->buf_size - dev->input->bufs + dev->input->bufe;
  603. pthread_mutex_unlock(&dev->input->buffer_lock);
  604. if (devices_running == 0) {
  605. log(LOG_ERR, "All receivers failed, exiting\n");
  606. do_exit = 1;
  607. continue;
  608. }
  609. if (dev->input->state != INPUT_RUNNING) {
  610. if (dev->input->state == INPUT_FAILED) {
  611. dev->input->state = INPUT_DISABLED;
  612. disable_device_outputs(dev);
  613. devices_running--;
  614. }
  615. device_num = next_device(demod_params, device_num);
  616. continue;
  617. }
  618. // number of input bytes per output wave sample (x 2 for I and Q)
  619. size_t bps = 2 * dev->input->bytes_per_sample * (size_t)round((double)dev->input->sample_rate / (double)WAVE_RATE);
  620. if (available < bps * FFT_BATCH + fft_size * dev->input->bytes_per_sample * 2) {
  621. // move to next device
  622. device_num = next_device(demod_params, device_num);
  623. SLEEP(10);
  624. continue;
  625. }
  626. if (dev->input->sfmt == SFMT_S16) {
  627. float const scale = 1.0f / dev->input->fullscale;
  628. #ifdef WITH_BCM_VC
  629. struct GPU_FFT_COMPLEX* ptr = fft->in;
  630. for (size_t b = 0; b < FFT_BATCH; b++, ptr += fft->step) {
  631. short* buf2 = (short*)(dev->input->buffer + dev->input->bufs + b * bps);
  632. for (size_t i = 0; i < fft_size; i++, buf2 += 2) {
  633. ptr[i].re = scale * (float)buf2[0] * window[i * 2];
  634. ptr[i].im = scale * (float)buf2[1] * window[i * 2];
  635. }
  636. }
  637. #else
  638. short* buf2 = (short*)(dev->input->buffer + dev->input->bufs);
  639. for (size_t i = 0; i < fft_size; i++, buf2 += 2) {
  640. fftin[i][0] = scale * (float)buf2[0] * window[i];
  641. fftin[i][1] = scale * (float)buf2[1] * window[i];
  642. }
  643. #endif /* WITH_BCM_VC */
  644. } else if (dev->input->sfmt == SFMT_F32) {
  645. float const scale = 1.0f / dev->input->fullscale;
  646. #ifdef WITH_BCM_VC
  647. struct GPU_FFT_COMPLEX* ptr = fft->in;
  648. for (size_t b = 0; b < FFT_BATCH; b++, ptr += fft->step) {
  649. float* buf2 = (float*)(dev->input->buffer + dev->input->bufs + b * bps);
  650. for (size_t i = 0; i < fft_size; i++, buf2 += 2) {
  651. ptr[i].re = scale * buf2[0] * window[i * 2];
  652. ptr[i].im = scale * buf2[1] * window[i * 2];
  653. }
  654. }
  655. #else // WITH_BCM_VC
  656. float* buf2 = (float*)(dev->input->buffer + dev->input->bufs);
  657. for (size_t i = 0; i < fft_size; i++, buf2 += 2) {
  658. fftin[i][0] = scale * buf2[0] * window[i];
  659. fftin[i][1] = scale * buf2[1] * window[i];
  660. }
  661. #endif /* WITH_BCM_VC */
  662. } else { // S8 or U8
  663. levels_ptr = (dev->input->sfmt == SFMT_U8 ? levels_u8 : levels_s8);
  664. #ifdef WITH_BCM_VC
  665. sample_fft_arg sfa = {fft_size / 4, fft->in};
  666. for (size_t i = 0; i < FFT_BATCH; i++) {
  667. samplefft(&sfa, dev->input->buffer + dev->input->bufs + i * bps, window, levels_ptr);
  668. sfa.dest += fft->step;
  669. }
  670. #else
  671. unsigned char* buf2 = dev->input->buffer + dev->input->bufs;
  672. for (size_t i = 0; i < fft_size; i++, buf2 += 2) {
  673. fftin[i][0] = levels_ptr[buf2[0]] * window[i];
  674. fftin[i][1] = levels_ptr[buf2[1]] * window[i];
  675. }
  676. #endif /* WITH_BCM_VC */
  677. }
  678. #ifdef WITH_BCM_VC
  679. gpu_fft_execute(fft);
  680. #else
  681. fftwf_execute(demod_params->fft);
  682. #endif /* WITH_BCM_VC */
  683. #ifdef WITH_BCM_VC
  684. for (int i = 0; i < dev->channel_count; i++) {
  685. float* wavein = dev->channels[i].wavein + dev->waveend;
  686. __builtin_prefetch(wavein, 1);
  687. const int bin = dev->bins[i];
  688. const GPU_FFT_COMPLEX* fftout = fft->out + bin;
  689. for (int j = 0; j < FFT_BATCH; j++, ++wavein, fftout += fft->step)
  690. *wavein = sqrtf(fftout->im * fftout->im + fftout->re * fftout->re);
  691. }
  692. for (int j = 0; j < dev->channel_count; j++) {
  693. if (dev->channels[j].needs_raw_iq) {
  694. struct GPU_FFT_COMPLEX* ptr = fft->out;
  695. for (int job = 0; job < FFT_BATCH; job++) {
  696. dev->channels[j].iq_in[2 * (dev->waveend + job)] = ptr[dev->bins[j]].re;
  697. dev->channels[j].iq_in[2 * (dev->waveend + job) + 1] = ptr[dev->bins[j]].im;
  698. ptr += fft->step;
  699. }
  700. }
  701. }
  702. #else
  703. for (int j = 0; j < dev->channel_count; j++) {
  704. dev->channels[j].wavein[dev->waveend] = sqrtf(fftout[dev->bins[j]][0] * fftout[dev->bins[j]][0] + fftout[dev->bins[j]][1] * fftout[dev->bins[j]][1]);
  705. if (dev->channels[j].needs_raw_iq) {
  706. dev->channels[j].iq_in[2 * dev->waveend] = fftout[dev->bins[j]][0];
  707. dev->channels[j].iq_in[2 * dev->waveend + 1] = fftout[dev->bins[j]][1];
  708. }
  709. }
  710. #endif /* WITH_BCM_VC */
  711. dev->waveend += FFT_BATCH;
  712. if (dev->waveend >= WAVE_BATCH + AGC_EXTRA) {
  713. for (int i = 0; i < dev->channel_count; i++) {
  714. AFC afc(dev, i);
  715. channel_t* channel = dev->channels + i;
  716. freq_t* fparms = channel->freqlist + channel->freq_idx;
  717. // set to NO_SIGNAL, will be updated to SIGNAL based on squelch below
  718. channel->axcindicate = NO_SIGNAL;
  719. for (int j = AGC_EXTRA; j < WAVE_BATCH + AGC_EXTRA; j++) {
  720. float& real = channel->iq_in[2 * (j - AGC_EXTRA)];
  721. float& imag = channel->iq_in[2 * (j - AGC_EXTRA) + 1];
  722. fparms->squelch.process_raw_sample(channel->wavein[j]);
  723. // If squelch is open / opening and using I/Q, then cleanup the signal and possibly update squelch.
  724. if (fparms->squelch.should_filter_sample() && channel->needs_raw_iq) {
  725. // remove phase rotation introduced by FFT sliding window
  726. float swf, cwf, re_tmp, im_tmp;
  727. sincosf_lut(channel->dm_phi, &swf, &cwf);
  728. multiply(real, imag, cwf, -swf, &re_tmp, &im_tmp);
  729. channel->dm_phi += channel->dm_dphi;
  730. channel->dm_phi &= 0xffffff;
  731. // apply lowpass filter, will be a no-op if not configured
  732. fparms->lowpass_filter.apply(re_tmp, im_tmp);
  733. // update I/Q and wave
  734. real = re_tmp;
  735. imag = im_tmp;
  736. channel->wavein[j] = sqrt(real * real + imag * imag);
  737. // update squelch post-cleanup
  738. if (fparms->lowpass_filter.enabled()) {
  739. fparms->squelch.process_filtered_sample(channel->wavein[j]);
  740. }
  741. }
  742. if (fparms->modulation == MOD_AM) {
  743. // if squelch is just opening then bootstrip agcavgfast with prior values of wavein
  744. if (fparms->squelch.first_open_sample()) {
  745. for (int k = j - AGC_EXTRA; k < j; k++) {
  746. if (channel->wavein[k] >= fparms->squelch.squelch_level()) {
  747. fparms->agcavgfast = fparms->agcavgfast * 0.9f + channel->wavein[k] * 0.1f;
  748. }
  749. }
  750. }
  751. // if squelch is just closing then fade out the prior samples of waveout
  752. else if (fparms->squelch.last_open_sample()) {
  753. for (int k = j - AGC_EXTRA + 1; k < j; k++) {
  754. channel->waveout[k] = channel->waveout[k - 1] * 0.94f;
  755. }
  756. }
  757. }
  758. float& waveout = channel->waveout[j];
  759. // If squelch sees power then do modulation-specific processing
  760. if (fparms->squelch.should_process_audio()) {
  761. if (fparms->modulation == MOD_AM) {
  762. if (channel->wavein[j] > fparms->squelch.squelch_level()) {
  763. fparms->agcavgfast = fparms->agcavgfast * 0.995f + channel->wavein[j] * 0.005f;
  764. }
  765. waveout = (channel->wavein[j - AGC_EXTRA] - fparms->agcavgfast) / (fparms->agcavgfast * 1.5f);
  766. if (abs(waveout) > 0.8f) {
  767. waveout *= 0.85f;
  768. fparms->agcavgfast *= 1.15f;
  769. }
  770. if ((abs(waveout)>bel_wave_out_level && channel->wavein[j]>bel_wave_in_level) ){
  771. #ifdef GPIOX
  772. gpiod_line_set_value(led_vox, 1);
  773. #endif
  774. audio_status=1;
  775. }else{
  776. #ifdef GPIOX
  777. gpiod_line_set_value(led_vox, 0);
  778. #endif
  779. audio_status=0;
  780. }
  781. squelch_status = channel->freqlist[channel->freq_idx].oldstatus & 1;
  782. int temp_status = squelch_status + (audio_status << 1);
  783. if (channel->freqlist[channel->freq_idx].oldstatus !=temp_status && (fparms->banbel)){
  784. pthread_mutex_lock(&lock_data);
  785. //fprintf(stderr,"HEJ %i,%i,%f,%f\n",channel->freqlist[channel->freq_idx].oldstatus ,temp_status,abs(waveout),channel->wavein[j]);
  786. status_data = temp_status;
  787. if (sem_post (&mutex_lock_main_thread) == -1) {
  788. perror ("sem_post: mutex_lock_main_thread"); exit (1);
  789. }
  790. if (sem_wait(&mutex_unlock_main_thread) == -1){
  791. perror ("sem_post: mutex_unlock_main_thread"); exit (1);
  792. }
  793. //channel->freqlist[channel->freq_idx].oldstatus = temp_status;;
  794. pthread_mutex_unlock(&lock_data);
  795. }
  796. }
  797. #ifdef NFM
  798. else if (fparms->modulation == MOD_NFM) {
  799. // FM demod
  800. if (fm_demod == FM_FAST_ATAN2) {
  801. waveout = polar_disc_fast(real, imag, channel->pr, channel->pj);
  802. } else if (fm_demod == FM_QUADRI_DEMOD) {
  803. waveout = fm_quadri_demod(real, imag, channel->pr, channel->pj);
  804. }
  805. channel->pr = real;
  806. channel->pj = imag;
  807. // de-emphasis IIR + DC blocking
  808. fparms->agcavgfast = fparms->agcavgfast * 0.995f + waveout * 0.005f;
  809. waveout -= fparms->agcavgfast;
  810. waveout = waveout * (1.0f - channel->alpha) + channel->prev_waveout * channel->alpha;
  811. // save off waveout before notch and ampfactor
  812. channel->prev_waveout = waveout;
  813. }
  814. #endif /* NFM */
  815. // process audio sample for CTCSS, will be no-op if not configured
  816. fparms->squelch.process_audio_sample(waveout);
  817. }
  818. // If squelch is still open then save samples to output
  819. if (fparms->squelch.is_open()) {
  820. // apply the notch filter, will be a no-op if not configured
  821. fparms->notch_filter.apply(waveout);
  822. // apply the ampfactor
  823. waveout *= fparms->ampfactor;
  824. // make sure the value is between +/- 1 (requirement for libmp3lame)
  825. if (isnan(waveout)) {
  826. waveout = 0.0;
  827. } else if (waveout > 1.0) {
  828. waveout = 1.0;
  829. } else if (waveout < -1.0) {
  830. waveout = -1.0;
  831. }
  832. channel->axcindicate = SIGNAL;
  833. if (channel->has_iq_outputs) {
  834. channel->iq_out[2 * (j - AGC_EXTRA)] = real;
  835. channel->iq_out[2 * (j - AGC_EXTRA) + 1] = imag;
  836. }
  837. // Squelch is closed
  838. } else {
  839. waveout = 0;
  840. if (channel->has_iq_outputs) {
  841. channel->iq_out[2 * (j - AGC_EXTRA)] = 0;
  842. channel->iq_out[2 * (j - AGC_EXTRA) + 1] = 0;
  843. }
  844. }
  845. }
  846. memmove(channel->wavein, channel->wavein + WAVE_BATCH, (dev->waveend - WAVE_BATCH) * sizeof(float));
  847. if (channel->needs_raw_iq) {
  848. memmove(channel->iq_in, channel->iq_in + 2 * WAVE_BATCH, (dev->waveend - WAVE_BATCH) * sizeof(float) * 2);
  849. }
  850. #ifdef WITH_BCM_VC
  851. afc.finalize(dev, i, fft->out);
  852. #else
  853. afc.finalize(dev, i, demod_params->fftout);
  854. #endif /* WITH_BCM_VC */
  855. if (tui || 1==1) {
  856. char symbol = fparms->squelch.signal_outside_filter() ? '~' : (char)channel->axcindicate;
  857. if (dev->mode == R_SCAN) {
  858. //GOTOXY(0, device_num * 17 + dev->row + 3);
  859. //printf("%4.0f/%3.0f%c %7.3f ", level_to_dBFS(fparms->squelch.signal_level()), level_to_dBFS(fparms->squelch.noise_level()), symbol,
  860. // (dev->channels[0].freqlist[channel->freq_idx].frequency / 1000000.0));
  861. } else {
  862. //GOTOXY(i * 10, device_num * 17 + dev->row + 3);
  863. //printf("%4.0f/%3.0f%c ", level_to_dBFS(fparms->squelch.signal_level()), level_to_dBFS(fparms->squelch.noise_level()), symbol);
  864. }
  865. //BANBEL
  866. if (symbol=='*'){
  867. #ifdef GPIOX
  868. gpiod_line_set_value(led_squ, 1);
  869. #endif
  870. squelch_status = 1;
  871. }else{
  872. #ifdef GPIOX
  873. gpiod_line_set_value(led_squ, 0);
  874. #endif
  875. squelch_status = 0;
  876. }
  877. int temp_status = squelch_status + (audio_status << 1);
  878. if (channel->freqlist[channel->freq_idx].oldstatus != temp_status){
  879. //fprintf(stderr,"BABEL %i %i\n",fparms->banbel,temp_status);
  880. if (fparms->banbel){
  881. pthread_mutex_lock(&lock_data);
  882. status_data = temp_status;
  883. if (sem_post (&mutex_lock_main_thread) == -1) {
  884. perror ("sem_post: mutex_lock_main_thread"); exit (1);
  885. }
  886. if (sem_wait(&mutex_unlock_main_thread) == -1){
  887. perror ("sem_post: mutex_unlock_main_thread"); exit (1);
  888. }
  889. pthread_mutex_unlock(&lock_data);
  890. }
  891. if ((temp_status & 1) != (channel->freqlist[channel->freq_idx].oldstatus & 1)) {
  892. mqtt_msg_t mqtt_msg;
  893. mqtt_msg.audio =(audio_status << 1);
  894. mqtt_msg.sq = squelch_status;
  895. mqtt_msg.freq = channel->freqlist->frequency;
  896. mqtt_msg.name = fparms->label;
  897. mqtt_msg.mountpoint = fparms->mountpoint;
  898. mqtt_msg.bel_status = -1;
  899. mqtt_msg.type=1;
  900. mqtt_queue.push(mqtt_msg);
  901. }
  902. channel->freqlist[channel->freq_idx].oldstatus = temp_status;
  903. //Here for mqtt
  904. }
  905. fflush(stdout);
  906. }
  907. if (channel->axcindicate != NO_SIGNAL) {
  908. channel->freqlist[channel->freq_idx].active_counter++;
  909. }
  910. }
  911. if (dev->waveavail == 1) {
  912. debug_print("devices[%d]: output channel overrun\n", device_num);
  913. dev->output_overrun_count++;
  914. } else {
  915. dev->waveavail = 1;
  916. }
  917. dev->waveend -= WAVE_BATCH;
  918. #ifdef DEBUG
  919. gettimeofday(&te, NULL);
  920. debug_bulk_print("waveavail %lu.%lu %lu\n", te.tv_sec, (unsigned long)te.tv_usec, (te.tv_sec - ts.tv_sec) * 1000000UL + te.tv_usec - ts.tv_usec);
  921. ts.tv_sec = te.tv_sec;
  922. ts.tv_usec = te.tv_usec;
  923. #endif /* DEBUG */
  924. demod_params->mp3_signal->send();
  925. dev->row++;
  926. if (dev->row == 12) {
  927. dev->row = 0;
  928. }
  929. }
  930. dev->input->bufs = (dev->input->bufs + bps * FFT_BATCH) % dev->input->buf_size;
  931. device_num = next_device(demod_params, device_num);
  932. }
  933. }
  934. void usage() {
  935. cout << "Usage: rtl_airband [options] [-c <config_file_path>]\n\
  936. \t-h\t\t\tDisplay this help text\n\
  937. \t-f\t\t\tRun in foreground, display textual waterfalls\n\
  938. \t-F\t\t\tRun in foreground, do not display waterfalls (for running as a systemd service)\n";
  939. #ifdef NFM
  940. cout << "\t-Q\t\t\tUse quadri correlator for FM demodulation (default is atan2)\n";
  941. #endif /* NFM */
  942. #ifdef DEBUG
  943. cout << "\t-d <file>\t\tLog debugging information to <file> (default is " << DEBUG_PATH << ")\n";
  944. #endif /* DEBUG */
  945. cout << "\t-e\t\t\tPrint messages to standard error (disables syslog logging)\n";
  946. cout << "\t-c <config_file_path>\tUse non-default configuration file\n\t\t\t\t(default: " << CFGFILE << ")\n\
  947. \t-v\t\t\tDisplay version and exit\n";
  948. exit(EXIT_SUCCESS);
  949. }
  950. static int count_devices_running() {
  951. int ret = 0;
  952. for (int i = 0; i < device_count; i++) {
  953. if (devices[i].input->state == INPUT_RUNNING) {
  954. ret++;
  955. }
  956. }
  957. return ret;
  958. }
  959. int main(int argc, char* argv[]) {
  960. #ifdef WITH_PROFILING
  961. ProfilerStart("rtl_airband.prof");
  962. #endif /* WITH_PROFILING */
  963. // initialization
  964. sem_init (&mutex_lock_main_thread, 1, 0);
  965. sem_init (&mutex_unlock_main_thread, 1, 0);
  966. if (pthread_mutex_init(&lock_data, NULL) != 0) {
  967. printf("\n mutex init has failed\n");
  968. return 1;
  969. }
  970. if (pthread_mutex_init(&lock_mqtt_data, NULL) != 0) {
  971. printf("\n mutex init has failed\n");
  972. return 1;
  973. }
  974. printf("SEM and locks OPEN\n");
  975. #ifdef GPIOX
  976. char const *chipname = "gpiochip0";
  977. unsigned int gpio16 = 16;
  978. unsigned int gpio20 = 20;
  979. unsigned int gpio26 = 26;
  980. unsigned int gpio24 = 24;
  981. unsigned int gpio25 = 25;
  982. chip = gpiod_chip_open_by_name(chipname);
  983. if (!chip) {
  984. perror("gpiod_chip_open_by_name");
  985. return 1;
  986. }
  987. led_squ = gpiod_chip_get_line(chip, gpio26);
  988. led_vox = gpiod_chip_get_line(chip, gpio20);
  989. led_control = gpiod_chip_get_line(chip, gpio16);
  990. relay1 = gpiod_chip_get_line(chip, gpio25);
  991. relay2 = gpiod_chip_get_line(chip, gpio24);
  992. #endif
  993. #ifdef GPIOX
  994. gpiod_line_request_output(led_squ, "Consumer1", 0);
  995. gpiod_line_set_value(led_squ, 0);
  996. gpiod_line_request_output(led_vox, "Consumer2", 0);
  997. gpiod_line_set_value(led_vox, 0);
  998. gpiod_line_request_output(led_control, "Consumer3", 0);
  999. gpiod_line_set_value(led_control, 0);
  1000. gpiod_line_request_output(relay1, "Consumer4", 0);
  1001. gpiod_line_set_value(relay1, 1);
  1002. gpiod_line_request_output(relay2, "Consumer5", 0);
  1003. gpiod_line_set_value(relay2, 1);
  1004. #endif
  1005. #pragma GCC diagnostic ignored "-Wwrite-strings"
  1006. char* cfgfile = CFGFILE;
  1007. char* pidfile = PIDFILE;
  1008. #pragma GCC diagnostic warning "-Wwrite-strings"
  1009. int opt;
  1010. char optstring[16] = "efFhvc:";
  1011. #ifdef NFM
  1012. strcat(optstring, "Q");
  1013. #endif /* NFM */
  1014. #ifdef DEBUG
  1015. strcat(optstring, "d:");
  1016. #endif /* DEBUG */
  1017. int foreground = 0; // daemonize
  1018. int do_syslog = 1;
  1019. while ((opt = getopt(argc, argv, optstring)) != -1) {
  1020. switch (opt) {
  1021. #ifdef NFM
  1022. case 'Q':
  1023. fm_demod = FM_QUADRI_DEMOD;
  1024. break;
  1025. #endif /* NFM */
  1026. #ifdef DEBUG
  1027. case 'd':
  1028. debug_path = strdup(optarg);
  1029. break;
  1030. #endif /* DEBUG */
  1031. case 'e':
  1032. do_syslog = 0;
  1033. break;
  1034. case 'f':
  1035. foreground = 1;
  1036. tui = 1;
  1037. break;
  1038. case 'F':
  1039. foreground = 1;
  1040. tui = 0;
  1041. break;
  1042. case 'c':
  1043. cfgfile = optarg;
  1044. break;
  1045. case 'v':
  1046. cout << "RTLSDR-Airband version " << RTL_AIRBAND_VERSION << "\n";
  1047. exit(EXIT_SUCCESS);
  1048. case 'h':
  1049. default:
  1050. usage();
  1051. break;
  1052. }
  1053. }
  1054. #ifdef DEBUG
  1055. if (!debug_path)
  1056. debug_path = strdup(DEBUG_PATH);
  1057. init_debug(debug_path);
  1058. #endif /* DEBUG */
  1059. // If executing other than as root, GPU memory gets alloc'd and the
  1060. // 'permission denied' message on /dev/mem kills rtl_airband without
  1061. // releasing GPU memory.
  1062. #ifdef WITH_BCM_VC
  1063. // should probably do this check in other circumstances also.
  1064. if (0 != getuid()) {
  1065. cerr << "FFT library requires that rtl_airband be executed as root\n";
  1066. exit(1);
  1067. }
  1068. #endif /* WITH_BCM_VC */
  1069. // read config
  1070. try {
  1071. Config config;
  1072. config.readFile(cfgfile);
  1073. Setting& root = config.getRoot();
  1074. if (root.exists("pidfile"))
  1075. pidfile = strdup(root["pidfile"]);
  1076. if (root.exists("fft_size")) {
  1077. int fsize = (int)(root["fft_size"]);
  1078. fft_size_log = 0;
  1079. for (size_t i = MIN_FFT_SIZE_LOG; i <= MAX_FFT_SIZE_LOG; i++) {
  1080. if (fsize == 1 << i) {
  1081. fft_size = (size_t)fsize;
  1082. fft_size_log = i;
  1083. break;
  1084. }
  1085. }
  1086. if (fft_size_log == 0) {
  1087. cerr << "Configuration error: invalid fft_size value (must be a power of two in range " << (1 << MIN_FFT_SIZE_LOG) << "-" << (1 << MAX_FFT_SIZE_LOG) << ")\n";
  1088. error();
  1089. }
  1090. }
  1091. if (root.exists("shout_metadata_delay"))
  1092. shout_metadata_delay = (int)(root["shout_metadata_delay"]);
  1093. if (shout_metadata_delay < 0 || shout_metadata_delay > 2 * TAG_QUEUE_LEN) {
  1094. cerr << "Configuration error: shout_metadata_delay is out of allowed range (0-" << 2 * TAG_QUEUE_LEN << ")\n";
  1095. error();
  1096. }
  1097. if (root.exists("localtime") && (bool)root["localtime"] == true)
  1098. use_localtime = true;
  1099. if (root.exists("multiple_demod_threads") && (bool)root["multiple_demod_threads"] == true) {
  1100. #ifdef WITH_BCM_VC
  1101. cerr << "Using multiple_demod_threads not supported with BCM VideoCore for FFT\n";
  1102. exit(1);
  1103. #endif /* WITH_BCM_VC */
  1104. multiple_demod_threads = true;
  1105. }
  1106. if (root.exists("multiple_output_threads") && (bool)root["multiple_output_threads"] == true) {
  1107. multiple_output_threads = true;
  1108. }
  1109. if (root.exists("log_scan_activity") && (bool)root["log_scan_activity"] == true)
  1110. log_scan_activity = true;
  1111. if (root.exists("stats_filepath"))
  1112. stats_filepath = strdup(root["stats_filepath"]);
  1113. #ifdef NFM
  1114. if (root.exists("tau"))
  1115. alpha = ((int)root["tau"] == 0 ? 0.0f : exp(-1.0f / (WAVE_RATE * 1e-6 * (int)root["tau"])));
  1116. #endif /* NFM */
  1117. if (root.exists("bel_start_on_time"))
  1118. bel_start_on_time=(int)(root["bel_start_on_time"]);
  1119. if (root.exists("bel_open_time"))
  1120. bel_open_time=(int)(root["bel_open_time"]);
  1121. if (root.exists("bel_blink_time"))
  1122. bel_blink_time=(int)(root["bel_blink_time"]);
  1123. if (root.exists("bel_wave_out_level"))
  1124. bel_wave_out_level=(float)(root["bel_wave_out_level"]);
  1125. if (root.exists("bel_wave_in_level"))
  1126. bel_wave_in_level=(float)(root["bel_wave_in_level"]);
  1127. if (root.exists("bel_prolong_time"))
  1128. bel_prolong_time=(int)(root["bel_prolong_time"]);
  1129. //MQTT
  1130. if (root.exists("bel_mqtt_server"))
  1131. bel_mqtt_server = strdup(root["bel_mqtt_server"]);
  1132. if (root.exists("bel_mqtt_client_id"))
  1133. bel_mqtt_client_id = strdup(root["bel_mqtt_client_id"]);
  1134. if (root.exists("bel_mqtt_user_id"))
  1135. bel_mqtt_user_id= strdup(root["bel_mqtt_user_id"]);
  1136. if (root.exists("bel_mqtt_server"))
  1137. bel_mqtt_password= strdup(root["bel_mqtt_password"]);
  1138. Setting& devs = config.lookup("devices");
  1139. device_count = devs.getLength();
  1140. if (device_count < 1) {
  1141. cerr << "Configuration error: no devices defined\n";
  1142. error();
  1143. }
  1144. struct sigaction sigact, pipeact;
  1145. memset(&sigact, 0, sizeof(sigact));
  1146. memset(&pipeact, 0, sizeof(pipeact));
  1147. pipeact.sa_handler = SIG_IGN;
  1148. sigact.sa_handler = &sighandler;
  1149. sigaction(SIGPIPE, &pipeact, NULL);
  1150. sigaction(SIGHUP, &sigact, NULL);
  1151. sigaction(SIGINT, &sigact, NULL);
  1152. sigaction(SIGQUIT, &sigact, NULL);
  1153. sigaction(SIGTERM, &sigact, NULL);
  1154. devices = (device_t*)XCALLOC(device_count, sizeof(device_t));
  1155. shout_init();
  1156. if (do_syslog) {
  1157. openlog("rtl_airband", LOG_PID, LOG_DAEMON);
  1158. log_destination = SYSLOG;
  1159. } else if (foreground) {
  1160. log_destination = STDERR;
  1161. } else {
  1162. log_destination = NONE;
  1163. }
  1164. if (root.exists("mixers")) {
  1165. Setting& mx = config.lookup("mixers");
  1166. mixers = (mixer_t*)XCALLOC(mx.getLength(), sizeof(struct mixer_t));
  1167. if ((mixer_count = parse_mixers(mx)) > 0) {
  1168. mixers = (mixer_t*)XREALLOC(mixers, mixer_count * sizeof(struct mixer_t));
  1169. } else {
  1170. free(mixers);
  1171. }
  1172. } else {
  1173. mixer_count = 0;
  1174. }
  1175. uint32_t devs_enabled = parse_devices(devs);
  1176. if (devs_enabled < 1) {
  1177. cerr << "Configuration error: no devices defined\n";
  1178. error();
  1179. }
  1180. device_count = devs_enabled;
  1181. debug_print("mixer_count=%d\n", mixer_count);
  1182. #ifdef DEBUG
  1183. for (int z = 0; z < mixer_count; z++) {
  1184. mixer_t* m = &mixers[z];
  1185. debug_print("mixer[%d]: name=%s, input_count=%d, output_count=%d\n", z, m->name, m->input_count, m->channel.output_count);
  1186. }
  1187. #endif /* DEBUG */
  1188. } catch (const FileIOException& e) {
  1189. cerr << "Cannot read configuration file " << cfgfile << "\n";
  1190. error();
  1191. } catch (const ParseException& e) {
  1192. cerr << "Error while parsing configuration file " << cfgfile << " line " << e.getLine() << ": " << e.getError() << "\n";
  1193. error();
  1194. } catch (const SettingNotFoundException& e) {
  1195. cerr << "Configuration error: mandatory parameter missing: " << e.getPath() << "\n";
  1196. error();
  1197. } catch (const SettingTypeException& e) {
  1198. cerr << "Configuration error: invalid parameter type: " << e.getPath() << "\n";
  1199. error();
  1200. } catch (const ConfigException& e) {
  1201. cerr << "Unhandled config exception\n";
  1202. error();
  1203. }
  1204. log(LOG_INFO, "RTLSDR-Airband version %s starting\n", RTL_AIRBAND_VERSION);
  1205. if (!foreground) {
  1206. int pid1, pid2;
  1207. if ((pid1 = fork()) == -1) {
  1208. cerr << "Cannot fork child process: " << strerror(errno) << "\n";
  1209. error();
  1210. }
  1211. if (pid1) {
  1212. waitpid(-1, NULL, 0);
  1213. return (0);
  1214. } else {
  1215. if ((pid2 = fork()) == -1) {
  1216. cerr << "Cannot fork child process: " << strerror(errno) << "\n";
  1217. error();
  1218. }
  1219. if (pid2) {
  1220. return (0);
  1221. } else {
  1222. int nullfd, dupfd;
  1223. if ((nullfd = open("/dev/null", O_RDWR)) == -1) {
  1224. log(LOG_CRIT, "Cannot open /dev/null: %s\n", strerror(errno));
  1225. error();
  1226. }
  1227. for (dupfd = 0; dupfd <= 2; dupfd++) {
  1228. if (dup2(nullfd, dupfd) == -1) {
  1229. log(LOG_CRIT, "dup2(): %s\n", strerror(errno));
  1230. error();
  1231. }
  1232. }
  1233. if (nullfd > 2)
  1234. close(nullfd);
  1235. FILE* f = fopen(pidfile, "w");
  1236. if (f == NULL) {
  1237. log(LOG_WARNING, "Cannot write pidfile: %s\n", strerror(errno));
  1238. } else {
  1239. fprintf(f, "%ld\n", (long)getpid());
  1240. fclose(f);
  1241. }
  1242. }
  1243. }
  1244. }
  1245. for (int i = 0; i < mixer_count; i++) {
  1246. if (mixers[i].enabled == false) {
  1247. continue; // no inputs connected = no need to initialize output
  1248. }
  1249. channel_t* channel = &mixers[i].channel;
  1250. if (channel->need_mp3) {
  1251. channel->lame = airlame_init(mixers[i].channel.mode, mixers[i].channel.highpass, mixers[i].channel.lowpass);
  1252. channel->lamebuf = (unsigned char*)malloc(sizeof(unsigned char) * LAMEBUF_SIZE);
  1253. }
  1254. for (int k = 0; k < channel->output_count; k++) {
  1255. output_t* output = channel->outputs + k;
  1256. if (output->type == O_ICECAST) {
  1257. shout_setup((icecast_data*)(output->data), channel->mode);
  1258. } else if (output->type == O_UDP_STREAM) {
  1259. udp_stream_data* sdata = (udp_stream_data*)(output->data);
  1260. if (!udp_stream_init(sdata, channel->mode, (size_t)WAVE_BATCH * sizeof(float))) {
  1261. cerr << "Failed to initialize mixer " << i << " output " << k << " - aborting\n";
  1262. error();
  1263. }
  1264. #ifdef WITH_PULSEAUDIO
  1265. } else if (output->type == O_PULSE) {
  1266. pulse_init();
  1267. pulse_setup((pulse_data*)(output->data), channel->mode);
  1268. #endif /* WITH_PULSEAUDIO */
  1269. }
  1270. }
  1271. }
  1272. for (int i = 0; i < device_count; i++) {
  1273. device_t* dev = devices + i;
  1274. for (int j = 0; j < dev->channel_count; j++) {
  1275. channel_t* channel = dev->channels + j;
  1276. // If the channel has icecast or MP3 file output, we will attempt to
  1277. // initialize a separate LAME context for MP3 encoding.
  1278. if (channel->need_mp3) {
  1279. channel->lame = airlame_init(channel->mode, channel->highpass, channel->lowpass);
  1280. channel->lamebuf = (unsigned char*)malloc(sizeof(unsigned char) * LAMEBUF_SIZE);
  1281. }
  1282. for (int k = 0; k < channel->output_count; k++) {
  1283. output_t* output = channel->outputs + k;
  1284. if (output->type == O_ICECAST) {
  1285. shout_setup((icecast_data*)(output->data), channel->mode);
  1286. } else if (output->type == O_UDP_STREAM) {
  1287. udp_stream_data* sdata = (udp_stream_data*)(output->data);
  1288. if (!udp_stream_init(sdata, channel->mode, (size_t)WAVE_BATCH * sizeof(float))) {
  1289. cerr << "Failed to initialize device " << i << " channel " << j << " output " << k << " - aborting\n";
  1290. error();
  1291. }
  1292. #ifdef WITH_PULSEAUDIO
  1293. } else if (output->type == O_PULSE) {
  1294. pulse_init();
  1295. pulse_setup((pulse_data*)(output->data), channel->mode);
  1296. #endif /* WITH_PULSEAUDIO */
  1297. }
  1298. }
  1299. }
  1300. if (input_init(dev->input) != 0 || dev->input->state != INPUT_INITIALIZED) {
  1301. if (errno != 0) {
  1302. cerr << "Failed to initialize input device " << i << ": " << strerror(errno) << " - aborting\n";
  1303. } else {
  1304. cerr << "Failed to initialize input device " << i << " - aborting\n";
  1305. }
  1306. error();
  1307. }
  1308. if (input_start(dev->input) != 0) {
  1309. cerr << "Failed to start input on device " << i << ": " << strerror(errno) << " - aborting\n";
  1310. error();
  1311. }
  1312. if (dev->mode == R_SCAN) {
  1313. // FIXME: set errno
  1314. if (pthread_mutex_init(&dev->tag_queue_lock, NULL) != 0) {
  1315. cerr << "Failed to initialize mutex - aborting\n";
  1316. error();
  1317. }
  1318. // FIXME: not needed when freq_count == 1?
  1319. pthread_create(&dev->controller_thread, NULL, &controller_thread, dev);
  1320. }
  1321. }
  1322. int timeout_device = 50; // 5 seconds
  1323. while ((devices_running = count_devices_running()) != device_count && timeout_device > 0) {
  1324. SLEEP(100);
  1325. timeout_device--;
  1326. }
  1327. if ((devices_running = count_devices_running()) != device_count) {
  1328. log(LOG_ERR, "%d device(s) failed to initialize - aborting\n", device_count - devices_running);
  1329. error();
  1330. }
  1331. if (tui && 1==0) { //PMPMPM
  1332. printf("\e[1;1H\e[2J");
  1333. GOTOXY(0, 0);
  1334. printf(" ");
  1335. for (int i = 0; i < device_count; i++) {
  1336. GOTOXY(0, i * 17 + 1);
  1337. for (int j = 0; j < devices[i].channel_count; j++) {
  1338. printf(" %7.3f ", devices[i].channels[j].freqlist[devices[i].channels[j].freq_idx].frequency / 1000000.0);
  1339. }
  1340. if (i != device_count - 1) {
  1341. GOTOXY(0, i * 17 + 16);
  1342. printf("-------------------------------------------------------------------------------");
  1343. }
  1344. }
  1345. }
  1346. THREAD belysning_control_check;
  1347. THREAD mqtt_control_check;
  1348. pthread_create(&belysning_control_check, NULL, &belysning_control_thread, NULL);
  1349. pthread_create(&mqtt_control_check, NULL, &mqtt_control_thread, NULL);
  1350. mqtt_msg_t mqtt_msg;
  1351. mqtt_msg.type=3;
  1352. mqtt_queue.push(mqtt_msg);
  1353. THREAD output_check;
  1354. pthread_create(&output_check, NULL, &output_check_thread, NULL);
  1355. int demod_thread_count = multiple_demod_threads ? device_count : 1;
  1356. demod_params_t* demod_params = (demod_params_t*)XCALLOC(demod_thread_count, sizeof(demod_params_t));
  1357. THREAD* demod_threads = (THREAD*)XCALLOC(demod_thread_count, sizeof(THREAD));
  1358. int output_thread_count = 1;
  1359. if (multiple_output_threads) {
  1360. output_thread_count = demod_thread_count;
  1361. if (mixer_count > 0) {
  1362. output_thread_count++;
  1363. }
  1364. }
  1365. output_params_t* output_params = (output_params_t*)XCALLOC(output_thread_count, sizeof(output_params_t));
  1366. THREAD* output_threads = (THREAD*)XCALLOC(output_thread_count, sizeof(THREAD));
  1367. // Setup the output and demod threads
  1368. if (multiple_output_threads == false) {
  1369. init_output(&output_params[0], 0, device_count, 0, mixer_count);
  1370. if (multiple_demod_threads == false) {
  1371. init_demod(&demod_params[0], output_params[0].mp3_signal, 0, device_count);
  1372. } else {
  1373. for (int i = 0; i < demod_thread_count; i++) {
  1374. init_demod(&demod_params[i], output_params[0].mp3_signal, i, i + 1);
  1375. }
  1376. }
  1377. } else {
  1378. if (multiple_demod_threads == false) {
  1379. init_output(&output_params[0], 0, device_count, 0, 0);
  1380. init_demod(&demod_params[0], output_params[0].mp3_signal, 0, device_count);
  1381. } else {
  1382. for (int i = 0; i < device_count; i++) {
  1383. init_output(&output_params[i], i, i + 1, 0, 0);
  1384. init_demod(&demod_params[i], output_params[i].mp3_signal, i, i + 1);
  1385. }
  1386. }
  1387. if (mixer_count > 0) {
  1388. init_output(&output_params[output_thread_count - 1], 0, 0, 0, mixer_count);
  1389. }
  1390. }
  1391. // Startup the output threads
  1392. for (int i = 0; i < output_thread_count; i++) {
  1393. pthread_create(&output_threads[i], NULL, &output_thread, &output_params[i]);
  1394. }
  1395. // Startup the mixer thread (if there is one) using the signal for the last output thread
  1396. THREAD mixer;
  1397. if (mixer_count > 0) {
  1398. pthread_create(&mixer, NULL, &mixer_thread, output_params[output_thread_count - 1].mp3_signal);
  1399. }
  1400. #ifdef WITH_PULSEAUDIO
  1401. pulse_start();
  1402. #endif /* WITH_PULSEAUDIO */
  1403. sincosf_lut_init();
  1404. // Startup the demod threads
  1405. for (int i = 0; i < demod_thread_count; i++) {
  1406. pthread_create(&demod_threads[i], NULL, &demodulate, &demod_params[i]);
  1407. }
  1408. // Wait for demod threads to exit
  1409. for (int i = 0; i < demod_thread_count; i++) {
  1410. pthread_join(demod_threads[i], NULL);
  1411. }
  1412. log(LOG_INFO, "Cleaning up\n");
  1413. for (int i = 0; i < device_count; i++) {
  1414. if (devices[i].mode == R_SCAN)
  1415. pthread_join(devices[i].controller_thread, NULL);
  1416. if (input_stop(devices[i].input) != 0 || devices[i].input->state != INPUT_STOPPED) {
  1417. if (errno != 0) {
  1418. log(LOG_ERR, "Failed do stop device #%d: %s\n", i, strerror(errno));
  1419. } else {
  1420. log(LOG_ERR, "Failed do stop device #%d\n", i);
  1421. }
  1422. }
  1423. }
  1424. log(LOG_INFO, "Input threads closed\n");
  1425. for (int i = 0; i < device_count; i++) {
  1426. device_t* dev = devices + i;
  1427. disable_device_outputs(dev);
  1428. }
  1429. if (mixer_count > 0) {
  1430. log(LOG_INFO, "Closing mixer thread\n");
  1431. pthread_join(mixer, NULL);
  1432. }
  1433. log(LOG_INFO, "Closing output thread(s)\n");
  1434. for (int i = 0; i < output_thread_count; i++) {
  1435. output_params[i].mp3_signal->send();
  1436. pthread_join(output_threads[i], NULL);
  1437. }
  1438. for (int i = 0; i < device_count; i++) {
  1439. device_t* dev = devices + i;
  1440. for (int j = 0; j < dev->channel_count; j++) {
  1441. channel_t* channel = dev->channels + j;
  1442. if (channel->need_mp3 && channel->lame) {
  1443. lame_close(channel->lame);
  1444. }
  1445. }
  1446. }
  1447. log(LOG_INFO, "Closing bel thread\n");
  1448. pthread_join(belysning_control_check, NULL);
  1449. log(LOG_INFO, "Closing mqtt thread\n");
  1450. pthread_kill(mqtt_control_check,SIGALRM);
  1451. // pthread_join(mqtt_control_check, NULL);
  1452. log(LOG_INFO, "Closing xxx thread\n");
  1453. close_debug();
  1454. #ifdef WITH_PROFILING
  1455. ProfilerStop();
  1456. #endif /* WITH_PROFILING */
  1457. return 0;
  1458. }