psgen_util.c 25 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247
  1. /*====================================================================*
  2. *
  3. * Copyright (c) 2013 Qualcomm Atheros, Inc.
  4. *
  5. * All rights reserved.
  6. *
  7. *====================================================================*/
  8. /*====================================================================*
  9. *
  10. * psgen_util.c - helpers for the psgen program
  11. *
  12. * Contributor(s):
  13. * Nathaniel Houghton <nhoughto@qca.qualcomm.com>
  14. *
  15. *--------------------------------------------------------------------*/
  16. #ifndef PSGEN_UTIL_SOURCE
  17. #define PSGEN_UTIL_SOURCE
  18. /*====================================================================*
  19. * system header files;
  20. *--------------------------------------------------------------------*/
  21. #include <ctype.h>
  22. #include <stdio.h>
  23. #include <unistd.h>
  24. /*====================================================================*
  25. * custom header files;
  26. *--------------------------------------------------------------------*/
  27. #include "../tools/chars.h"
  28. #include "../tools/files.h"
  29. #include "../tools/error.h"
  30. #include "../tools/number.h"
  31. #include "../nda/psgen.h"
  32. #include "../pib/pib.h"
  33. /*====================================================================*
  34. *
  35. * Read a double in from string s, scaling with a suffix;
  36. *
  37. * Returns pointer character where parsing stopped.
  38. *
  39. *--------------------------------------------------------------------*/
  40. const char * strtodouble (const char * s, double * d)
  41. {
  42. const char * p;
  43. int sign = 1;
  44. double div;
  45. div = 0;
  46. * d = 0;
  47. p = s;
  48. if (* p == '-')
  49. {
  50. sign = -1;
  51. ++ p;
  52. }
  53. else if (* p == '+')
  54. {
  55. sign = 1;
  56. ++ p;
  57. }
  58. while (* p != '\0')
  59. {
  60. if (isdigit ((unsigned char)* p))
  61. {
  62. if (div == 0)
  63. {
  64. * d = * d * 10 + (* p - '0');
  65. }
  66. else
  67. {
  68. * d = * d + (* p - '0') / div;
  69. div *= 10;
  70. }
  71. }
  72. else if (* p == '.' && div == 0)
  73. {
  74. div = 10;
  75. }
  76. else
  77. {
  78. break;
  79. }
  80. ++ p;
  81. }
  82. * d *= sign;
  83. switch (* p)
  84. {
  85. case 'M':
  86. * d *= 1000000;
  87. ++ p;
  88. break;
  89. case 'K':
  90. case 'k':
  91. * d *= 1000;
  92. ++ p;
  93. break;
  94. }
  95. return (p);
  96. }
  97. /*====================================================================*
  98. *
  99. *
  100. *
  101. *--------------------------------------------------------------------*/
  102. uint32_t freq_to_index (double freq, struct device_spec * d)
  103. {
  104. return (rint ((freq / HPAV_CARRIER_WIDTH - 74.0) / d->carriers_per_prescaler));
  105. }
  106. /*====================================================================*
  107. *
  108. *
  109. *
  110. *--------------------------------------------------------------------*/
  111. double index_to_freq (uint32_t index, struct device_spec * d)
  112. {
  113. return (HPAV_CARRIER_WIDTH * (index * d->carriers_per_prescaler + 74.0));
  114. }
  115. /*====================================================================*
  116. *
  117. *
  118. *
  119. *--------------------------------------------------------------------*/
  120. double ps_to_amp (uint32_t new_ps_val, uint32_t old_ps_val)
  121. {
  122. if (old_ps_val == 0)
  123. {
  124. /* XXX: what should really be done here? */
  125. old_ps_val = 1;
  126. }
  127. return (20 * log10 ((double) new_ps_val / old_ps_val));
  128. }
  129. /*====================================================================*
  130. *
  131. *
  132. *
  133. *--------------------------------------------------------------------*/
  134. uint32_t amp_to_ps (double amp, uint32_t old_ps_val, struct device_spec * d)
  135. {
  136. double new_ps_val = rint (pow (10.0, amp / 20.0) * old_ps_val);
  137. if (new_ps_val > d->prescaler_max)
  138. {
  139. return (d->prescaler_max + 1);
  140. }
  141. return (uint32_t) new_ps_val;
  142. }
  143. /*====================================================================*
  144. *
  145. *
  146. *
  147. *--------------------------------------------------------------------*/
  148. int create_trace_rs (struct rs_file * rs_file, struct trace * trace)
  149. {
  150. int i;
  151. int j;
  152. const char * p;
  153. for (i = 0; i < rs_file->item_count; ++ i)
  154. {
  155. if (! strcasecmp (rs_file->item [i].name, "Values"))
  156. {
  157. rs_file->trace_start = i + 1;
  158. rs_file->trace_end = rs_file->trace_start + atoi (rs_file->item [i].value) -1;
  159. if (rs_file->trace_end >= rs_file->item_count)
  160. {
  161. error (1, 0, "spectrum analyzer trace \"Values\" field is incorrect in file %s", rs_file->path);
  162. }
  163. break;
  164. }
  165. }
  166. if (i == rs_file->item_count)
  167. {
  168. error (1, 0, "no trace data found in input file %s", rs_file->path);
  169. }
  170. memset (trace, 0, sizeof (* trace));
  171. trace->count = rs_file->trace_end - rs_file->trace_start + 1;
  172. trace->freq = calloc (trace->count, sizeof (* trace->freq));
  173. if (trace->freq == NULL)
  174. {
  175. error (1, errno, "out of memory");
  176. }
  177. trace->value = calloc (trace->count, sizeof (* trace->value));
  178. if (trace->value == NULL)
  179. {
  180. error (1, errno, "out of memory");
  181. }
  182. for (i = 0, j = rs_file->trace_start; i < trace->count; ++ i, ++ j)
  183. {
  184. p = strtodouble (rs_file->item [j].name, & trace->freq [i]);
  185. if (* p != '\0')
  186. {
  187. error (1, 0, "invalid frequency value in spectrum analyzer trace: %s", rs_file->item [j].name);
  188. }
  189. p = strtodouble (rs_file->item [j].value, & trace->value [i]);
  190. if (* p != '\0')
  191. {
  192. error (1, 0, "invalid amplitude value in spectrum analyzer trace: %s", rs_file->item [j].value);
  193. }
  194. }
  195. return (0);
  196. }
  197. /*====================================================================*
  198. *
  199. *
  200. *
  201. *--------------------------------------------------------------------*/
  202. int load_rs_file (const char * path, struct rs_file * rs_file)
  203. {
  204. int c;
  205. off_t fsize;
  206. char * data;
  207. char * p;
  208. char * start;
  209. int count;
  210. FILE * fp;
  211. fp = fopen (path, "r");
  212. if (fp == NULL)
  213. {
  214. error (1, errno, "could not open file %s", path);
  215. }
  216. memset (rs_file, 0, sizeof (* rs_file));
  217. if (fseek (fp, 0, SEEK_END) == -1)
  218. {
  219. error (1, errno, "could not seek in file %s", path);
  220. }
  221. fsize = ftell (fp);
  222. if (fseek (fp, 0, SEEK_SET) == -1)
  223. {
  224. error (1, errno, "could not seek in file %s", path);
  225. }
  226. if (fsize == 0)
  227. {
  228. error (1, 0, "input file %s is empty", path);
  229. }
  230. data = malloc (fsize);
  231. if (data == NULL)
  232. {
  233. error (1, errno, "out of memory");
  234. }
  235. p = data;
  236. while ((c = fgetc (fp)) != EOF)
  237. {
  238. if (c == '\n')
  239. {
  240. ++ rs_file->item_count;
  241. }
  242. * p = c;
  243. ++ p;
  244. }
  245. fclose (fp);
  246. rs_file->path = strdup (path);
  247. if (rs_file->path == NULL)
  248. {
  249. error (1, errno, "out of memory");
  250. }
  251. rs_file->item = calloc (rs_file->item_count, sizeof (struct rs_item));
  252. if (rs_file->item == NULL)
  253. {
  254. error (1, errno, "out of memory");
  255. }
  256. p = data;
  257. count = 0;
  258. while (count < rs_file->item_count)
  259. {
  260. /* collect name */
  261. start = p;
  262. while (* p != ';' && * p != '\n' && * p != '\0')
  263. {
  264. ++ p;
  265. }
  266. if (* p != ';')
  267. {
  268. error (1, 0, "unexpected end of line %d in file %s", count + 1, rs_file->path);
  269. }
  270. * p = '\0';
  271. ++ p;
  272. rs_file->item [count].name = start;
  273. /* collect value */
  274. start = p;
  275. while (* p != ';' && * p != '\n' && * p != '\0')
  276. {
  277. ++ p;
  278. }
  279. if (* p != ';')
  280. {
  281. error (1, 0, "unexpected end of line %d in file %s", count + 1, rs_file->path);
  282. }
  283. * p = '\0';
  284. ++ p;
  285. rs_file->item [count].value = start;
  286. /* collect unit */
  287. start = p;
  288. while (* p != ';' && * p != '\n' && * p != '\0')
  289. {
  290. ++ p;
  291. }
  292. if (* p != '\n')
  293. {
  294. error (1, 0, "unexpected item on line %d in file %s", count + 1, rs_file->path);
  295. }
  296. * p = '\0';
  297. ++ p;
  298. rs_file->item [count].unit = start;
  299. ++ count;
  300. }
  301. return (0);
  302. }
  303. /*====================================================================*
  304. *
  305. *
  306. *
  307. *--------------------------------------------------------------------*/
  308. void free_rs_file (struct rs_file * rs_file)
  309. {
  310. free (rs_file->item [0].name);
  311. free (rs_file->path);
  312. free (rs_file->item);
  313. }
  314. /*====================================================================*
  315. *
  316. *
  317. *
  318. *--------------------------------------------------------------------*/
  319. void free_tweaks (struct tweak * t)
  320. {
  321. if (t == NULL)
  322. {
  323. return;
  324. }
  325. free_tweaks (t->next);
  326. free (t);
  327. }
  328. /*====================================================================*
  329. *
  330. *
  331. *
  332. *--------------------------------------------------------------------*/
  333. void free_dev_config (struct dev_config * dconf)
  334. {
  335. free (dconf->ps->value);
  336. free (dconf->ps);
  337. free (dconf);
  338. }
  339. /*====================================================================*
  340. *
  341. *
  342. *
  343. *--------------------------------------------------------------------*/
  344. int parse_range (const char * s, double * start, double * end)
  345. {
  346. const char * p;
  347. p = s;
  348. p = strtodouble (p, start);
  349. if (* p != '-')
  350. {
  351. return (-1);
  352. }
  353. ++ p;
  354. p = strtodouble (p, end);
  355. if (* p != '\0')
  356. {
  357. return (-1);
  358. }
  359. return (0);
  360. }
  361. /*====================================================================*
  362. *
  363. *
  364. *
  365. *--------------------------------------------------------------------*/
  366. int parse_tweak (struct tweak * t, const char * s)
  367. {
  368. const char * p;
  369. p = s;
  370. p = strtodouble (p, & t->sf);
  371. if (* p != ',')
  372. {
  373. return (-1);
  374. }
  375. ++ p;
  376. p = strtodouble (p, & t->ef);
  377. if (* p != ',')
  378. {
  379. return (-1);
  380. }
  381. ++ p;
  382. p = strtodouble (p, & t->sv);
  383. if (* p != ',')
  384. {
  385. return (-1);
  386. }
  387. ++ p;
  388. p = strtodouble (p, & t->ev);
  389. if (* p != '\0')
  390. {
  391. return (-1);
  392. }
  393. return (0);
  394. }
  395. /*====================================================================*
  396. *
  397. *
  398. *
  399. *--------------------------------------------------------------------*/
  400. int create_trace_copy (struct trace * dst, struct trace * src)
  401. {
  402. memcpy (dst, src, sizeof (* dst));
  403. dst->freq = calloc (dst->count, sizeof (* dst->freq));
  404. if (dst->freq == NULL)
  405. {
  406. return (-1);
  407. }
  408. dst->value = calloc (dst->count, sizeof (* dst->value));
  409. if (dst->value == NULL)
  410. {
  411. free (dst->freq);
  412. return (-1);
  413. }
  414. memcpy (dst->freq, src->freq, dst->count * sizeof (* dst->freq));
  415. memcpy (dst->value, src->value, dst->count * sizeof (* dst->value));
  416. return (0);
  417. }
  418. /*====================================================================*
  419. *
  420. *
  421. *
  422. *--------------------------------------------------------------------*/
  423. int reshape_trace (struct trace * dst, struct trace * src, struct device_spec * dspec, double start_freq, double end_freq)
  424. {
  425. int i;
  426. dst->count = dspec->prescaler_count;
  427. dst->freq = calloc (dst->count, sizeof (* dst->freq));
  428. if (dst->freq == NULL)
  429. {
  430. return (-1);
  431. }
  432. dst->value = calloc (dst->count, sizeof (* dst->value));
  433. if (dst->value == NULL)
  434. {
  435. free (dst->freq);
  436. return (-1);
  437. }
  438. if (start_freq == -1)
  439. {
  440. start_freq = index_to_freq (0, dspec);
  441. }
  442. if (end_freq == -1)
  443. {
  444. end_freq = index_to_freq (dst->count, dspec);
  445. }
  446. for (i = 0; i < dst->count; ++ i)
  447. {
  448. dst->freq [i] = index_to_freq (i, dspec);
  449. if (dst->freq [i] < start_freq || dst->freq [i] + PRESCALER_FREQ_WIDTH (dspec) > end_freq)
  450. {
  451. dst->value [i] = 0;
  452. }
  453. else
  454. {
  455. dst->value [i] = estimate_trace_value (src, dst->freq [i], PRESCALER_FREQ_WIDTH (dspec));
  456. }
  457. }
  458. return (0);
  459. }
  460. /*====================================================================*
  461. *
  462. *
  463. *
  464. *--------------------------------------------------------------------*/
  465. void free_trace_data (struct trace * t)
  466. {
  467. free (t->freq);
  468. free (t->value);
  469. memset (t, 0, sizeof (* t));
  470. }
  471. /*====================================================================*
  472. *
  473. *
  474. *
  475. *--------------------------------------------------------------------*/
  476. int find_trace_index_range (struct trace * t, double freq_start, double freq_end, uint32_t * idx_start, uint32_t * idx_end)
  477. {
  478. int i;
  479. int found_start = 0;
  480. * idx_start = * idx_end = 0;
  481. for (i = 0; i < t->count; ++ i)
  482. {
  483. if (t->freq [i] >= freq_end)
  484. {
  485. break;
  486. }
  487. if (t->freq [i] >= freq_start)
  488. {
  489. if (found_start == 0)
  490. {
  491. * idx_start = i;
  492. * idx_end = i;
  493. found_start = 1;
  494. }
  495. else
  496. {
  497. * idx_end = i;
  498. }
  499. }
  500. }
  501. if (! found_start)
  502. {
  503. return (-1);
  504. }
  505. return (0);
  506. }
  507. /*====================================================================*
  508. *
  509. *
  510. *
  511. *--------------------------------------------------------------------*/
  512. double estimate_trace_value (struct trace * t, double freq, double width)
  513. {
  514. uint32_t start_idx,
  515. end_idx;
  516. if (find_trace_index_range (t, freq, freq + width, & start_idx, & end_idx) == -1)
  517. {
  518. error (1, 0, "could not find trace value for frequency range %f -> %f", freq, freq + width);
  519. }
  520. else
  521. {
  522. uint32_t i;
  523. double sum;
  524. sum = 0;
  525. for (i = start_idx; i <= end_idx; ++ i)
  526. {
  527. sum += t->value [i];
  528. }
  529. return (sum / (end_idx - start_idx + 1));
  530. }
  531. exit (1);
  532. }
  533. /*====================================================================*
  534. *
  535. *
  536. *
  537. *--------------------------------------------------------------------*/
  538. int apply_tweak (struct trace * trace, struct tweak * tweak, int mode)
  539. {
  540. uint32_t i;
  541. double slope;
  542. uint32_t index_sf,
  543. index_ef;
  544. if (find_trace_index_range (trace, tweak->sf, tweak->ef, & index_sf, & index_ef) == -1)
  545. {
  546. error (1, 0, "could not find trace frequency range %f -> %f", tweak->sf, tweak->ef);
  547. }
  548. slope = (tweak->ev - tweak->sv) / (index_ef - index_sf);
  549. switch (mode)
  550. {
  551. case TWEAK_ABSOLUTE:
  552. for (i = index_sf; i <= index_ef; ++ i)
  553. {
  554. trace->value [i] = tweak->sv + slope * (i - index_sf);
  555. }
  556. break;
  557. case TWEAK_RELATIVE:
  558. for (i = index_sf; i <= index_ef; ++ i)
  559. {
  560. trace->value [i] += tweak->sv + slope * (i - index_sf);
  561. }
  562. break;
  563. default:
  564. return (-1);
  565. }
  566. return (0);
  567. }
  568. /*====================================================================*
  569. *
  570. *
  571. *
  572. *--------------------------------------------------------------------*/
  573. struct dev_config * generate_config (struct trace * tr_old, struct trace * tr_new, struct device_spec * dspec, int gain_adj, struct prescalers * input_ps, double start_freq, double end_freq)
  574. {
  575. unsigned i;
  576. double old_val;
  577. double new_val;
  578. double diff;
  579. uint32_t ps_val;
  580. struct dev_config * dconf;
  581. dconf = malloc (sizeof (* dconf));
  582. if (dconf == NULL)
  583. {
  584. error (0, errno, "out of memory");
  585. return (NULL);
  586. }
  587. dconf->ps = malloc (sizeof (* dconf->ps));
  588. if (dconf->ps == NULL)
  589. {
  590. error (0, errno, "out of memory");
  591. free (dconf);
  592. return (NULL);
  593. }
  594. dconf->ps->count = dspec->prescaler_count;
  595. dconf->ps->value = calloc (dconf->ps->count, sizeof (* dconf->ps->value));
  596. if (dconf->ps->value == NULL)
  597. {
  598. error (0, errno, "out of memory");
  599. free (dconf);
  600. return (NULL);
  601. }
  602. dconf->dspec = dspec;
  603. dconf->gain_adj = gain_adj;
  604. dconf->truncated = 0;
  605. dconf->average = 0;
  606. dconf->notched = 0;
  607. if (start_freq == -1)
  608. {
  609. start_freq = index_to_freq (0, dspec);
  610. }
  611. if (end_freq == -1)
  612. {
  613. end_freq = index_to_freq (dspec->prescaler_count, dspec);
  614. }
  615. for (i = 0; i < dspec->prescaler_count; ++ i)
  616. {
  617. double index_start_freq = index_to_freq (i, dspec);
  618. if (index_start_freq < start_freq || index_start_freq + PRESCALER_FREQ_WIDTH (dspec) > end_freq)
  619. {
  620. diff = 0;
  621. }
  622. else
  623. {
  624. old_val = tr_old->value [i];
  625. new_val = tr_new->value [i];
  626. diff = new_val - (old_val + dconf->gain_adj);
  627. }
  628. ps_val = amp_to_ps (diff, input_ps->value [i], dspec);
  629. if (ps_val > dspec->prescaler_max)
  630. {
  631. ps_val = dspec->prescaler_max;
  632. ++ dconf->truncated;
  633. }
  634. if (ps_val == 0)
  635. {
  636. ++ dconf->notched;
  637. }
  638. dconf->ps->value [i] = ps_val;
  639. dconf->average += ps_val;
  640. }
  641. dconf->average /= dspec->prescaler_count;
  642. return (dconf);
  643. }
  644. /*====================================================================*
  645. *
  646. *
  647. *
  648. *--------------------------------------------------------------------*/
  649. void print_config_stats (struct dev_config * dconf, FILE * fp)
  650. {
  651. fprintf (fp, "# Output Prescaler Information\n");
  652. fprintf (fp, "#\n");
  653. fprintf (fp, "# Average Prescaler Value: %f\n", dconf->average);
  654. fprintf (fp, "# Carriers Notched: %d\n", dconf->notched);
  655. fprintf (fp, "# AFE Gain Adjustment: %d dB\n", dconf->gain_adj);
  656. if (dconf->truncated)
  657. {
  658. fprintf (fp, "#\n");
  659. fprintf (fp, "# WARNING! Actual gain is lower than desired gain for %d carriers!\n", dconf->truncated);
  660. fprintf (fp, "# The overall AFE gain may need to be increased.\n");
  661. }
  662. fprintf (fp, "#\n");
  663. }
  664. /*====================================================================*
  665. *
  666. *
  667. *
  668. *--------------------------------------------------------------------*/
  669. void print_config (struct dev_config * dconf, FILE * fp)
  670. {
  671. unsigned i;
  672. for (i = 0; i < dconf->ps->count; ++ i)
  673. {
  674. fprintf (fp, "%08d %08x\n", i, dconf->ps->value [i]);
  675. }
  676. }
  677. /*====================================================================*
  678. *
  679. *
  680. *
  681. *--------------------------------------------------------------------*/
  682. int set_tx_gain_6400 (struct _file_ * pib, int gain)
  683. {
  684. uint8_t gain_value;
  685. uint8_t gain_enable;
  686. if (lseek (pib->file, GAIN_ENABLE_OFFSET_6400, SEEK_SET) != GAIN_ENABLE_OFFSET_6400)
  687. {
  688. return (-1);
  689. }
  690. switch (gain)
  691. {
  692. case - 6:
  693. gain_value = 0x05;
  694. break;
  695. case - 4:
  696. gain_value = 0x03;
  697. break;
  698. case - 2:
  699. gain_value = 0x01;
  700. break;
  701. case 0:
  702. gain_value = 0x00;
  703. break;
  704. case 2:
  705. case 4:
  706. case 6:
  707. gain_value = gain;
  708. break;
  709. default:
  710. error (0, 0, "invalid gain value: %d", gain);
  711. return (-1);
  712. }
  713. if (gain_value == 0)
  714. {
  715. gain_enable = 0;
  716. }
  717. else
  718. {
  719. gain_enable = 1;
  720. }
  721. if (write (pib->file, & gain_enable, sizeof (gain_enable)) != 1)
  722. {
  723. error (1, errno, "could not enable output power level adjustment");
  724. }
  725. if (write (pib->file, & gain_value, sizeof (gain_value)) != 1)
  726. {
  727. error (1, errno, "could set output power level adjustment");
  728. }
  729. return (0);
  730. }
  731. /*====================================================================*
  732. *
  733. *
  734. *
  735. *--------------------------------------------------------------------*/
  736. int update_pib (const char * path, struct dev_config * dconf)
  737. {
  738. struct _file_ pib;
  739. pib.name = path;
  740. pib.file = open (path, O_BINARY | O_RDWR);
  741. if (pib.file == -1)
  742. {
  743. error (1, errno, "could not open PIB file %s for updating", path);
  744. }
  745. if (lightning_pib_file (& pib))
  746. {
  747. error (1, 0, "invalid PIB file %s", path);
  748. }
  749. if (psin (& pib, dconf))
  750. {
  751. error (1, 0, "could not read prescalers from PIB file %s", path);
  752. }
  753. if (lightning_pib_lock (& pib))
  754. {
  755. error (1, 0, "could not update checksum in PIB file %s", path);
  756. }
  757. if (dconf->dspec->set_tx_gain != NULL)
  758. {
  759. if (dconf->dspec->set_tx_gain (& pib, dconf->gain_adj) == -1)
  760. {
  761. error (1, 0, "could not update TX gain in PIB file %s", path);
  762. }
  763. }
  764. if (lightning_pib_lock (& pib))
  765. {
  766. error (1, 0, "could not update checksum in PIB file %s", path);
  767. }
  768. close (pib.file);
  769. return (0);
  770. }
  771. /*====================================================================*
  772. *
  773. *
  774. *
  775. *--------------------------------------------------------------------*/
  776. int ar7x00_psin (struct _file_ * pib, uint32_t value, uint32_t index)
  777. {
  778. off_t offset = AMP_PRESCALER_OFFSET + (index * 10 / 8);
  779. uint8_t bit_offset = (index * 10) % 8;
  780. uint16_t tmp;
  781. if (lseek (pib->file, offset, SEEK_SET) != offset)
  782. {
  783. return (-1);
  784. }
  785. if (read (pib->file, & tmp, sizeof (tmp)) != sizeof (tmp))
  786. {
  787. return (-1);
  788. }
  789. if (lseek (pib->file, offset, SEEK_SET) != offset)
  790. {
  791. return (-1);
  792. }
  793. value &= 0x03FF;
  794. tmp = LE16TOH (tmp);
  795. tmp &= ~ (0x03FF << bit_offset);
  796. tmp |= value << bit_offset;
  797. tmp = HTOLE16 (tmp);
  798. if (write (pib->file, & tmp, sizeof (tmp)) != sizeof (tmp))
  799. {
  800. return (-1);
  801. }
  802. return (0);
  803. }
  804. /*====================================================================*
  805. *
  806. *
  807. *
  808. *--------------------------------------------------------------------*/
  809. int psin (struct _file_ * pib, struct dev_config * dconf)
  810. {
  811. uint32_t value;
  812. unsigned limit;
  813. unsigned i;
  814. limit = pibscalers (pib);
  815. if ((limit != INT_CARRIERS) && (limit != AMP_CARRIERS))
  816. {
  817. error (1, 0, "Don't understand this PIB's prescaler format");
  818. }
  819. if (limit == INT_CARRIERS)
  820. {
  821. if (lseek (pib->file, INT_PRESCALER_OFFSET, SEEK_SET) != INT_PRESCALER_OFFSET)
  822. {
  823. error (1, errno, "Can't seek %s", pib->name);
  824. }
  825. }
  826. if (dconf->dspec->prescaler_count != limit)
  827. {
  828. error (1, 0, "PIB file type does not match device target type");
  829. }
  830. for (i = 0; i < limit; ++ i)
  831. {
  832. value = dconf->ps->value [i];
  833. if (limit == INT_CARRIERS)
  834. {
  835. if (write (pib->file, & value, sizeof (value)) != sizeof (value))
  836. {
  837. error (1, errno, "Can't save %s", pib->name);
  838. }
  839. }
  840. else if (limit == AMP_CARRIERS)
  841. {
  842. if (value & ~ 0x03FF)
  843. {
  844. error (1, errno, "Position %d has invalid prescaler value", i);
  845. }
  846. if (ar7x00_psin (pib, value, i))
  847. {
  848. error (1, errno, "Can't update %s", pib->name);
  849. }
  850. }
  851. }
  852. return (0);
  853. }
  854. /*====================================================================*
  855. *
  856. *
  857. *
  858. *--------------------------------------------------------------------*/
  859. int check_tx_gain_6400 (int gain_adj)
  860. {
  861. if ((gain_adj & 1) || gain_adj < - 6 || gain_adj > 6)
  862. {
  863. error (1, 0, "invalid gain adjustment, must be one of -6, -4, -2, 0, 2, 4, 6");
  864. return (-1);
  865. }
  866. return (0);
  867. }
  868. /*====================================================================*
  869. *
  870. *
  871. *
  872. *--------------------------------------------------------------------*/
  873. #ifdef WIN32
  874. double rint (double x)
  875. {
  876. if (x > 0)
  877. {
  878. return (floor (x + 0.5));
  879. }
  880. else if (x < 0)
  881. {
  882. return (ceil (x - 0.5));
  883. }
  884. return (x);
  885. }
  886. #endif
  887. /*====================================================================*
  888. *
  889. *
  890. *
  891. *--------------------------------------------------------------------*/
  892. struct prescalers * load_prescalers (const char * path, struct device_spec * d)
  893. {
  894. struct prescalers * ps;
  895. uint32_t i;
  896. FILE * fp;
  897. int c;
  898. uint32_t count;
  899. uint32_t index;
  900. uint32_t value;
  901. ps = malloc (sizeof (* ps));
  902. if (ps == NULL)
  903. {
  904. error (1, errno, "out of memory");
  905. }
  906. memset (ps, 0, sizeof (* ps));
  907. ps->count = d->prescaler_count;
  908. ps->value = calloc (sizeof (* ps->value), ps->count);
  909. if (path == NULL)
  910. {
  911. for (i = 0; i < ps->count; ++ i)
  912. {
  913. ps->value [i] = d->prescaler_unity;
  914. }
  915. return (ps);
  916. }
  917. fp = fopen (path, "rb");
  918. if (fp == NULL)
  919. {
  920. error (1, errno, "could not open %s", path);
  921. free (ps);
  922. return (NULL);
  923. }
  924. count = 0;
  925. while ((c = getc (fp)) != EOF)
  926. {
  927. if (isspace (c))
  928. {
  929. continue;
  930. }
  931. if ((c == '#') || (c == ';'))
  932. {
  933. do
  934. {
  935. c = getc (fp);
  936. }
  937. while (nobreak (c));
  938. continue;
  939. }
  940. index = 0;
  941. while (isdigit (c))
  942. {
  943. index *= 10;
  944. index += c - '0';
  945. c = getc (fp);
  946. }
  947. if (index != count)
  948. {
  949. error (1, ECANCELED, "Carrier %d out of order", index);
  950. }
  951. while (isblank (c))
  952. {
  953. c = getc (fp);
  954. }
  955. value = 0;
  956. while (isxdigit (c))
  957. {
  958. value *= 16;
  959. value += todigit (c);
  960. c = getc (fp);
  961. }
  962. if (count < d->prescaler_count)
  963. {
  964. ps->value [count] = value;
  965. }
  966. while (nobreak (c))
  967. {
  968. c = getc (fp);
  969. }
  970. count++;
  971. }
  972. if (count < d->prescaler_count)
  973. {
  974. error (1, 0, "Not enough prescalers");
  975. }
  976. else if (count > d->prescaler_count)
  977. {
  978. fprintf (stderr, "Warning: %d prescalers ignored at end of input file\n", count - d->prescaler_count);
  979. }
  980. fclose (fp);
  981. return (ps);
  982. }
  983. /*====================================================================*
  984. *
  985. *
  986. *
  987. *--------------------------------------------------------------------*/
  988. int replace_ps_around_notch (struct prescalers * ps, uint32_t width, uint32_t notch_start, uint32_t notch_end)
  989. {
  990. uint32_t i;
  991. uint32_t avg;
  992. /* replace notches on left of notch */
  993. if (notch_start > 0)
  994. {
  995. if (notch_start < width * 2)
  996. {
  997. fprintf (stderr, "error: not enough prescalers on left side of notch to copy data from\n");
  998. return (-1);
  999. }
  1000. avg = 0;
  1001. for (i = notch_start - 2 * width; i < notch_start - width; ++ i)
  1002. {
  1003. avg += ps->value [i];
  1004. }
  1005. avg /= width;
  1006. for (i = notch_start - width; i < notch_start; ++ i)
  1007. {
  1008. ps->value [i] = avg;
  1009. }
  1010. }
  1011. /* replace carriers on right of notch */
  1012. if (notch_end + 1 < ps->count)
  1013. {
  1014. if (notch_end + 2 * width > ps->count)
  1015. {
  1016. fprintf (stderr, "error: not enough prescalers on right side of notch to copy data from\n");
  1017. return (-1);
  1018. }
  1019. avg = 0;
  1020. for (i = notch_end + width; i < notch_end + 2 * width; ++ i)
  1021. {
  1022. avg += ps->value [i];
  1023. }
  1024. avg /= width;
  1025. for (i = notch_end; i < notch_end + width; ++ i)
  1026. {
  1027. ps->value [i] = avg;
  1028. }
  1029. }
  1030. return (0);
  1031. }
  1032. /*====================================================================*
  1033. *
  1034. *
  1035. *
  1036. *--------------------------------------------------------------------*/
  1037. int replace_prescalers_around_notches (struct prescalers * ps, uint32_t width)
  1038. {
  1039. uint32_t i = 0;
  1040. uint32_t notch_start,
  1041. notch_end;
  1042. int in_notch = 0;
  1043. for (i = 0; i < ps->count; i ++)
  1044. {
  1045. if (ps->value [i] != 0)
  1046. {
  1047. break;
  1048. }
  1049. }
  1050. for (; i < ps->count; ++ i)
  1051. {
  1052. // for (i = 0; i < ps->count; ++i) {
  1053. if (ps->value [i] == 0)
  1054. {
  1055. if (in_notch == 0)
  1056. {
  1057. in_notch = 1;
  1058. notch_start = i;
  1059. }
  1060. }
  1061. else
  1062. {
  1063. if (in_notch)
  1064. {
  1065. in_notch = 0;
  1066. notch_end = i;
  1067. if (replace_ps_around_notch (ps, width, notch_start, notch_end) == -1)
  1068. {
  1069. return (-1);
  1070. }
  1071. }
  1072. }
  1073. }
  1074. if (in_notch)
  1075. {
  1076. notch_end = i -1;
  1077. if (replace_ps_around_notch (ps, width, notch_start, notch_end) == -1)
  1078. {
  1079. return (-1);
  1080. }
  1081. }
  1082. return (0);
  1083. }
  1084. /*====================================================================*
  1085. *
  1086. * void show_prescalers (struct prescalers * ps, uint32_t scale);
  1087. *
  1088. *
  1089. *--------------------------------------------------------------------*/
  1090. void show_prescalers (struct prescalers * ps, unsigned scale)
  1091. {
  1092. uint32_t index;
  1093. for (index = 0; index < ps->count; index++)
  1094. {
  1095. uint32_t value = ps->value [index];
  1096. printf ("%04d %3d", index, value);
  1097. if (value)
  1098. {
  1099. printf (" ");
  1100. while (value > (scale >> 1))
  1101. {
  1102. printf ("#");
  1103. value -= scale;
  1104. }
  1105. }
  1106. printf ("\n");
  1107. }
  1108. printf ("\n");
  1109. return;
  1110. }
  1111. /*====================================================================*
  1112. *
  1113. *
  1114. *
  1115. *--------------------------------------------------------------------*/
  1116. void show_trace (struct trace * trace, unsigned scale)
  1117. {
  1118. signed index = trace->count;
  1119. for (index = 0; index < trace->count; index++)
  1120. {
  1121. printf ("%8.3f %8.3f", trace->freq [index], trace->value [index]);
  1122. printf ("\n");
  1123. }
  1124. printf ("\n");
  1125. return;
  1126. }
  1127. #endif