KM3NeT CLB  2.0
KM3NeT CLB v2 Embedded Software
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
edfa-eau.c
1 /*
2  * KM3NeT CLB v2 Firmware
3  *
4  * Copyright 2015 KM3NeT Collaboration
5  *
6  * All Rights Reserved.
7  *
8  *
9  * File : edaf-eau.c
10  * Created : 16 feb 2015
11  * Author : Riccardo Travaglini
12  */
13 
14 #include <stddef.h>
15 #include "kernel/tm.h"
16 #include "kernel/err.h"
17 #include "string.h"
18 #include "assert.h"
19 #include <util/float.h>
20 #include <util/convert.h>
21 
22 
23 #include "drv/uart/edfa-eau.h"
24 
25 
26 // #define EDFASIM
27 
28 #define EDFA_TIMEOUT_MS 2000
29 
30 #define FULL_CMD_MAX_LENGTH 30
31 
32 
33 
34 static char _retEdfaCmdBuf[EDFA_MAX_RET_LEN];
35 
36 
37 
38 #ifdef EDFASIM
39 #include <stdio.h>
40 static char _cmdBuf[20];
41 static char status[20]="sta: 000000000\r";
42 static bool bemi = 0;
43 
44 char * strstr(const char *in, const char *str);
45 char * strcat(char *s, const char *append);
46 #else
47 static int _EdfaCursor = 0;
48 #endif
49 
50 static const CnvParams _int = CNV_DEFAULT;
51 
52 int atoi_mult(const char* s, int decimals, bool trunc_nRound);
53 
54 
55 /*
56 rx a char from the edfa uart
57 */
58 bool _edfaIn(char* c)
59 {
60  if(bfEmpty(EDFA_UART->rxfifo))return false;
61 
62  __irqDisable();
63  bfRead(EDFA_UART->rxfifo,(uint8_t*) c);
64  __irqEnable();
65 #ifdef EDFADEBUG
66  printf("rx -> %c\n",*c);
67 #endif
68  return true;
69 }
70 
71 /*
72 send a char to the edfa uart
73 */
74 void _edfaOut(int c)
75 {
76  suartTx(EDFA_UART,c);
77 #ifdef EDFADEBUG
78  printf("tx -> %c\n",c);
79 #endif
80 }
81 
82 /*
83 send a string to the edfa uart
84 */
85 void _edfaputs (const char * string)
86 {
87 #ifndef EDFASIM
88  _edfaOut(' '); // puts >1 blanks at the beginning to wakeup the rs-232 driver (FMC mezzanine issue due to MAX3227 autopowerdown)
89  _edfaOut(' ');
90  _edfaOut(' ');
91  while(*string != '\0')
92  {
93  _edfaOut(*string++);
94  }
95  _edfaOut('\r'); // EDFA needs a carrige return at the end of the command
96 #else
97  int i=0;
98  while(*string != '\0' && i < 20){
99  _cmdBuf[i] = *string;
100  i++;
101  string++;
102  }
103  if(i < 20)_cmdBuf[i] = '\0';
104 #endif
105  return;
106 }
107 
108 /*
109 receive command return, put it into the _retEdfaCmdBuf buffer; set error if incomplete (== no \r) after timeout
110 */
111 bool _edfaRxCommand()
112 {
113 #ifndef EDFASIM
114  char c;
115  uint32_t to = timeOutInit(EDFA_TIMEOUT_MS);
116  bool ok ;
117  while (1)
118  {
119  ok = _edfaIn(&c);
120  if(ok){
121  if (c >= ' ' && c <= '~' && _EdfaCursor < (EDFA_MAX_RET_LEN - 1) )
122  {
123  _retEdfaCmdBuf[_EdfaCursor++] = c;
124  }
125  else if ( c == '\r') // EDFA sends a carriage return at the end of the response
126  {
127 /* _retEdfaCmdBuf[_EdfaCursor] = '\r'; */
128  _retEdfaCmdBuf[_EdfaCursor] = '\0'; /* remove carriage return and terminate string*/
129  if (_EdfaCursor > 0){
130  _EdfaCursor = 0;
131  return true;
132  }
133  }
134  }
135  if (timeOut(to)) {
137  return false;
138  }
139  }
140  return false;
141 #else
142  int ic;
143  if(strstr(_cmdBuf,"sta"))strcpy(_retEdfaCmdBuf,status);
144  else if(strstr(_cmdBuf,"emon")){
145  strcpy(_retEdfaCmdBuf,"EMON\0");
146  strcpy(status,"STA:100696068\0");
147  bemi = 1;
148  }
149  else if(strstr(_cmdBuf,"emoff")){
150  strcpy(_retEdfaCmdBuf," EMOFF\0");
151  strcpy(status,"STA:000000000\0");
152  bemi = 0;
153  }
154  else if(strstr(_cmdBuf,"rop")){
155  strcpy(_retEdfaCmdBuf," rop: 6.1\0");
156  }
157  else if(strstr(_cmdBuf,"rip")){
158  strcpy(_retEdfaCmdBuf," rip:-2.0345\0");
159  }
160  else if(strstr(_cmdBuf,"rdc1")){
161  strcpy(_retEdfaCmdBuf,"rdc1:2184\0");
162  }
163  else if(strstr(_cmdBuf,"rct")){
164  strcpy(_retEdfaCmdBuf,"rct:28.9\0");
165  }
166  else if(strstr(_cmdBuf,"apc")){
167  if(!bemi)strcpy(_retEdfaCmdBuf,"apc\0");
168  else strcpy(_retEdfaCmdBuf,"ERR: Emission is on\0");
169  }
170  else if(strstr(_cmdBuf,"sps")){
171  strcpy(_retEdfaCmdBuf,"sps:\0");
172  ic = strstr(_cmdBuf, "sps") - _cmdBuf;
173  ic += strlen("sps");
174  strcat(_retEdfaCmdBuf,_cmdBuf+ic);
175  }
176  else if(strstr(_cmdBuf,"rps")){
177  strcpy(_retEdfaCmdBuf,"rps: 7.30\0");
178  }
179  else if(strstr(_cmdBuf,"rmp")){
180  strcpy(_retEdfaCmdBuf,"rmp:10.5\0");
181  }
182 #ifndef _EDFA_NOAGC
183  else if(strstr(_cmdBuf,"agc")){
184  if(!bemi)strcpy(_retEdfaCmdBuf,"agc\0");
185  else strcpy(_retEdfaCmdBuf,"ERR: Emission is on\0");
186  }
187  else if(strstr(_cmdBuf,"sgs")){
188  strcpy(_retEdfaCmdBuf,"sgs:\0");
189  ic = strstr(_cmdBuf, "sgs") - _cmdBuf;
190  ic += strlen("sgs");
191  strcat(_retEdfaCmdBuf,_cmdBuf+ic);
192  }
193  else if(strstr(_cmdBuf,"rgs")){
194  strcpy(_retEdfaCmdBuf,"rgs: 16.4\0");
195  }
196  else if(strstr(_cmdBuf,"rop")){
197  strcpy(_retEdfaCmdBuf,"rop:26.1\0");
198  }
199  else if(strstr(_cmdBuf,"rmg")){
200  strcpy(_retEdfaCmdBuf,"rmg:32.0\0");
201  }
202  else if(strstr(_cmdBuf,"rng")){
203  strcpy(_retEdfaCmdBuf,"rng:10.4\0");
204  }
205 #endif
206  else if(strstr(_cmdBuf,"rmt")){
207  strcpy(_retEdfaCmdBuf,"rmt:73.0\0");
208  }
209  else if(strstr(_cmdBuf,"rmc")){
210  strcpy(_retEdfaCmdBuf,"rmc:2500\0");
211  }
212  else if(strstr(_cmdBuf,"rpn")){
213  strcpy(_retEdfaCmdBuf,"RPN: P60-000280\0");
214  }
215  else if(strstr(_cmdBuf,"rfv")){
216  strcpy(_retEdfaCmdBuf,"RFV: 1.0.114\0");
217  }
218  else if(strstr(_cmdBuf,"rdate")){
219  strcpy(_retEdfaCmdBuf,"RDATE: MAY 12, 2009\0");
220  }
221  else if(strstr(_cmdBuf,"rsn")){
222  strcpy(_retEdfaCmdBuf,"RSN: FA100625\0");
223  }
224  else strcpy(_retEdfaCmdBuf,"BCMD\0");
225  return true;
226 #endif
227 }
228 
229 
230 
231 /*
232  communication with edfa is case insensitive, so I decide to covert all to lowercase
233 */
234 void stolower(char *s)
235 {
236  for(; *s; s++)
237  if(('A' <= *s) && (*s <= 'Z'))
238  *s = 'a' + (*s - 'A');
239 }
240 
241 
242 /*
243 parse response: if = "bcmd" => unknown commad
244  needs comamd echoed back
245  if command needs reponse => it check for comma before response
246 */
247 bool _checkEdfaRet(const char* cmd , bool hasRet, char **ptrRet)
248 {
249  char* rt;
250  size_t len = strlen(cmd);
251  stolower(_retEdfaCmdBuf);
252 
253 
254  if( strstr(_retEdfaCmdBuf,"bcmd")){ // BCMD response (not case sensitive)
256  return false;
257  }
258  else{
259  rt = strstr(_retEdfaCmdBuf,cmd);
260  if(rt == 0){
261 
262  rt = strstr(_retEdfaCmdBuf,"err"); // cmd "apc" can return "err"
263  if(rt == 0){
265  return false;
266  }
267  else {
268  *ptrRet = rt;
269  return true;
270  }
271  }
272  else if(hasRet){
273  if(*(rt+len) != ':'){ // rt e' all'inizio di cmd => tipo rt+=strlen(cmd)
275  return false;
276  }
277  else{
278  // To keep context in command
279  //rt += len+1;
280  //while(*rt == ' '){rt++;};
281  *ptrRet = rt;
282  return true;
283  }
284  }
285  else return true;
286  }
287 
288 }
289 
290 /*
291 genric command tx and response rx with no arguments
292 */
293 bool edfaCmd(const char* cmd, bool hasRet, char** ret)
294 {
295  _edfaputs(cmd);
296  if(!_edfaRxCommand())return false;
297  return _checkEdfaRet(cmd ,hasRet,ret);
298 
299 }
300 
301 /*
302 genric command tx and response rx with arguments
303 */
304 bool edfaCmdArg(const char* cmd, const char* arg, bool hasRet, char** ret)
305 {
306  char fullcmd[FULL_CMD_MAX_LENGTH];
307  size_t lencmd = strlen(cmd);
308  size_t lenarg = strlen(arg);
309  if(lencmd + lenarg + 1 >= FULL_CMD_MAX_LENGTH){
311  return false;
312  }
313 
314  strcpy (fullcmd,cmd);
315  strcat (fullcmd," ");
316  strcat (fullcmd, arg);
317 
318  _edfaputs(fullcmd);
319  if(!_edfaRxCommand())return false;
320  return _checkEdfaRet(cmd ,hasRet,ret);
321 
322 }
323 
324 
325 bool edfaReadStatus(bool* emission,bool* startup)
326 {
327  char* rtString;
328  int ilast=0;
329  int tens = 1;
330  int istatus = 0;
331  if(!edfaCmd("sta",true,&rtString))return false;
332  while(rtString[ilast] != '\0'){ilast++;} // point to end of the string
333 
334  while(rtString[ilast] != ' ' && rtString[ilast] != ':'){ // the string is the 32-bit status value in decimal -> converted here
335  ilast--;
336  if(rtString[ilast] >= '0' && rtString[ilast] <= '9') istatus += (rtString[ilast]-'0') * tens;
337  tens *= 10;
338  }
339 
340  *emission = ((istatus >> 2) & 0x1) == 0x1 ? true: false;
341  *startup = ((istatus >> 7) & 0x1) == 0x1 ? true: false;;
342  return true;
343 }
344 
345 bool edfaEmOn()
346 {
347  return edfaCmd("emon",false,NULL);
348 }
349 
350 bool edfaEmOff()
351 {
352  return edfaCmd("emoff",false,NULL);
353 }
354 
355 
356 bool edfaReadCompOutPw(char** retString)
357 {
358  return edfaCmd("rop",true,retString);
359 }
360 
361 bool edfaReadCompInPw(char** retString)
362 {
363  return edfaCmd("rip",true,retString);
364 }
365 
366 bool edfaReadPumpDiodeCur(char** retString)
367 {
368  return edfaCmd("rdc",true,retString);
369 }
370 
371 bool edfaReadTemp(char** retString)
372 {
373  return edfaCmd("rct",true,retString);
374 }
375 
376 bool edfaSetAPCMode(char** retString)
377 {
378  return edfaCmd("apc",false,retString);
379 }
380 
381 bool edfaSetCompOutPw(const char* s_dbm, char** retString)
382 {
383 
384 
385  return edfaCmdArg("sps",s_dbm,true,retString);
386 }
387 
388 bool edfaReadCompPwSet(char** retString)
389 {
390  return edfaCmd("rps",true,retString);
391 }
392 
393 bool edfaReadMaxCompOutPw(char** retString)
394 {
395  return edfaCmd("rmp",true,retString);
396 }
397 
398 #ifndef _EDFA_NOAGC
399 bool edfaSetAGCMode(char** retString)
400 {
401  return edfaCmd("agc",false,retString);
402 }
403 
404 bool edfaSetGainSet(const char* s_db, char** retString)
405 {
406 
407  return edfaCmdArg("sgs",s_db,true,retString);
408 }
409 
410 bool edfaReadGainSet(char** retString)
411 {
412  return edfaCmd("rgs",true,retString);
413 }
414 
415 bool edfaReadActGain(char** retString)
416 {
417  return edfaCmd("rop",true,retString);
418 }
419 
420 bool edfaReadMaxGain(char** retString)
421 {
422  return edfaCmd("rmg",true,retString);
423 }
424 bool edfaReadMinGain(char** retString)
425 {
426  return edfaCmd("rng",true,retString);
427 }
428 #endif
429 
430 bool edfaReadMaxTemp(char** retString)
431 {
432  return edfaCmd("rmt",true,retString);
433 }
434 
435 bool edfaReadMaxPumpDiodeCur(char** retString)
436 {
437  return edfaCmd("rmc",true,retString);
438 }
439 bool edfaReadPart(char** retString)
440 {
441  return edfaCmd("rpn",true,retString);
442 }
443 
444 bool edfaReadFwVer(char** retString)
445 {
446  return edfaCmd("rfv",true,retString);
447 }
448 
449 bool edfaReadDate(char** retString)
450 {
451  return edfaCmd("rdate",true,retString);
452 }
453 
454 bool edfaReadSerial(char** retString)
455 {
456  return edfaCmd("rsn",true,retString);
457 }
458 
459 /*void atofixed(const char* s, EdfaFixedPoint* rf)
460 {
461  assert(rf);
462 int point_seen,d;
463 int minus = 1;
464  rf->integer = 0;
465  rf->mantissa = 0;
466 
467 
468  while(*s == ' '){s++;}
469  if (*s == '-'){
470  s++;
471  minus = -1;
472  }
473  for (point_seen = 0; *s; s++){
474  if (*s == '.'){
475  point_seen = 1;
476  continue;
477  }
478  d = *s - '0';
479  if (d >= 0 && d <= 9){
480  if (point_seen) {
481  rf-> mantissa = rf-> mantissa * 10 + d ;
482  }
483  else rf->integer = rf->integer * 10 + d;
484  }
485  }
486  rf->integer *= minus;
487 }
488 */
489 static int quick_pow10(int n)
490 {
491  static int pow10[10] = {
492  1, 10, 100, 1000, 10000,
493  100000, 1000000, 10000000, 100000000, 1000000000
494  };
495 
496  return pow10[n];
497 }
498 
499 int atoi_mult(const char* s, int decimals, bool trunc_nRound){
500 
501 assert(decimals+1 < 10);
502  int left = 0, right = 0, sign =1, digit = 0;
503  while(*s == ' '){s++;}
504  if (*s == '-'){
505  s++;
506  sign = -1;
507  };
508  for (int point_seen = 0; *s; s++){
509  if (*s == '.'){
510  point_seen = 1;
511  continue;
512  };
513  int d = *s - '0';
514  if (d >= 0 && d <= 9){
515  if (point_seen){
516  digit++;
517  right = right*10 + d;
518  if(!trunc_nRound && digit > decimals){
519  if(d >= 5)right++;
520  break;
521  }
522  }
523  else {
524  left = left*10 + d;
525  }
526  if(digit == decimals && trunc_nRound)break;
527  };
528  };
529  return sign * left * quick_pow10(decimals) + sign * right * quick_pow10(decimals - digit);
530 };
531 
532 /*int32_t fixed2ScaledInt(EdfaFixedPoint fix,unsigned int scaleFact)
533 {
534  return fix->integer * scaleFact +
535 }*/
536 
537 /*void edfaOutputPower(EdfaFixedPoint* rf)
538 {
539  char *pRet;
540  if(!edfaReadCompOutPw(&pRet)){
541  rf->integer = -1;
542  rf->mantissa=0;
543  }
544  else{
545  atofixed(pRet,rf);
546  }
547 }*/
548 int edfaOutputPower()
549 {
550  char *pRet;
551  if(!edfaReadCompOutPw(&pRet)){
552  return -1;
553  }
554  else{
555  return atoi_mult(pRet,3,true);
556  }
557 }
558 
559 int edfaInputPower()
560 {
561  char *pRet;
562  if(!edfaReadCompInPw(&pRet)){
563  return -1;
564  }
565  else{
566  return atoi_mult(pRet,3,true);
567  }
568 }
569 
570 int edfaReadSetpoint()
571 {
572  char *pRet;
573  if(!edfaReadCompPwSet(&pRet)){
574  return -1;
575  }
576  else{
577  return atoi_mult(pRet,3,true);
578  }
579 }
580 
581 int edfaPumpCur()
582 {
583  char *pRet;
584  if(!edfaReadPumpDiodeCur(&pRet)){
585  return -1;
586  }
587  else{
588  return atoi_mult(pRet,3,true);
589  }
590 }
591 
592 
593 int edfaTemp()
594 {
595  char *pRet;
596  if(!edfaReadTemp(&pRet)){
597  return -1;
598  }
599  else{
600  return atoi_mult(pRet,3,true);
601  }
602 }
603 
604 void edfaWriteSetpoint(f32_t val, char** retString)
605 {
606  char c_integer[21];
607  char c_mantissa[10];
608  int ilen;
609 
610  int integer,mantissa;
611 
612  integer = fltInt(val);
613  mantissa = fltFrac(val,8);
614 
615  if( cnvFormatI(integer , c_integer,_int) == 0
616  || cnvFormatU(mantissa , c_mantissa,_int) == 0){
618  return;
619  }
620  strcat(c_integer,".");
621  strcat(c_integer,c_mantissa);
622 
623  edfaSetCompOutPw(c_integer, retString);
624 
625 }
626 
627 bool edfaDbgCmdReply(const char * cmd, char ** retString) {
628  return edfaCmd(cmd, true, retString);
629 }
630 
631 bool edfaDbgCmd(const char * cmd) {
632  return edfaCmd(cmd, false, NULL);
633 }
634 
#define E_EDFA_TOOLONG
command parameter too long
Definition: edfa-eau.h:45
int cnvFormatU(int32_t input, char *output, CnvParams params)
Formats an unsigned integer into a character buffer.
Definition: convert.c:137
static bool bfEmpty(ByteFifo *const bf)
Returns whether or not the byte-fifo is empty.
Definition: bytefifo.h:72
#define E_EDFA_NOCOMMA
no comma when required in response
Definition: edfa-eau.h:42
static void __irqEnable()
Enabled IRQ&#39;s on a global level.
Definition: lm32.h:75
int32_t fltInt(f32_t value)
Returns the integer part of the floating point value.
Definition: float.c:102
#define E_EDFA_INVALID
invalid
Definition: edfa-eau.h:48
int cnvFormatI(int32_t input, char *output, CnvParams params)
Formats a signed integer into a character buffer.
Definition: convert.c:160
#define E_EDFA_TIMEOUT
Receive timeout.
Definition: edfa-eau.h:32
uint32_t fltFrac(f32_t value, int decimals)
Returns the fractional part of the floating point with the specified number of decimals.
Definition: float.c:96
static void __irqDisable()
Disables IRQ&#39;s on a global level.
Definition: lm32.h:62
#define E_EDFA_BDCM
bd command
Definition: edfa-eau.h:35
Special library for primitive IEEE 754 floating point handling without dragging all float support alo...
#define CNV_DEFAULT
Default conversion/formatting parameters (base 10).
Definition: convert.h:47
static uint32_t timeOutInit(uint32_t msec)
Initializes a timeout with the specified no of msecs.
Definition: tm.h:53
static bool timeOut(uint32_t to)
Checks whether or not the timeout has expired.
Definition: tm.h:77
Manages the global system error.
This structure provides information about formatting and parsing.
Definition: convert.h:37
Simple timer functions.
uint32_t f32_t
32 bit representation for float.
Definition: float.h:30
#define E_EDFA_NOCMD
no echoed command back
Definition: edfa-eau.h:39
bool bfRead(ByteFifo *const bf, uint8_t *const b)
Reads a byte from the byte-fifo.
Definition: bytefifo.c:28
bool errSet(uint32_t code, const char *error, const char *name)
Sets an error.
#define ERROR(CODE,...)
Expands an error code to an error code with a description (if ERROR_W_DESCR is declared).
bool suartTx(SUART_Descriptor *desc, char c)
Transmits a character.
Definition: suart.c:58
EDFA-EAU (30-C3-20-C) Uart driver.
bool edfaDbgCmdReply(const char *cmd, char **retString)
Execute an EDFA debug command, and returns the reply.
Definition: edfa-eau.c:627
This module implements parsing and formating of strings and integers.
bool edfaDbgCmd(const char *cmd)
Execute an EDFA debug command w/o a reply.
Definition: edfa-eau.c:631