Programmation application web pour la platforme redpitaya

Programmation application web pour la platforme redpitaya - Electronique, domotique, DIY

Marsh Posté le 12-05-2024 à 11:59:19    

Bonjour tout le monde,

 

Il y a quelque semaines, j'ai découvert une nouvelle plateforme de développement open-source qui me permettara de remplacer les instruments couteux et volumineux de mon laboratoire, la redptitaya. Je me suis procuré le modèle STEMlab 125-14 qui propose deux entrées de 125Msps 14 bits et de deux sorties 14 bits, un FPGA Xilinx Zynq 7010 couplé à un processeur ARM Cortex-A9 double-coralité et offre un accès à distance, avec une interface utilisateur d'application en ligne accessible via Ethernet ou Wi-Fi. Pour faire fonctionner tout ce petit monde la plateforme à créer un système d'exploitation basé sur un système linux ubuntu (actuellement j’utilise la dernière version du système RedPitaya_OS_2.00-30_stable.img).
https://redpitaya.com/wp-content/uploads/elementor/thumbs/Red_Pitaya_STEMlab_125-14-p91a8dpiccj0fiqw3w96w8ax4av9fms8og1vxtmhls.jpg
Puisque cette carte ne peut pas gérer d'écran, il est essentiel de concevoir une interface utilisateur web fonctionnant sur un navigateur internet pour contrôler l'application back-end, compilé et installé sur le système d'exploitation. Tout ce qui fonctionne dans le navigateur est le frontend. C'est la partie qui permet de visualiser les données à l'écran ou modifier certains paramètres pour ajuster les paramètres à l'intérieur de l'application back-end.
La partie front-end de l'application utilise la technologie HTML5, CSS3 et Javascript pour créer l'interface web.
La partie back-end est programmé en C ou en C++ et peut nécessité du Vérilog pour manipuler le FPGA.
L'échange d'information entre le C++ et le Javascript s’effectue par des fichiers JSON, pour transmettre les valeurs des paramètres ou des signaux échantillonnés et générés. Pour que cela fonctionne un serveur NGINX fonctionne en continue. (Si vous voulez plus d'information surfez sur la documentation de la plateforme au lien suivant: https://redpitaya.readthedocs.io.)

 

Pour me familiariser avec le système, j’essaie de développer une application me permettant de faire un générateur de signaux sur deux sorties DAC 14 bits et oscilloscope sur les deux entrées ADC 14 bits. Mon application devra être capable de configurer la forme, l'amplitude, la fréquence des signaux à générer et d'afficher dans un plot jQuery la forme des signaux échantillonnées et générée. Pour l'instant je me contente de faire rentrer les signaux générés sur les entrées de la carte en connectant une sortie à une entrée par un câble coaxiale.

 

A ce stade du développement, j'ai commencé à réaliser une petite interface web m'affichant un menu dans un bandeau vertical pour choisir et configurer les channels et un plot jQuery pour afficher les signaux. De plus j'ai aussi programmer la partie back-end en C++ pour créer les paramètres nécessaire et des fonctions pour manipuler les convertisseurs 14 bits. Pour plus de simplicité la plateforme possède quelque libraire simplifiant la transmissions et la réception des sockets pour échanger les paramètres et d'autre librairie permettant de configurer et échantillonner les signaux DAC et ADC.

 

Le cœur de mon problème est que l'interface front-end refuse catégoriquement de se connecter à l'interface back-end, ce dont je ne comprend pas, puisque ce processus doit se faire automatiquement par la librairie C++ de la carte. Le code Javascipt doit juste vérifié si le socket a était accpété en le demandant au serveur NGNIX. Cependant le serveur me renvoie continuellement l'erreur suivante:  "Can not load application. Error: -1 app.js:120:14"

 

J’espère que quelqu’un connait le système pour me partager ses connaissances sur ce système et que peut-être cela répondra à mon problème.

 

Si vous voulez lire mon code pour trouver peut-être une incohérence, ou tester mon code sur votre redpitaya, le voici ci-dessous:

 

La partie back-end:
fichier src/hardwareInfo.h

Code :
  1. #pragma one
  2. #include <cstdio>
  3. #include <cstdlib>
  4. #include <cstdint>
  5. #include "rp.h"
  6. typedef enum {
  7.     RP_125_14,
  8.     RP_250_12,
  9.     RP_125_14_4CH,
  10.     RP_122_16
  11. } models_t;
  12. uint8_t getADCChannels();
  13. uint8_t getDACChannels();
  14. float getDACGainCh1();
  15. uint32_t getADCRate();
  16. // return current CPU clock
  17. double getClock();
  18. models_t getModel();
 

fichier hardwareInfo.cpp

Code :
  1. #include <ctime>
  2. #include <unistd.h>
  3. #include <sys/types.h>
  4. #include <sys/sysinfo.h>
  5. #include <string>
  6. #include "hardwareInfo.h"
  7. #include "rp.h"
  8. #include "rp_hw-calib.h"
  9. #include "log.h"
  10. uint8_t getADCChannels() {
  11.     uint8_t c = 0;
  12.     if (rp_HPGetFastADCChannelsCount(&c) != RP_HP_OK){
  13.         Error("Can't get fast ADC channels count\n" );
  14.         exit(-1);
  15.     }
  16.     return c;
  17. }
  18. uint8_t getDACChannels() {
  19.     uint8_t c = 0;
  20.     if (rp_HPGetFastDACChannelsCount(&c) != RP_HP_OK){
  21.         Error("Can't get fast DAC channels count\n" );
  22.         exit(-1);
  23.     }
  24.     return c;
  25. }
  26. float getDACGainCh1() {
  27.     float c = 0;
  28.     if (rp_HPGetFastDACGain(RP_CH_1, &c) != RP_HP_OK){
  29.         Error("Can't get fast DAC gain\n" );
  30.         exit(-1);
  31.     }
  32.     return c;
  33. }
  34. uint32_t getADCRate() {
  35.     uint32_t c = 0;
  36.     if (rp_HPGetBaseFastADCSpeedHz(&c) != RP_HP_OK){
  37.         Error("Can't get fast ADC rate\n" );
  38.         exit(-1);
  39.     }
  40.     return c;
  41. }
  42. double getClock() {
  43.     struct timespec tp;
  44.     clock_gettime(CLOCK_REALTIME, &tp);
  45.     return ((double)tp.tv_sec * 1000.f) + ((double)tp.tv_nsec / 1000000.f);
  46. }
  47. models_t getModel() {
  48.     rp_HPeModels_t c = STEM_125_14_v1_0;
  49.     if (rp_HPGetModel(&c) != RP_HP_OK){
  50.         Error("Can't get board model\n" );
  51.         exit(-1);
  52.     }
  53.     switch (c)
  54.     {
  55.         case STEM_125_10_v1_0:
  56.         case STEM_125_14_v1_0:
  57.         case STEM_125_14_v1_1:
  58.         case STEM_125_14_LN_v1_1:
  59.         case STEM_125_14_Z7020_v1_0:
  60.         case STEM_125_14_Z7020_LN_v1_1:
  61.             return RP_125_14;
  62.         case STEM_122_16SDR_v1_0:
  63.         case STEM_122_16SDR_v1_1:
  64.             return RP_122_16;
  65.         case STEM_125_14_Z7020_4IN_v1_0:
  66.         case STEM_125_14_Z7020_4IN_v1_2:
  67.         case STEM_125_14_Z7020_4IN_v1_3:
  68.             return RP_125_14_4CH;
  69.         case STEM_250_12_v1_0:
  70.         case STEM_250_12_v1_1:
  71.         case STEM_250_12_v1_2:
  72.         case STEM_250_12_v1_2a:
  73.         case STEM_250_12_v1_2b:
  74.             return RP_250_12;
  75.         default:
  76.             Error("Can't get board model\n" );
  77.             exit(-1);
  78.     }
  79.     return RP_125_14;
  80. }
 

fichier src/log.h

Code :
  1. #pragma once
  2. #include <string>
  3. #include <fstream>
  4. #include <iostream>
  5. #include <memory>
  6. #include <stdexcept>
  7. const std::string log_filename = "/tmp/exemple.txt";
  8. template<typename ... Args>
  9. inline std::string string_format( const std::string& format, Args ... args )
  10. {
  11.     int size_s = std::snprintf( nullptr, 0, format.c_str(), args ... ) + 1; // Extra space for '\0'
  12.     if( size_s <= 0 ){ throw std::runtime_error( "Error during formatting." ); }
  13.     auto size = static_cast<size_t>( size_s );
  14.     std::unique_ptr<char[]> buf( new char[ size ] );
  15.     std::snprintf( buf.get(), size, format.c_str(), args ... );
  16.     return std::string( buf.get(), buf.get() + size - 1 ); // We don't want the '\0' inside
  17. }
  18. template<typename ... Args>
  19. void Log(const std::string& format, Args ... args) {
  20.     std::ofstream file(log_filename.c_str(), std::ios::in | std::ios::out | std::ios::app);
  21.     if (file.is_open()) {
  22.         file << string_format(format, args ...);
  23.         file.close();
  24.     }
  25. }
  26. template<typename ... Args>
  27. void Error(const std::string& format, Args ... args) {
  28.     std::ofstream file(log_filename.c_str(), std::ios::in | std::ios::out | std::ios::app);
  29.     if (file.is_open()) {
  30.         file << "[Error] " << string_format(format, args ...);
  31.         file.close();
  32.     }
  33. }
 

Fichier src/main.h

Code :
  1. #pragma once
  2. #include <DataManager.h>
  3. #include <CustomParameters.h>
  4. #include "rpApp.h"
  5. #define SIGNAL_SIZE_DEFAULT    1024 //Signal size
  6. #define SIGNAL_UPDATE_INTERVAL 1
  7. #define PARAMS_UPDATE_INTERVAL 1
  8. #define RW CBaseParameter::RW
  9. #define RWSA CBaseParameter::RWSA
  10. #define RO CBaseParameter::RO
  11. #define FPGA_UPDATE_NONE 0
  12. #define FPGA_UPDATE 1
  13. #define SFLOAT(VAR, size, value) CFloatSignal VAR(#VAR, size, value);
  14. #define SFLOAT2(VAR, size, value) CFloatSignal VAR[2] = {{#VAR "1", size, value}, {#VAR "2", size, value}}
  15. #define SFLOAT4(VAR, size, value) CFloatSignal VAR[4] = {{#VAR "1", size, value}, {#VAR "2", size, value}, {#VAR "3", size, value}, {#VAR "4", size, value}}
  16. #define PBOOL(VAR, ...) CBooleanParameter VAR(#VAR, __VA_ARGS__)
  17. #define PBOOL2(VAR, ...) CBooleanParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  18. #define PBOOL4(VAR, ...) CBooleanParameter VAR[4] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}, {#VAR "3", __VA_ARGS__}, {#VAR "4", __VA_ARGS__}}
  19. #define PINT(VAR, ...) CIntParameter VAR(#VAR, __VA_ARGS__)
  20. #define PINT2(VAR, ...) CIntParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  21. #define PINT4(VAR, ...) CIntParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}, {#VAR "3", __VA_ARGS__},{#VAR "4", __VA_ARGS__}}
  22. #define PUINT(VAR, ...) CUIntParameter VAR(#VAR, __VA_ARGS__)
  23. #define PUINT2(VAR, ...) CUIntParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  24. #define PUINT4(VAR, ...) CUIntParameter VAR[4] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__},{#VAR "3", __VA_ARGS__},{#VAR "4", __VA_ARGS__}}
  25. #define PFLOAT(VAR, ...) CFloatParameter VAR(#VAR, __VA_ARGS__)
  26. #define PFLOAT2(VAR, ...) CFloatParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  27. #define PFLOAT4(VAR, ...) CFloatParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}, {#VAR "3", __VA_ARGS__},{#VAR "4", __VA_ARGS__}}
  28. #define PDOUBLE(VAR, ...) CDoubleParameter VAR(#VAR, __VA_ARGS__)
  29. #define PDOUBLE2(VAR, ...) CDoubleParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  30. #define PDOUBLE4(VAR, ...) CDoubleParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}, {#VAR "3", __VA_ARGS__},{#VAR "4", __VA_ARGS__}}
  31. #define PSTRING(VAR, ...) CStringParameter VAR(#VAR, __VA_ARGS__)
  32. #define PSTRING2(VAR, ...) CStringParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__}}
  33. #define PSTRING4(VAR, ...) CStringParameter VAR[2] = {{#VAR "1", __VA_ARGS__},{#VAR "2", __VA_ARGS__},{#VAR "3", __VA_ARGS__},{#VAR "4", __VA_ARGS__}}
  34. #ifdef __cplusplus
  35. extern "C" {
  36. #endif
  37. /* Parameters description structure - must be the same for all RP controllers */
  38. typedef struct rp_app_params_s {
  39.     char  *name;
  40.     float  value;
  41.     int    fpga_update;
  42.     int    read_only;
  43.     float  min_val;
  44.     float  max_val;
  45. } rp_app_params_t;
  46. //Rp app functions
  47. const char *rp_app_desc(void);
  48. int rp_app_init(void);
  49. int rp_app_exit(void);
  50. int rp_set_params(rp_app_params_t *p, int len);
  51. int rp_get_params(rp_app_params_t **p);
  52. int rp_get_signals(float ***s, int *sig_num, int *sig_len);
  53. #ifdef __cplusplus
  54. }
  55. #endif
 

Fichier src/main.cpp

Code :
  1. #include <fstream>
  2. #include <math.h>
  3. #include <stdio.h>
  4. #include <string.h>
  5. #include <stdlib.h>
  6. #include <time.h>
  7. #include <unistd.h>
  8. #include "rp.h"
  9. #include "rpApp.h"
  10. #include "log.h"
  11. #include "hardwareInfo.h"
  12. #include "main.h"
  13. /********************************************************/
  14. /* Global variables                                     */
  15. /********************************************************/
  16. bool g_appState = false;
  17. rp_acq_decimation_t g_decimation = RP_DEC_8192;
  18. int g_timeDelay = 1000000;   // delay us to start acquiring fresh data
  19. uint32_t g_buffer_size = ADC_BUFFER_SIZE;
  20. float *g_buffer = (float *)malloc(g_buffer_size * sizeof(float));
  21. PBOOL(APP_RUN, RW, true, FPGA_UPDATE_NONE);
  22. /********************************************************/
  23. /* Signals variables                                    */
  24. /********************************************************/
  25. SFLOAT2(OSC_SIGNAL_CH, SIGNAL_SIZE_DEFAULT, 0.0f);
  26. SFLOAT2(GEN_SIGNAL_CH, SIGNAL_SIZE_DEFAULT, 0.0f);
  27. SFLOAT2(MATH_SIGNAL_CH, SIGNAL_SIZE_DEFAULT, 0.0f);
  28. /********************************************************/
  29. /* Oscilloscope parameters from here on                 */
  30. /********************************************************/
  31. PFLOAT(TIME_SCALE, RWSA, 0.1, 0, 0, 1000);
  32. PFLOAT(VOLT_SCALE, RWSA, 0.1, 0, 0, 10);
  33. PBOOL2(OSC_SHOW_CH, RW, false, FPGA_UPDATE);
  34. PBOOL2(OSC_INVERT_CH, RW, false, FPGA_UPDATE);
  35. //User probe attenuation setting for channel 1 & 2:
  36. // 0 - 1x
  37. // 1 - 10x
  38. // 2 - 100x
  39. PINT2(OSC_PROB_CH, RW, 0, FPGA_UPDATE, 0, 2);
  40. // User jumper gain setting for channel 1 & 2:
  41. // 0 - high gain (-1/1 [V] Full-scale)
  42. // 1 - low gain (-20/20 [V] Full-scale)
  43. PINT2(OSC_GAIN_CH, RW, 0, FPGA_UPDATE, 0, 1);
  44. // Trigger mode:
  45. // 0 - Auto
  46. // 1 - Normal
  47. // 2 - Single
  48. PINT(OSC_TRIGGER_MODE, RW, 0, FPGA_UPDATE, 0, 2);
  49. // Trigger source:
  50. // 0 - ChA
  51. // 1 - ChB
  52. // 2 - ext
  53. PINT(OSC_TRIGGER_SOURCE, RW, 0, FPGA_UPDATE, 0, 2);
  54. // Trigger Edge:
  55. // 0 - Rising
  56. // 1 - Falling
  57. PINT(OSC_TRIGGER_EDGE, RW, 0, FPGA_UPDATE, 0, 1);
  58. PFLOAT(OSC_TRIGGER_DELAY, RW, 0, FPGA_UPDATE, -1e7,  1e7);
  59. PFLOAT(OSC_TRIGGER_LEVEL, RW, 0, FPGA_UPDATE, -2, 2);
  60. PFLOAT2(OSC_MEAS_MIN_CH, RO, 0, FPGA_UPDATE, -1000, 1000);
  61. PFLOAT2(OSC_MEAS_MAX_CH, RO, 0, FPGA_UPDATE, -1000, 1000);
  62. PFLOAT2(OSC_MEAS_AMP_CH, RO, 0, FPGA_UPDATE, -1000, 1000);
  63. PFLOAT2(OSC_MEAS_AVG_CH, RO, 0, FPGA_UPDATE, -1000, 1000); // Average
  64. PFLOAT2(OSC_MEAS_FREQ_CH, RO, 0, FPGA_UPDATE, -1000, 1000); // Frequency
  65. PFLOAT2(OSC_MEAS_PER_CH, RO, 0, FPGA_UPDATE, -1000, 1000); // Periode
  66. /********************************************************/
  67. /* Generator parameters from here on                    */
  68. /********************************************************/
  69. PBOOL2(GEN_SHOW_CH, RW, false, FPGA_UPDATE_NONE);
  70. PBOOL2(GEN_ENABLE_CH, RW, false, FPGA_UPDATE);
  71. PFLOAT2(GEN_AMPLITUDE_CH, RW, 0.8, FPGA_UPDATE, -2.0, 2.0);
  72. PFLOAT2(GEN_FREQUENCY_CH, RW, 1000, FPGA_UPDATE, 1, 50e6);
  73. PFLOAT2(GEN_OFFSET_CH, RW, 0, FPGA_UPDATE, -1.0, 1.0);
  74. PINT2(GEN_WAVEFORM_CH, RW, 0, FPGA_UPDATE, 0, 8);
  75. PINT2(GEN_MODE_CH, RW, 0, FPGA_UPDATE, 0, 2);
  76. PFLOAT2(GEN_DUTY_CYCLE_CH, RW, 25.0, FPGA_UPDATE, 0.0, 100.0);
  77. PFLOAT2(GEN_BURST_COUNT_CH, RW, 1, FPGA_UPDATE, 0, 1000);
  78. PFLOAT2(GEN_BURST_PER_CH, RW, 1, FPGA_UPDATE, 0, 50e6);
  79. PFLOAT2(GEN_BURST_REP_CH, RW, 1, FPGA_UPDATE, 0, 1000);
  80. /********************************************************/
  81. /* Math parameters from here on                         */
  82. /********************************************************/
  83. PBOOL2(MATH_SHOW_CH, RW, false, FPGA_UPDATE_NONE);
  84. // Operator
  85. // 0 - Addition
  86. // 1 - Soustration
  87. // 2 - produit
  88. // 3 - absolute
  89. // 4 - invert
  90. PINT2(MATH_OPERATOR_CH, RW, 0, FPGA_UPDATE, 0, 5);
  91. PINT2(MATH_FIRST_SIGN_CH, RW, 0, FPGA_UPDATE, 0, 3);
  92. PINT2(MATH_SECOND_SIGN_CH, RW, 0, FPGA_UPDATE, 0, 3);
  93. PFLOAT2(MATH_CONST_CH, RW, 1.0, FPGA_UPDATE, -10.0, 10.0);
  94. // Save signals
  95. // 0 - json format
  96. // 1 - csv format
  97. // 2 - wav format
  98. // 3 - dat format
  99. PINT2(SAVE_FORMAT, RW, 0, FPGA_UPDATE_NONE, 0, 3);
  100. // ------------------------------------------------------------
  101. // Generator functions
  102. // ------------------------------------------------------------
  103. int startGenerator(rp_channel_t _channel, rp_waveform_t _wave, float _frequency, float _amplitude, float _offset, float _duty) {
  104. int ret = RP_OK;
  105. ret |= rp_GenReset();
  106. ret |= rp_GenOffset(_channel,_offset);
  107. ret |= rp_GenAmp(_channel,_amplitude);
  108. ret |= rp_GenWaveform(_channel,_wave);
  109. ret |= rp_GenFreq(_channel,_frequency);
  110. if (_wave == RP_WAVEFORM_PWM)
  111.  rp_GenDutyCycle(_channel, _duty);
  112. ret |= rp_GenOutEnable(_channel);
  113. ret |= rp_GenTriggerOnly(_channel);
  114. return ret;
  115. }
  116. bool UpdateGenChParams(uint8_t ch) {
  117. if (GEN_SHOW_CH[ch].IsNewValue()) {
  118.  GEN_SHOW_CH[ch].Update();
  119. }
  120. bool conf_osc = false;
  121. if (GEN_ENABLE_CH[ch].IsNewValue()) {
  122.  GEN_ENABLE_CH[ch].Update();
  123.  conf_osc = true;
  124. }
  125. if (GEN_WAVEFORM_CH[ch].IsNewValue()) {
  126.  GEN_WAVEFORM_CH[ch].Update();
  127.  conf_osc = true;
  128. }
  129. if (GEN_FREQUENCY_CH[ch].IsNewValue()) {
  130.  GEN_FREQUENCY_CH[ch].Update();
  131.  conf_osc = true;
  132. }
  133. if (GEN_AMPLITUDE_CH[ch].IsNewValue()) {
  134.  GEN_AMPLITUDE_CH[ch].Update();
  135.  conf_osc = true;
  136. }
  137. if (GEN_OFFSET_CH[ch].IsNewValue()) {
  138.  GEN_OFFSET_CH[ch].Update();
  139.  conf_osc = true;
  140. }
  141. if (GEN_DUTY_CYCLE_CH[ch].IsNewValue()) {
  142.  GEN_DUTY_CYCLE_CH[ch].Update();
  143.  conf_osc = true;
  144. }
  145. if (GEN_MODE_CH[ch].IsNewValue()) {
  146.  GEN_MODE_CH[ch].Update();
  147.  conf_osc = true;
  148. }
  149. if (g_appState == true) {
  150.  return conf_osc;
  151. } else {
  152.  return false;
  153. }
  154. }
  155. // Generator configurations
  156. void configureGenerator() {
  157. for (uint8_t i = 0; 2; i++) {
  158.  if (UpdateGenChParams(i) && GEN_ENABLE_CH.Value()) {
  159.   bool enable;
  160.   rp_GenOutIsEnabled((rp_channel_t) i, &enable);
  161.   if (!enable) rp_GenOutEnable((rp_channel_t) i);
  162.   if (startGenerator(
  163.    (rp_channel_t) i,
  164.    (rp_waveform_t) GEN_WAVEFORM_CH[i].Value(),
  165.    (float) GEN_FREQUENCY_CH[i].Value(),
  166.    (float) GEN_AMPLITUDE_CH[i].Value(),
  167.    (float) GEN_OFFSET_CH[i].Value(),
  168.    (float) GEN_DUTY_CYCLE_CH[i].Value()) != RP_OK)
  169.   {
  170.    Error("Start generator failed\n" );
  171.   }
  172.  } else {
  173.   bool enable;
  174.   rp_GenOutIsEnabled((rp_channel_t) i, &enable);
  175.   if (enable) rp_GenOutDisable((rp_channel_t) i);
  176.  }
  177. }
  178. Log("Generator parameters updated\n" );
  179. }
  180. // ------------------------------------------------------------
  181. // Scope functions
  182. // ------------------------------------------------------------
  183. int analyseData(int mul, uint8_t ch) {
  184. return RP_OK;
  185. }
  186. // update signal on channel 1 & 2
  187. int OscAcquisitionSignal(void)
  188. {
  189. int ret = RP_OK;
  190. auto model = getModel();
  191. if (model == RP_122_16){
  192.  Error("Not available on 122-16\n" );
  193.  return 0;
  194. }
  195. for (uint8_t i=0; i<2; i++) {
  196.  int mul = OSC_PROB_CH[i].Value();
  197.  if (OSC_SHOW_CH[i].Value()) {
  198.   ret |= rp_AcqGetOldestDataV((rp_channel_t) i, &g_buffer_size, g_buffer);
  199.   ret |= analyseData(mul, i);
  200.   for (uint32_t j = 0; j < SIGNAL_SIZE_DEFAULT; j++) {
  201.    if (OSC_SHOW_CH[i].Value()) {
  202.     if (OSC_SIGNAL_CH[i].GetSize() != g_buffer_size)
  203.      OSC_SIGNAL_CH[i].Resize(g_buffer_size);
  204.     OSC_SIGNAL_CH[i][j] = g_buffer[j] * mul; // - (VOLT_SCALE.Value() + OSC_MEAS_AVG_CH[0].Value());
  205.    }
  206.   }
  207.  }
  208. }
  209. return ret;
  210. }
  211. // ------------------------------------------------------------
  212. //
  213. // ------------------------------------------------------------
  214. // get decimation
  215. void get_decimation() {
  216.     float cal_dec = (getADCRate() / ADC_BUFFER_SIZE) * TIME_SCALE.Value() / 100;   // 100 = 10(whole range)/1000(to second)
  217.    
  218.     /* Find optimal decimation setting */
  219.     if(cal_dec < 1) {
  220.         g_decimation = RP_DEC_1;
  221.         g_timeDelay = 131;
  222.     } else if(cal_dec < 8) {
  223.         g_decimation = RP_DEC_8;
  224.         g_timeDelay = 1048;
  225.     } else if(cal_dec < 64) {
  226.         g_decimation = RP_DEC_64;
  227.         g_timeDelay = 8388;
  228.     } else if(cal_dec < 1024) {
  229.         g_decimation = RP_DEC_1024;
  230.         g_timeDelay = 134200;
  231.     } else if(cal_dec < 8192) {
  232.         g_decimation = RP_DEC_8192;
  233.         g_timeDelay = 1000000;
  234.     } else if(cal_dec < 65536) {
  235.         g_decimation = RP_DEC_65536;
  236.         g_timeDelay = 8589000;
  237.     } else {
  238.         g_decimation = RP_DEC_8192;
  239.         g_timeDelay = 1000000;
  240.     }
  241. }
  242. // set acquire
  243. void set_acquire() {
  244. rp_AcqReset();
  245. rp_AcqSetDecimation(g_decimation);
  246. // rp_AcqSetAveraging(true);
  247. // rp_AcqSetTriggerLevel(RP_T_CH_1, 0);
  248. // rp_AcqSetTriggerDelay(ADC_BUFFER_SIZE/2.0);
  249. for (uint8_t i = 0; i < 2; i++) {
  250.  if(OSC_GAIN_CH[i].Value()) {
  251.   rp_AcqSetGain((rp_channel_t) i, RP_HIGH);
  252.  } else {
  253.   rp_AcqSetGain((rp_channel_t) i, RP_LOW);
  254.  }
  255. }
  256. rp_AcqStart();
  257. /* After acquisition is started some time delay is needed in order to acquire fresh samples in to buffer*/
  258. /* Here we have used time delay of one second but you can calculate exact value taking in to account buffer*/
  259. /*length and smaling rate. Time scale/length of a buffer for decimation 8 takes 1.049 ms to full 16 KS in buffer*/
  260. usleep(g_timeDelay);
  261. // rp_AcqSetTriggerSrc(RP_TRIG_SRC_CHA_PE);
  262. }
  263. // Run or stop APP
  264. void run_app() {
  265. // Init generator
  266. rp_GenReset();
  267. configureGenerator();
  268. // Init acquire signal
  269. get_decimation();
  270. set_acquire();
  271. g_appState = true;
  272. }
  273. void stop_app() {
  274.     g_appState = false;
  275. // stop acqusition
  276. rp_AcqStop();
  277. // Disabe generator
  278. for (uint8_t i = 0; i < 2; i++)
  279.  rp_GenOutDisable((rp_channel_t) i);
  280. }
  281. // ------------------------------------------------------------
  282. // RP Application functions
  283. // ------------------------------------------------------------
  284. //Application description
  285. const char *rp_app_desc(void)
  286. {
  287. return (const char *)"Red Pitaya scope and genarator application.\n";
  288. }
  289. //Application init
  290. int rp_app_init(void)
  291. {
  292. g_appState = false;
  293. srand(time(0));
  294. Log("Loading scope and genarator application\n" );
  295. // Initialization of API
  296. if (rpApp_Init() != RP_OK) {
  297.  Error("Red Pitaya API init failed!\n" );
  298.  return EXIT_FAILURE;
  299. } else {
  300.  Log("Red Pitaya API init success!\n" );
  301. }
  302. CDataManager::GetInstance()->SetParamInterval(SIGNAL_UPDATE_INTERVAL);
  303. CDataManager::GetInstance()->SetSignalInterval(PARAMS_UPDATE_INTERVAL);
  304. CDataManager::GetInstance()->SendAllParams();
  305. if (APP_RUN.Value() == true) {
  306.  run_app();
  307. }
  308. return 0;
  309. }
  310. //Application exit
  311. int rp_app_exit(void)
  312. {
  313. stop_app();
  314. rpApp_Release();
  315. free(g_buffer);
  316. Log("Unload Red Pitaya application\n----------------------------------------\n" );
  317. return 0;
  318. }
  319. //Set parameters
  320. int rp_set_params(rp_app_params_t *p, int len)
  321. {
  322. return 0;
  323. }
  324. //Get parameters
  325. int rp_get_params(rp_app_params_t **p)
  326. {
  327. return 0;
  328. }
  329. //Get signals
  330. int rp_get_signals(float ***s, int *sig_num, int *sig_len)
  331. {
  332. return 0;
  333. }
  334. //Update signals
  335. void UpdateSignals(void)
  336. {
  337. if (g_appState == true) {
  338.  OscAcquisitionSignal();
  339. }
  340. }
  341. //Update parameters
  342. void UpdateParams(void) {}
  343. void OnNewParams(void)
  344. {
  345. APP_RUN.Update();
  346.     // Run or stop APP
  347. if (APP_RUN.Value() == true) {
  348.  run_app();
  349. } else {
  350.  stop_app();
  351. }
  352. TIME_SCALE.Update();
  353. bool gain_is_new = false;
  354. for (uint8_t i = 0; i < 2; i++) {
  355.  OSC_SHOW_CH[i].Update();
  356.  OSC_INVERT_CH[i].Update();
  357.  OSC_PROB_CH[i].Update();
  358.  gain_is_new |= OSC_GAIN_CH[i].IsNewValue();
  359. }
  360. // change decimation if needed
  361.     if(g_appState && (TIME_SCALE.IsNewValue() || gain_is_new)) {
  362.        
  363.  VOLT_SCALE.Update();
  364.         rp_acq_decimation_t curr_dec = g_decimation;
  365.         get_decimation();
  366.         if(curr_dec != g_decimation || gain_is_new) {
  367.   for (uint8_t i = 0; i < 2; i++)
  368.    OSC_GAIN_CH[i].Update();
  369.             g_appState = false;
  370.            
  371.             rp_AcqStop();
  372.             set_acquire();
  373.             // rp_AcqSetDecimation(dec);
  374.             g_appState = true;
  375.         }
  376.     }
  377. configureGenerator();
  378. }
  379. void OnNewSignals(void) {}
  380. void PostUpdateSignals(void) {}
 

le fichier de compilation des sources c/c++
[i]Fichier src/Makefile

Code :
  1. CXX=$(CROSS_COMPILE)g++
  2. RM=rm
  3. INSTALL_DIR ?= /opt/redpitaya
  4. CXXSOURCES=main.cpp
  5. INCLUDE =  -I$(INSTALL_DIR)/include
  6. INCLUDE += -I$(INSTALL_DIR)/include/api2
  7. INCLUDE += -I$(INSTALL_DIR)/include/apiApp
  8. INCLUDE += -I$(INSTALL_DIR)/rp_sdk
  9. INCLUDE += -I$(INSTALL_DIR)/rp_sdk/libjson
  10. LIBS = -L$(INSTALL_DIR)/lib
  11. LIBS += -L$(INSTALL_DIR)/rp_sdk
  12. COMMON_FLAGS+=-Wall -fPIC -Os -s -w
  13. CFLAGS+=$(COMMON_FLAGS) $(INCLUDE)
  14. CXXFLAGS+=$(COMMON_FLAGS) -std=c++11 $(INCLUDE)
  15. LDFLAGS = -shared $(COMMON_FLAGS) $(LIBS)
  16. LDFLAGS+= -Wl,--whole-archive,--no-as-needed
  17. LDFLAGS+= -lcryptopp -lrpapp -lrp_sdk -lrp
  18. LDFLAGS+= -Wl,--no-whole-archive
  19. COBJECTS=$(CSOURCES:.c=.o)
  20. CXXOBJECTS=$(CXXSOURCES:.cpp=.o)
  21. OBJECTS=$(COBJECTS) $(CXXOBJECTS)
  22. OUT_DIR=../
  23. C_OUT_NAME=$(OUT_DIR)controllerhf.so
  24. all: make_c_app
  25. clean: clean_c_app
  26. make_c_app: $(OBJECTS)
  27. $(CXX) -o $(C_OUT_NAME) $(OBJECTS) $(CFLAGS) $(LDFLAGS)
  28. clean_c_app:
  29. $(RM) -f $(C_OUT_NAME) $(OBJECTS)
  


La partie front-end
Fichier index.html

Code :
  1. <!--
  2. *
  3. * Red Pitaya scope application
  4. *
  5. * (c) Red Pitaya http://www.redpitaya.com
  6. *
  7. -->
  8. <!DOCTYPE html>
  9. <html lang="en">
  10. <head>
  11.     <meta http-equiv="content-type" content="text/html; charset=utf-8"></meta>
  12.     <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
  13.    
  14. <title>Red Pitaya</title>
  15.     <link href="../assets/loader.css?" rel="stylesheet" type="text/css">
  16. <link rel="stylesheet" href="css/style.css?">
  17.     <script src="../assets/jquery/jquery-2.1.3.min.js" onerror="location.reload()"></script>
  18. <script src="../assets/jquery/jquery.flot.js" onerror="location.reload()"></script>
  19. <script src="../assets/bootstrap/js/bootstrap.min.js"onerror="location.reload()"></script>   <!-- this line have to be after jquery-->
  20.     <script src="../assets/pako.js?1" onerror="location.reload()"></script>
  21. <script src="js/guiHandler.js"></script>
  22.     <script src="js/app.js"></script>
  23. </head>
  24. <body>
  25.     <!-- Icon de chargement de la page -->
  26. <div id = "loader-wrapper">
  27.  <div id="loader"></div>
  28.  <div id="loader-desc">LOADING...</div>
  29. </div>
  30. <!-- En-tête de la page -->
  31. <header>
  32.  <button class="header-button buttonL" id="return-button">
  33.   <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  34.    <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
  35.    <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
  36.    <g id="SVGRepo_iconCarrier">
  37.     <path d="M15 5L9 12L15 19" stroke="#202020" stroke-width="1.5" stroke-linecap="round"
  38.      stroke-linejoin="round"></path>
  39.    </g>
  40.   </svg>
  41.  </button>
  42.  <button class="header-button buttonL" id="home-button">
  43.   <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  44.    <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
  45.    <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
  46.    <g id="SVGRepo_iconCarrier">
  47.     <path d="M22 22L2 22" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  48.     <path d="M2 11L10.1259 4.49931C11.2216 3.62279 12.7784 3.62279 13.8741 4.49931L22 11"
  49.      stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  50.     <path d="M15.5 5.5V3.5C15.5 3.22386 15.7239 3 16 3H18.5C18.7761 3 19 3.22386 19 3.5V8.5"
  51.      stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  52.     <path d="M4 22V9.5" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  53.     <path d="M20 22V9.5" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  54.     <path
  55.      d="M15 22V17C15 15.5858 15 14.8787 14.5607 14.4393C14.1213 14 13.4142 14 12 14C10.5858 14 9.87868 14 9.43934 14.4393C9 14.8787 9 15.5858 9 17V22"
  56.      stroke="#202020" stroke-width="1.5"></path>
  57.     <path
  58.      d="M14 9.5C14 10.6046 13.1046 11.5 12 11.5C10.8954 11.5 10 10.6046 10 9.5C10 8.39543 10.8954 7.5 12 7.5C13.1046 7.5 14 8.39543 14 9.5Z"
  59.      stroke="#202020" stroke-width="1.5"></path>
  60.    </g>
  61.   </svg>
  62.  </button>
  63.  <button class="header-button buttonR" id="info-button">
  64.   <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  65.    <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
  66.    <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
  67.    <g id="SVGRepo_iconCarrier">
  68.     <circle cx="12" cy="12" r="10" stroke="#202020" stroke-width="1.5"></circle>
  69.     <path d="M10.125 8.875C10.125 7.83947 10.9645 7 12 7C13.0355 7 13.875 7.83947 13.875 8.875C13.875 9.56245 13.505 10.1635 12.9534 10.4899C12.478 10.7711 12 11.1977 12 11.75V13"
  70.      stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  71.     <circle cx="12" cy="16" r="1" fill="#202020"></circle>
  72.    </g>
  73.   </svg>
  74.  </button>
  75.  <div id="header-title">Scope & Generator</div>
  76. </header>
  77. <section>
  78.  <div id="left-section">
  79.   <div id="placeholder"></div>
  80.  </div>
  81.  <div id="right-section">
  82.   <div id="setup-navbar">
  83.    <button class="setup-navbar-button" id="input-1-button">Input 1</button>
  84.    <button class="setup-navbar-button" id="input-2-button">Input 2</button>
  85.    <button class="setup-navbar-button" id="output-1-button">Output 1</button>
  86.    <button class="setup-navbar-button" id="output-2-button">Output 2</button>
  87.    <button class="setup-navbar-button" id="math-1-button">Math 1</button>
  88.    <button class="setup-navbar-button" id="math-2-button">Math 2</button>
  89.    <button class="setup-navbar-button" id="trigger-button">Trigger</button>
  90.    <button class="setup-navbar-button" id="save-button">Save</button>
  91.   </div>
  92.   <!-- Menu pour un signal en entrée -->
  93.   <div class="setup-params" id="setup-params-input">
  94.    <div class="param-flex-container" id="show-container">
  95.     <label for="show">Show</label>
  96.     <input type="checkbox" id="OSC_SHOW_CH" name="show">
  97.    </div>
  98.    <div class="param-flex-container" id="invert-container">
  99.     <label for="invert">Invert</label>
  100.     <input type="checkbox" id="OSC_INVERT_CH" name="invert">
  101.    </div>
  102.    <div>Attenuation</div>
  103.    <!-- Attenuation avec la sonde de mesure -->
  104.    <div class="param-flex-container" id="prob-container">
  105.     <label for="prob">Probe</label>
  106.     <select name="prob" id="OSC_PROB_CH">
  107.      <option selected value="0">1</option>
  108.      <option value="1">10</option>
  109.      <option value="2">100</option>
  110.     </select>
  111.    </div>
  112.    <!-- Position du switch sur l'entrée de la red pitaya -->
  113.    <div class="param-flex-container" id="gain-container">
  114.     <label for="gain">Input</label>
  115.     <select name="gain" id="OSC_GAIN_CH">
  116.      <option selected value="0">Low voltage</option>
  117.      <option value="1">High voltage</option>
  118.     </select>
  119.    </div>
  120.   </div>
  121.   <!-- Menu pour configurer un signal en sortie -->
  122.   <div class="setup-params" id="setup-params-output">
  123.    <div class="param-flex-container" id="enable-container">
  124.     <label for="enable">Enable</label>
  125.     <input type="checkbox" id="GEN_ENABLE_CH" name="enable">
  126.    </div>
  127.    <div class="param-flex-container" id="show-container">
  128.     <label for="show">Show</label>
  129.     <input type="checkbox" id="GEN_SHOW_CH" name="show">
  130.    </div>
  131.    <div class="param-flex-container" id="amplitude-container">
  132.     <label for="amplitude">Amplitude [V]:</label>
  133.     <input type="number" id="GEN_AMPLITUDE_CH" name="amplitude" step="0.01">
  134.    </div>
  135.    <div class="param-flex-container" id="frequency-container">
  136.     <label for="frequency">Frequency [Hz]:</label>
  137.     <input type="number" id="GEN_FREQUENCY_CH" name="frequency" step="0.01">
  138.    </div>
  139.    <div class="param-flex-container" id="offset-container">
  140.     <label for="offset">Offset [V]:</label>
  141.     <input type="number" id="GEN_OFFSET_CH" name="offset" step="0.01">
  142.    </div>
  143.    <div class="param-flex-container" id="waveform-container">
  144.     <label for="waveform">Waveform :</label>
  145.     <select name="waveform" id="GEN_WAVEFORM_CH">
  146.      <option selected value="0">Sine</option>
  147.      <option value="2">Triangle</option>
  148.      <option value="1">Square</option>
  149.      <option value="6">PWM</option>
  150.      <option value="3">Ramp up</option>
  151.      <option value="4">Ramp Down</option>
  152.      <option value="5">DC positif</option>
  153.      <option value="8">DC negatif</option>
  154.      <!--<option value="7">Arbitrary</option>-->
  155.      <!--<option value="9">Sweep</option>-->
  156.     </select>
  157.    </div>
  158.    <div class="param-flex-container" id="mode-container">
  159.     <label for="mode">Mode :</label>
  160.     <select name="mode" id="GEN_MODE_CH">
  161.      <option selected value="0">Continious</option>
  162.      <option value="1">Burst</option>
  163.      <option value="2">Stream</option>
  164.     </select>
  165.    </div>
  166.    <div id="pwm-setup">
  167.     <div>PWM Options</div>
  168.     <div class="param-flex-container" id="duty-cycle-container">
  169.      <label for="duty-cycle">Duty Cycle [%]:</label>
  170.      <input type="number" id="GEN_DUTY_CYCLE_CH" name="duty-cycle" step="0.01">
  171.     </div>
  172.    </div>
  173.    <div id="burst-setup">
  174.     <div>Burst Options</div>
  175.     <div class="param-flex-container" >
  176.      <label for="burst-count">Burst Count :</label>
  177.      <input type="number" id="GEN_BURST_COUNT" name="burst-count" step="0.01">
  178.     </div>
  179.     <div class="param-flex-container" >
  180.      <label for="burst-periode">Burst Periode :</label>
  181.      <input type="number" id="GEN_BURST_PER" name="burst-periode" step="0.01">
  182.     </div>
  183.     <div class="param-flex-container" >
  184.      <label for="burst-repetition">Burst Repetition :</label>
  185.      <input type="number" id="GEN_BURST_REP" name="burst-repetition" step="0.01">
  186.     </div>
  187.    </div>
  188.                 <div id="sweep-setup">
  189.     <div>Sweep Options</div>
  190.     <!-- A compléter -->
  191.    </div>
  192.   </div>
  193.   <!-- Menu math -->
  194.   <div class="setup-params" id="setup-params-math">
  195.    <div class="param-flex-container" id="enable-container">
  196.     <label for="show">Show</label>
  197.     <input type="checkbox" id="MATH_SHOW_CH" name="show">
  198.    </div>
  199.    <div class="param-flex-container" id="operator-container">
  200.     <label for="operator">Operator :</label>
  201.     <select name="operator" id="MATH_OPERATOR_CH">
  202.      <option selected value="0">+</option>
  203.      <option value="1">-</option>
  204.      <option value="2">*</option>
  205.      <option value="3">abs</option>
  206.      <option value="4">invert</option>
  207.     </select>
  208.    </div>
  209.    <div class="param-flex-container" id="first-signal-container">
  210.     <label for="first-signal">First signal :</label>
  211.     <select name="first-signal" id="MATH_FIRST_SIGN_CH">
  212.      <option selected value="0">Input CH1</option>
  213.      <option value="1">Input CH2</option>
  214.      <option value="2">Output CH1</option>
  215.      <option value="3">Output CH2</option>
  216.     </select>
  217.    </div>
  218.    <div class="param-flex-container" id="second-signal-container">
  219.     <label for="second-signal">First signal :</label>
  220.     <select name="second-signal" id="MATH_SECOND_SIGN_CH">
  221.      <option selected value="0">Input CH1</option>
  222.      <option value="1">Input CH2</option>
  223.      <option value="2">Output CH1</option>
  224.      <option value="3">Output CH2</option>
  225.      <option value="4">Constant</option>
  226.     </select>
  227.    </div>
  228.    <div class="param-flex-container" id="second-signal-container">
  229.     <label for="constant">Constant :</label>
  230.     <input type="number" id="MATH_CONST_CH" name="constant" step="0.01">
  231.    </div>
  232.   </div>
  233.   <!-- Menu du trigger -->
  234.   <div class="setup-params" id="setup-params-trigger">
  235.                 <div>A compléter</div>
  236.   </div>
  237.   <!-- Menu pour sauvgrader les signaux affiché -->
  238.   <div class="setup-params" id="setup-params-save">
  239.                 <div>Save showed signals</div>
  240.    <div class="param-flex-container" id="save-container">
  241.     <label for="save-format">Format</label>
  242.     <select name="save-format" id="SAVE_FORMAT">
  243.      <option value="0">JSON</option>
  244.      <option selected value="1">CSV</option>
  245.      <option value="2">WAV</option>
  246.      <option value="3">DAT</option>
  247.     </select>
  248.    </div>
  249.    <div class="param-flex-container">
  250.     <button id="save-button" style="width: 100%;">Save</button>
  251.    </div>
  252.             </div>
  253.  </div>
  254. </section>
  255. <footer>
  256.  <button class="header-button buttonL">
  257.   <svg width="64px" height="64px" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
  258.    <g id="SVGRepo_bgCarrier" stroke-width="0"></g>
  259.    <g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g>
  260.    <g id="SVGRepo_iconCarrier">
  261.     <path d="M22 19H14M2 19H10" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  262.     <path d="M12 17V14" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  263.     <circle cx="12" cy="19" r="2" stroke="#202020" stroke-width="1.5"></circle>
  264.     <path
  265.      d="M2 11C2 9.34315 3.34315 8 5 8H19C20.6569 8 22 9.34315 22 11C22 12.6569 20.6569 14 19 14H5C3.34315 14 2 12.6569 2 11Z"
  266.      stroke="#202020" stroke-width="1.5"></path>
  267.     <path
  268.      d="M2 5C2 3.34315 3.34315 2 5 2H19C20.6569 2 22 3.34315 22 5C22 6.65685 20.6569 8 19 8H5C3.34315 8 2 6.65685 2 5Z"
  269.      stroke="#202020" stroke-width="1.5"></path>
  270.     <path d="M13 5L19 5" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  271.     <path d="M13 11L19 11" stroke="#202020" stroke-width="1.5" stroke-linecap="round"></path>
  272.     <circle cx="6" cy="5" r="1" fill="#202020"></circle>
  273.     <circle cx="6" cy="11" r="1" fill="#202020"></circle>
  274.    </g>
  275.   </svg>
  276.  </button>
  277.  <div id="footer-messages">
  278.   <div id="message-A">-</div>
  279.   <div id="message-B">-</div>
  280.   <div id="message-C">-</div>
  281.  </div>
  282. </footer>
  283. </body>
 

Fichier css/style.css

Code :
  1. :root {
  2. --header-color: #555;
  3. --header-color-hover: #999;
  4. --border-color: black;
  5. --right-section-color: #b6b6b6;
  6. }
  7. * {
  8. box-sizing: border-box;
  9. padding: 0;
  10. margin: 0;
  11. }
  12. body {
  13. font-family: Arial, Helvetica, sans-serif;
  14. display: flex;
  15. flex-direction: column;
  16. min-height: 100vh;
  17. /* Pour que le footer reste en bas */
  18. }
  19. button, input {
  20. overflow: hidden;
  21. cursor: pointer;
  22. border-width: 1;
  23. border-style: none;
  24. }
  25. button {
  26. color: black;
  27. border-color: var(--border-color);
  28. }
  29. /* ================================================== */
  30. header {
  31. height: 40px;
  32. background-color: var(--header-color);
  33. text-align: center;
  34. font-size: 24px;
  35. color: white;
  36. }
  37. #header-title {
  38. text-align: center;
  39. font-size: 28px;
  40. }
  41. .header-button {
  42. height: 40px;
  43. padding-left: 4px;
  44. padding-right: 4px;
  45. background-color: var(--header-color);
  46. }
  47. .header-button:hover {
  48. height: 40px;
  49. padding-left: 4px;
  50. padding-right: 4px;
  51. background-color: var(--header-color-hover);
  52. color: #444;
  53. }
  54. .header-button svg {
  55.     height: 95%; /* Redimensionne le logo à 70% de la hauteur du bouton */
  56.     display: block; /* Pour s'assurer que le SVG est centré verticalement */
  57.     margin: auto; /* Pour centrer le SVG horizontalement */
  58. margin-left: -12px;
  59. margin-right: -12px;
  60. }
  61. .buttonL {
  62. float: left;
  63. border-right: 1px solid var(--border-color); /* Seule la bordure droite est visible */
  64. }
  65. .buttonR {
  66. float: right;
  67. border-left: 1px solid var(--border-color); /* Seule la bordure gauche est visible */
  68. }
  69. /* ================================================== */
  70. section {
  71. flex: 1;
  72. /* Pour que la section s'étire sur tout l'espace restant */
  73. display: flex;
  74. }
  75. /* -------------------------------------------------- */
  76. #left-section {
  77. width: 70%;
  78. background-color: #f1f1f1;
  79. padding: 0px;
  80. }
  81. #placeholder {
  82. border: 0;
  83. background-color: #fff;
  84. /* Pour remplir l'espace disponible */
  85. width: 100%;
  86.     height: 100%;
  87. }
  88. /* -------------------------------------------------- */
  89. #right-section {
  90. width: 30%;
  91. background-color: var(--right-section-color);
  92. padding: 0px;
  93. }
  94. #setup-navbar {
  95. padding: 4px;
  96. overflow-x: scroll;
  97. overflow-y: hidden;
  98. background-color: #303030;
  99. }
  100. .setup-navbar-button {
  101. padding: 4px;
  102. margin: 0px;
  103. box-sizing: border-box;
  104. float: left;
  105. display: block;
  106. color: #f2f2f2;
  107. text-align: center;
  108. text-decoration: none;
  109. background-color: #303030;
  110. border-color: black;
  111. }
  112. /* Change color on hover */
  113. .setup-navbar-button:hover {
  114. background-color: #ddd;
  115. color: black;
  116. }
  117. .setup-navbar-button.active {
  118. background-color: #20a720;
  119. color: #f2f2f2;
  120. }
  121. .setup-navbar-button.active:hover {
  122. background-color: #aa0e0e;
  123. color: #f2f2f2;
  124. }
  125. .param-flex-container {
  126. display: flex;
  127. flex-wrap: nowrap;
  128. padding: 4px 8px 4px 8px;
  129. }
  130. .param-flex-container > * {
  131. width: 60%;
  132. text-align: center;
  133. }
  134. .param-flex-container > label {
  135. width: 40%;
  136. text-align: left;
  137. }
  138. /* ================================================== */
  139. footer {
  140. height: 40px;
  141. background-color: var(--header-color);
  142. padding: 0px;
  143. text-align: center;
  144. color: white;
  145. }
  146. #footer-messages {
  147. font-size: 10px;
  148. }
  149. /* ================================================== */
  150. /* Responsive layout - longueur fenêtre < 600px */
  151. @media (max-width: 600px) {
  152. #header-title {
  153.         text-align: center;
  154.         font-size: 18px;
  155.     }
  156.     section {
  157.         flex-direction: column; /* Passe en disposition verticale */
  158.     }
  159.     #left-section,
  160.     #right-section {
  161.         width: 100%; /* Les sections prennent toute la largeur */
  162.     }
  163. }
 

Fichier js/app.js

Code :
  1. // Frozen enum - Immutable
  2. const Waveform = Object.freeze({
  3. SINE  :0, //!< Wave form sine
  4. SQUARE  :1, //!< Wave form square
  5. TRIANGLE :2, //!< Wave form triangle
  6. RAMP_UP  :3, //!< Wave form sawtooth (/|)
  7. RAMP_DOWN :4, //!< Wave form reversed sawtooth (|\)
  8. DC   :5, //!< Wave form dc
  9. PWM   :6, //!< Wave form pwm
  10. //ARBITRARY :7, //!< Use defined wave form
  11. DC_NEG  :8, //!< Wave form negative dc
  12. //SWEEP  :9, //!< Wave form sweep
  13. });
  14. const GenMode = Object.freeze({
  15. CONTINUOUS :0, //!< Continuous signal generation
  16. BURST  :1, //!< Signal is generated N times, wher N is defined with rp_GenBurstCount method
  17. STREAM  :2 //!< User can continuously write data to buffer
  18. });
  19. const Menu = Object.freeze({
  20. CLOSE    :0,
  21. INPUT_CHANNEL_1  :1,
  22. INPUT_CHANNEL_2  :2,
  23. OUTPUT_CHANNEL_1 :3,
  24. OUTPUT_CHANNEL_2 :4,
  25. MATH_CHANNEL_1     :5,
  26. MATH_CHANNEL_2   :6,
  27. TRIGGER    :7,
  28. SAVE                :8
  29. });
  30. (function() {
  31.     if ("performance" in window == false) {
  32.         window.performance = {};
  33.     }
  34.     Date.now = (Date.now || function() { // thanks IE8
  35.         return new Date().getTime();
  36.     });
  37.     if ("now" in window.performance == false) {
  38.         var nowOffset = Date.now();
  39.         if (performance.timing && performance.timing.navigationStart) {
  40.             nowOffset = performance.timing.navigationStart
  41.         }
  42.         window.performance.now = function now() {
  43.             return Date.now() - nowOffset;
  44.         }
  45.     }
  46. })();
  47. (function(APP, $, unused) {
  48. // Params cache
  49. APP.params = {
  50.  shared: {},
  51.  local: {},
  52.  callback: {}
  53. };
  54. var length_display_signal = 1024*16;
  55. APP.signals = {
  56.  length_display: length_display_signal,
  57.  OSC_SIGNAL_CH1: Array(length_display_signal).fill(0),
  58.  OSC_SIGNAL_CH2: Array(length_display_signal).fill(0),
  59.  GEN_SIGNAL_CH1: Array(length_display_signal).fill(0),
  60.  GEN_SIGNAL_CH2: Array(length_display_signal).fill(0),
  61.  MATH_SIGNAL_CH1: Array(length_display_signal).fill(0),
  62.  MATH_SIGNAL_CH2: Array(length_display_signal).fill(0),
  63. };
  64. // App configuration
  65. APP.config = {};
  66. APP.config.app_id = 'exemple';
  67.     APP.config.client_id = undefined;
  68.     APP.config.server_ip = ''; // Leave empty on production, it is used for testing only
  69.     APP.config.start_app_url = window.location.origin + '/bazaar?start=' + APP.config.app_id;
  70.     APP.config.stop_app_url = window.location.origin + '/bazaar?stop=' + APP.config.app_id;
  71.     APP.config.socket_url = 'ws://' + window.location.host + '/wss'; // WebSocket server URI
  72. APP.config.previousPageUrl = '/';
  73.     // Other global variables
  74. APP.ws = null;
  75. APP.plot = {};
  76. APP.parameterStack = [];
  77. APP.signalStack = [];
  78. APP.parametersCache = {};
  79. // App state
  80. APP.state = {
  81.  socket_opened: false,
  82.  unexpected_closed: false,
  83.  processing: false,
  84.  parametersCache_isEmpty: false,
  85.  currentMenu: Menu.CLOSE,
  86.  currentChannel: 1,
  87.  running: false,
  88. };
  89. APP.startApp = function() {
  90.  $.get(
  91.    APP.config.start_app_url
  92.   )
  93.   .done(function(dresult) {
  94.    if (dresult.status == 'OK') {
  95.     try {
  96.      APP.connectWebSocket();
  97.      console.log("Load manager" );
  98.     } catch (e) {
  99.      APP.startApp();
  100.     }
  101.    } else if (dresult.status == 'ERROR') {
  102.     console.log(dresult.reason ? dresult.reason : 'Could not start the application (ERR1)');
  103.     APP.startApp();
  104.    } else {
  105.     console.log('Could not start the application (ERR2)');
  106.     APP.startApp();
  107.    }
  108.   })
  109.   .fail(function() {
  110.    console.log('Could not start the application (ERR3)');
  111.    APP.startApp();
  112.   });
  113. };
  114. APP.realoadAPP = function() {
  115.  $.ajax({
  116.             method: "GET",
  117.             url: "/get_client_id",
  118.             timeout: 2000
  119.         }).done(function(msg) {
  120.             if (msg.trim() === APP.config.app_id) {
  121.                 location.reload();
  122.             }
  123.         }).fail(function(msg) {
  124.             console.log(msg);
  125.         });
  126. }
  127. // Creates a WebSocket connection with the web server
  128. APP.connectWebSocket = function() {
  129.  if (window.WebSocket) {
  130.   APP.ws = new WebSocket(APP.config.socket_url);
  131.   APP.ws.binaryType = "arraybuffer";
  132.  } else if (window.MozWebSocket) {
  133.   APP.ws = new MozWebSocket(APP.config.socket_url);
  134.   APP.ws.binaryType = "arraybuffer";
  135.  } else {
  136.   console.log('Browser does not support WebSocket');
  137.  }
  138.  // Define WebSocket event listeners
  139.  if (APP.ws) {
  140.   APP.ws.onopen = function() {
  141.    console.log('Socket opened');
  142.    APP.state.socket_opened = true;
  143.    APP.state.unexpected_closed = true;
  144.    APP.sendParameters();
  145.   };
  146.   APP.ws.onclose = function() {
  147.    APP.state.socket_opened = false;
  148.    if (APP.state.unexpected_closed)
  149.     setTimeout(APP.startApp(), 1000);
  150.    console.log('Socket closed');
  151.   };
  152.   APP.ws.onerror = function(ev) {
  153.    if (!APP.state.socket_opened)
  154.     APP.startApp();
  155.    console.log('Websocket error: ', ev);
  156.   };
  157.   APP.ws.onmessage = function(ev) {
  158.    try {
  159.     var data = new Uint8Array(ev.data);
  160.     var inflate = pako.inflate(data);
  161.     var text = String.fromCharCode.apply(null, new Uint8Array(inflate));
  162.     var receive = JSON.parse(text);
  163.     //Recieving parameters
  164.     if (receive.parameters) {
  165.      APP.parameterStack.push(receive.parameters);
  166.     }
  167.     //Recieve signals
  168.     if (receive.signals) {
  169.      //g_PacketsRecv++;
  170.      APP.signalStack.push(receive.signals);
  171.     }
  172.    } catch (e) {
  173.     console.log(e);
  174.    } finally {}
  175.   };
  176.  }
  177. };
  178. /* -------------------------------------------------------------------- */
  179. // Lire la valeur d'un paramètre partagé ou local
  180. APP.getVal = function(param_name) {
  181.  if (param_name in APP.params.shared) {
  182.   return APP.params.shared[param_name].value;
  183.  } else if (param_name in APP.params.local) {
  184.   return APP.params.local[param_name].value;
  185.  } else
  186.   return 0;
  187. }
  188. // Modifier la valeur d'un paramètre partagé ou local
  189. APP.setVal = function(param_name, value, send = false) {
  190.  if (param_name in APP.params.shared) {
  191.   console.log("set value of shared param ", param_name);
  192.   if (typeof(APP.params.shared[param_name].value) !== "string" ) {
  193.    if (value > APP.params.shared[param_name].max) value = APP.params.shared[param_name].max;
  194.    if (value < APP.params.shared[param_name].min) value = APP.params.shared[param_name].min;
  195.    APP.params.shared[param_name].value = value;
  196.   } else {
  197.    value = toString(value);
  198.    APP.params.shared[param_name].value = value;
  199.   }
  200.   if (send === true) {
  201.    console.log("app parameters in cache" );
  202.    APP.parametersCache[param_name] = { "value": value };
  203.    APP.state.parametersCache_isEmpty = false;
  204.   }
  205.  } else if (param_name in APP.params.local) {
  206.   console.log("set value of local param ", param_name);
  207.   if (typeof(APP.params.local[param_name].value) !== "string" ) {
  208.    if (value > APP.params.local[param_name].max) value = APP.params.local[param_name].max;
  209.    if (value < APP.params.local[param_name].min) value = APP.params.local[param_name].min;
  210.    APP.params.local[param_name].value = value;
  211.   } else {
  212.    value = toString(value);
  213.    APP.params.local[param_name].value = value;
  214.   }
  215.  }
  216.  return value;
  217. };
  218. // Mettre à jour un paramètre à partir de la valeur d'un élément js du même nom
  219. APP.updateVal = function(param_name, channel = "", proprety = "" ) {
  220.  var val;
  221.  if (proprety.length > 0) {
  222.   val = APP.setVal(param_name + channel, $("#" + param_name).prop(proprety), true);
  223.   $("#" + param_name).prop(proprety, val);
  224.  } else {
  225.   val = APP.setVal(param_name + channel, $("#" + param_name).val(), true);
  226.   $("#" + param_name).val(val);
  227.  }
  228.  return val;
  229. }
  230. APP.updateBoolVal = function(param_name, channel = "", proprety = "" ) {
  231.  var val;
  232.  if (proprety.length > 0) {
  233.   val = APP.setVal(param_name + channel, parseInt($("#" + param_name).prop(proprety))?true:false, true);
  234.   $("#" + param_name).prop(proprety, val);
  235.  } else {
  236.   val = APP.setVal(param_name + channel, parseInt($("#" + param_name).val())?true:false, true);
  237.   $("#" + param_name).val(val);
  238.  }
  239.  return val;
  240. }
  241. APP.updateIntVal = function(param_name, channel = "", proprety = "" ) {
  242.  var val;
  243.  if (proprety.length > 0) {
  244.   val = APP.setVal(param_name + channel, parseInt($("#" + param_name).prop(proprety)), true);
  245.   $("#" + param_name).prop(proprety, val);
  246.  } else {
  247.   val = APP.setVal(param_name + channel, parseInt($("#" + param_name).val()), true);
  248.   $("#" + param_name).val(val);
  249.  }
  250.  return val;
  251. }
  252. APP.updateFloatVal = function(param_name, channel = "", proprety = "" ) {
  253.  var val;
  254.  if (proprety.length > 0) {
  255.   val = APP.setVal(param_name + channel, parseFloat($("#" + param_name).prop(proprety)), true);
  256.   $("#" + param_name).prop(proprety, val);
  257.  } else {
  258.   val = APP.setVal(param_name + channel, parseFloat($("#" + param_name).val()), true);
  259.   $("#" + param_name).val(val);
  260.  }
  261.  return val;
  262. }
  263. // Mettre à jour la valeur d'un élément js à partir de un paramètre du même nom
  264. APP.updateUI = function(param_name, channel = "", proprety = "" ) {
  265.  var val;
  266.  if (proprety.length > 0) {
  267.   val = APP.getVal(param_name + channel);
  268.   $("#" + param_name).prop(proprety, val);
  269.  } else {
  270.   val = APP.getVal(param_name + channel);
  271.   $("#" + param_name).val(val);
  272.  }
  273.  return val;
  274. }
  275. /* -------------------------------------------------------------------- */
  276. // Processes newly received data for signals
  277. APP.processSignals = function(new_signals) {
  278.  var newDatas = [];
  279.  // Draw signals
  280.  for (sig_name in new_signals) {
  281.   // Ignore empty signals
  282.   if (!(sig_name in APP.signals)) {
  283.    APP.signals[sig_name] = Array(APP.signals.length_display).fill(0)
  284.   }
  285.   if (new_signals[sig_name].size == 0) continue;
  286.   var pointsXY = [];
  287.   count = APP.signals.length_display - new_signals[sig_name].size;
  288.   for (i = 0; i < count; i++) {
  289.    APP.signals[sig_name][i] = APP.signals[sig_name][i+new_signals[sig_name].size];
  290.    pointsXY.push([i, APP.signals[sig_name][i]]);
  291.   }
  292.   for (var i = 0; i < new_signals[sig_name].size; i++) {
  293.    APP.signals[sig_name][i+count] = new_signals[sig_name].value[i];
  294.    pointsXY.push([i+count, APP.signals[sig_name][i+count]]);
  295.    //pointsXY.push([i, new_signals[sig_name].value[i]]);
  296.   }
  297.   newDatas.push(pointsXY);
  298.  }
  299.  // Update graph
  300.  APP.plot.setData(newDatas);
  301.  APP.plot.draw();
  302. }
  303. //Handler
  304. var signalsHandler = function() {
  305.  if (!APP.state.socket_opened || !APP.state.running) return;
  306.  while (APP.signalStack.length > 0) {
  307.   APP.processSignals(APP.signalStack[0]);
  308.   APP.signalStack.splice(0, 1);
  309.  }
  310. }
  311. APP.processParameters = function(new_params) {
  312.  var old_params = $.extend(true, {}, APP.params.shared);
  313.  var send_all_params = Object.keys(new_params).indexOf('send_all_params') != -1;
  314.  if ('APP_RUN' in new_params) {
  315.             APP.state.running = new_params['APP_RUN'].value;
  316.         }
  317.  for (var param_name in new_params) {
  318.   APP.params.shared[param_name] = new_params[param_name];
  319.   if (APP.params.callback[param_name] !== undefined)
  320.    APP.params.callback[param_name](new_params);
  321.  }
  322.  // On attend de recevoir les premiers paramètres de l'application C avant de laisser
  323.  // la main à l'utilisateur pour changer les paramètres
  324.  if ($("body" ).hasClass("loaded" ) === false) {
  325.   console.log("Recept init parms ", new_params);
  326.   $("body" ).addClass("loaded" );
  327.   // on masque l"icon de chargement
  328.   var $element = $("#loader-wrapper" );
  329.   if ($element.length == 0){
  330.    $element.remove();
  331.   }
  332.  }
  333. };
  334. // Sends to server parameters
  335. APP.sendParameters = function() {
  336.  if (APP.state.parametersCache_isEmpty !== false) {
  337.   if (!APP.state.socket_opened) {
  338.    console.log('ERROR: Cannot save changes, socket not opened');
  339.    return false;
  340.   }
  341.   APP.parametersCache["in_command"] = { value: "send_all_params" };
  342.   APP.ws.send(JSON.stringify({ parameters: APP.parametersCache }));
  343.   APP.parametersCache = {};
  344.   APP.state.parametersCache_isEmpty = true;
  345.  }
  346.  return true;
  347. };
  348. var parametersHandler = function() {
  349.  if (!APP.state.socket_opened) return;
  350.  while (APP.parameterStack.length > 0) {
  351.   APP.processParameters(APP.parameterStack[0]);
  352.   APP.parameterStack.splice(0, 1);
  353.  }
  354.  APP.sendParameters();
  355. }
  356. //Set handlers timers
  357. setInterval(signalsHandler, 40);
  358. setInterval(parametersHandler, 10);
  359. /* -------------------------------------------------------------------- */
  360. APP.change_app_run = function(new_params) {
  361.  $("#APP_RUN" ).text(new_params['APP_RUN'].value? "RUN":"STOP" );
  362. }
  363. APP.change_osc_show_ch1 = function(new_params) {
  364.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_1)
  365.   $("#OSC_SHOW_CH" ).prop("checked", new_params['OSC_SHOW_CH1'].value);
  366. }
  367. APP.change_osc_show_ch2 = function(new_params) {
  368.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_2)
  369.   $("#OSC_SHOW_CH" ).prop("checked", new_params['OSC_SHOW_CH2'].value);
  370. }
  371. APP.change_osc_invert_ch1 = function(new_params) {
  372.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_1)
  373.   $("#OSC_INVERT_CH" ).prop("checked", new_params['OSC_INVERT_CH1'].value);
  374. }
  375. APP.change_osc_invert_ch2 = function(new_params) {
  376.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_2)
  377.   $("#OSC_INVERT_CH" ).prop("checked", new_params['OSC_INVERT_CH2'].value);
  378. }
  379. APP.change_osc_prob_ch1 = function(new_params) {
  380.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_1)
  381.   $("#OSC_PROB_CH" ).prop("checked", new_params['OSC_PROB_CH1'].value);
  382. }
  383. APP.change_osc_prob_ch2 = function(new_params) {
  384.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_2)
  385.   $("#OSC_PROB_CH" ).prop("checked", new_params['OSC_PROB_CH2'].value);
  386. }
  387. APP.change_osc_gain_ch1 = function(new_params) {
  388.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_1)
  389.   $("#OSC_GAIN_CH" ).prop("checked", new_params['OSC_GAIN_CH1'].value);
  390. }
  391. APP.change_osc_gain_ch2 = function(new_params) {
  392.  if (APP.state.currentMenu === Menu.INPUT_CHANNEL_2)
  393.   $("#OSC_GAIN_CH" ).prop("checked", new_params['OSC_GAIN_CH2'].value);
  394. }
  395. APP.change_gen_enable_ch1 = function(new_params) {
  396.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  397.   $("#GEN_ENABLE_CH" ).prop("checked", new_params['GEN_ENABLE_CH1'].value);
  398. }
  399. APP.change_gen_enable_ch2 = function(new_params) {
  400.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  401.   $("#GEN_ENABLE_CH" ).prop("checked", new_params['GEN_ENABLE_CH2'].value);
  402. }
  403. APP.change_gen_show_ch1 = function(new_params) {
  404.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  405.   $("#GEN_SHOW_CH" ).prop("checked", new_params['GEN_SHOW_CH1'].value);
  406. }
  407. APP.change_gen_show_ch2 = function(new_params) {
  408.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  409.   $("#GEN_SHOW_CH" ).prop("checked", new_params['GEN_SHOW_CH2'].value);
  410. }
  411. APP.change_gen_amplitude_ch1 = function(new_params) {
  412.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  413.   $("#GEN_AMPLITUDE_CH" ).val(new_params['GEN_AMPLITUDE_CH1'].value);
  414. }
  415. APP.change_gen_amplitude_ch2 = function(new_params) {
  416.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  417.   $("#GEN_AMPLITUDE_CH" ).val(new_params['GEN_AMPLITUDE_CH2'].value);
  418. }
  419. APP.change_gen_frequency_ch1 = function(new_params) {
  420.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  421.   $("#GEN_FREQUENCY_CH" ).val(new_params['GEN_FREQUENCY_CH1'].value);
  422. }
  423. APP.change_gen_frequency_ch2 = function(new_params) {
  424.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  425.   $("#GEN_FREQUENCY_CH" ).val(new_params['GEN_FREQUENCY_CH2'].value);
  426. }
  427. APP.change_gen_offset_ch1 = function(new_params) {
  428.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  429.   $("#GEN_OFFSET_CH" ).val(new_params['GEN_OFFSET_CH1'].value);
  430. }
  431. APP.change_gen_frequency_ch2 = function(new_params) {
  432.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  433.   $("#GEN_OFFSET_CH" ).val(new_params['GEN_OFFSET_CH2'].value);
  434. }
  435. APP.change_gen_waveform_ch1 = function(new_params) {
  436.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1) {
  437.   var val = new_params['GEN_WAVEFORM_CH1'].value;
  438.   $("#GEN_WAVEFORM_CH" ).val(val);
  439.   APP.UI.update_gen_waveform_section(val);
  440.  }
  441. }
  442. APP.change_gen_waveform_ch2 = function(new_params) {
  443.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2) {
  444.   var val = new_params['GEN_WAVEFORM_CH2'].value;
  445.   $("#GEN_WAVEFORM_CH" ).val(val);
  446.   APP.UI.update_gen_waveform_section(val);
  447.  }
  448. }
  449. APP.change_gen_mode_ch1 = function(new_params) {
  450.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1) {
  451.   var val = new_params['GEN_MODE_CH1'].value;
  452.   $("#GEN_MODE_CH" ).val(val);
  453.   APP.UI.update_gen_mode_section(val);
  454.  }
  455. }
  456. APP.change_gen_mode_ch2 = function(new_params) {
  457.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2) {
  458.   var val = new_params['GEN_MODE_CH2'].value;
  459.   $("#GEN_MODE_CH" ).val(val);
  460.   APP.UI.update_gen_mode_section(val);
  461.  }
  462. }
  463. APP.change_gen_duty_cycle_ch1 = function(new_params) {
  464.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  465.   $("#GEN_DUTY_CYCLE_CH" ).val(new_params['GEN_DUTY_CYCLE_CH1'].value);
  466. }
  467. APP.change_gen_duty_cycle_ch2 = function(new_params) {
  468.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  469.   $("#GEN_DUTY_CYCLE_CH" ).val(new_params['GEN_DUTY_CYCLE_CH2'].value);
  470. }
  471. APP.change_gen_burst_count_ch1 = function(new_params) {
  472.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  473.   $("#GEN_BURST_COUNT_CH" ).val(new_params['GEN_BURST_COUNT_CH1'].value);
  474. }
  475. APP.change_gen_burst_count_ch2 = function(new_params) {
  476.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  477.   $("#GEN_BURST_COUNT_CH" ).val(new_params['GEN_BURST_COUNT_CH2'].value);
  478. }
  479. APP.change_gen_burst_rep_ch1 = function(new_params) {
  480.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  481.   $("#GEN_BURST_REP_CH" ).val(new_params['GEN_BURST_REP_CH1'].value);
  482. }
  483. APP.change_gen_burst_rep_ch2 = function(new_params) {
  484.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  485.   $("#GEN_BURST_REP_CH" ).val(new_params['GEN_BURST_REP_CH2'].value);
  486. }
  487. APP.change_gen_burst_per_ch1 = function(new_params) {
  488.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_1)
  489.   $("#GEN_BURST_PER_CH" ).val(new_params['GEN_BURST_PER_CH1'].value);
  490. }
  491. APP.change_gen_burst_per_ch2 = function(new_params) {
  492.  if (APP.state.currentMenu === Menu.OUTPUT_CHANNEL_2)
  493.   $("#GEN_BURST_PER_CH" ).val(new_params['GEN_BURST_PER_CH2'].value);
  494. }
  495. APP.params.callback["APP_RUN"] = APP.change_app_run;
  496. APP.params.callback["OSC_SHOW_CH1"] = APP.change_osc_show_ch1;
  497. APP.params.callback["OSC_SHOW_CH2"] = APP.change_osc_show_ch2;
  498. APP.params.callback["OSC_INVERT_CH1"] = APP.change_osc_invert_ch1;
  499. APP.params.callback["OSC_INVERT_CH2"] = APP.change_osc_invert_ch2;
  500. APP.params.callback["OSC_PROB_CH1"] = APP.change_osc_prob_ch1;
  501. APP.params.callback["OSC_PROB_CH2"] = APP.change_osc_prob_ch2;
  502. APP.params.callback["OSC_GAIN_CH1"] = APP.change_osc_gain_ch1;
  503. APP.params.callback["OSC_GAIN_CH2"] = APP.change_osc_gain_ch2;
  504. APP.params.callback["GEN_ENABLE_CH1"] = APP.change_gen_enable_ch1;
  505. APP.params.callback["GEN_ENABLE_CH2"] = APP.change_gen_enable_ch2;
  506. APP.params.callback["GEN_SHOW_CH1"] = APP.change_gen_show_ch1;
  507. APP.params.callback["GEN_SHOW_CH2"] = APP.change_gen_show_ch2;
  508. APP.params.callback["GEN_AMPLITUDE_CH1"] = APP.change_gen_amplitude_ch1;
  509. APP.params.callback["GEN_AMPLITUDE_CH2"] = APP.change_gen_amplitude_ch2;
  510. APP.params.callback["GEN_FREQUENCY_CH1"] = APP.change_gen_frequency_ch1;
  511. APP.params.callback["GEN_FREQUENCY_CH2"] = APP.change_gen_frequency_ch2;
  512. APP.params.callback["GEN_OFFSET_CH1"] = APP.change_gen_offset_ch1;
  513. APP.params.callback["GEN_OFFSET_CH2"] = APP.change_gen_offset_ch2;
  514. APP.params.callback["GEN_WAVEFORM_CH1"] = APP.change_gen_waveform_ch1;
  515. APP.params.callback["GEN_WAVEFORM_CH2"] = APP.change_gen_waveform_ch2;
  516. APP.params.callback["GEN_MODE_CH1"] = APP.change_gen_mode_ch1;
  517. APP.params.callback["GEN_MODE_CH2"] = APP.change_gen_mode_ch2;
  518. APP.params.callback["GEN_DUTY_CYCLE_CH1"] = APP.change_gen_duty_cycle_ch1;
  519. APP.params.callback["GEN_DUTY_CYCLE_CH2"] = APP.change_gen_duty_cycle_ch2;
  520. APP.params.callback["GEN_BURST_COUNT_CH1"] = APP.change_gen_burst_count_ch1;
  521. APP.params.callback["GEN_BURST_COUNT_CH2"] = APP.change_gen_burst_count_ch2;
  522. APP.params.callback["GEN_BURST_REP_CH1"] = APP.change_gen_burst_rep_ch1;
  523. APP.params.callback["GEN_BURST_REP_CH2"] = APP.change_gen_burst_rep_ch2;
  524. APP.params.callback["GEN_BURST_PER_CH1"] = APP.change_gen_burst_per_ch1;
  525. APP.params.callback["GEN_BURST_PER_CH2"] = APP.change_gen_burst_per_ch2;
  526. }(window.APP = window.APP || {}, jQuery));
  527. // Page onload event handler
  528. $(function() {
  529. APP.config.client_id = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
  530.         var r = Math.random() * 16 | 0,
  531.             v = c == 'x' ? r : (r & 0x3 | 0x8);
  532.         return v.toString(16);
  533.     });
  534.     $.ajax({
  535.         url: '/set_client_id', //Server script to process data
  536.         type: 'POST',
  537.         //Ajax events
  538.         //beforeSend: beforeSendHandler,
  539.         success: function(e) { console.log(e); },
  540.         error: function(e) { console.log(e); },
  541.         // Form data
  542.         data: APP.config.client_id,
  543.         //Options to tell jQuery not to process data or worry about content-type.
  544.         cache: false,
  545.         contentType: false,
  546.         processData: false
  547.     });
  548. // Init plot
  549. APP.plot = $.plot($("#placeholder" ), [], {
  550.  series: {
  551.   shadowSize: 0, // Drawing is faster without shadows
  552.  },
  553.  yaxis: {
  554.   min: -5,
  555.   max: 5,
  556.   show: true,
  557.  },
  558.  xaxis: {
  559.   min: 0,
  560.   max: APP.signals.length_display,
  561.   show: true
  562.  },
  563.  grid: {
  564.   show: true
  565.  },
  566.  colors: [
  567.   '#FF2A68', '#FF9500', '#FFDB4C', '#87FC70', '#22EDC7', '#1AD6FD', '#C644FC', '#52EDC7', '#EF4DB6'
  568.  ]
  569. });
  570. APP.UI.close_menu();
  571. for (var name in APP.UI.changeCallbacks) {
  572.  $("#" + name).change(APP.UI.changeCallbacks[name]);
  573. }
  574. for (var name in APP.UI.clickCallbacks) {
  575.  $("#" + name).click(APP.UI.clickCallbacks[name]);
  576. }
  577. // Bind to the window resize event to redraw the graph; trigger that event to do the first drawing
  578. $(window).resize(function() {
  579.  APP.plot.resize();
  580.  APP.plot.setupGrid();
  581. });
  582. // Revenir à la page précédente si on clic sur back-btn
  583. APP.config.previousPageUrl = document.referrer;
  584. const currentUrl = window.location.href;
  585. if (currentUrl === APP.config.previousPageUrl || APP.config.previousPageUrl === "" ){
  586.  APP.config.previousPageUrl = "/";
  587. }
  588. $("#return-button" ).on("click", function(event) {
  589.  APP.state.unexpected_closed = false;
  590.  window.location.href = APP.config.previousPageUrl;
  591. });
  592. $("#home-button" ).on("click", function(event) {
  593.  APP.state.unexpected_closed = false;
  594.  window.location.href = "/";
  595.  APP.ws.onclose = function() {}; // disable onclose handler first
  596.  APP.ws.close();
  597. });
  598. APP.startApp();
  599. // Stop the application when page is unloaded
  600. $(window).on('beforeunload', function() {
  601.  if (APP.ws) {
  602.   APP.ws.onclose = function() {}; // disable onclose handler first
  603.   APP.ws.close();
  604.   $.ajax({
  605.    url: APP.config.stop_app_url,
  606.    async: false
  607.   });
  608.   APP.state.unexpected_closed = false;
  609.  }
  610. });
  611. });


Message édité par clemCH le 12-05-2024 à 12:41:08
Reply

Marsh Posté le 12-05-2024 à 11:59:19   

Reply

Marsh Posté le 12-05-2024 à 12:05:46    

Hello,
Sympa de vouloir partager, mais ça serait une très bonne idée de créer un GitHub (ou assimilé) pour ça, parce que la c'est légèrement imbitable. Les forums c'est pas trop fait pour les côté coller de 10000 lignes...

 

En outre, je doute franchement qu'un problème comme "le front ne se connecte pas bien au backend" nécessite d'avoir le programme complet pour être identifié.

Message cité 1 fois
Message édité par TotalRecall le 12-05-2024 à 12:07:37

---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 12-05-2024 à 12:06:25    

voilà la suite du code
 
Fichier js/guiHandler.js

Code :
  1. /*
  2. *
  3. * Red Pitaya scope application
  4. *
  5. * (c) Red Pitaya http://www.redpitaya.com
  6. *
  7. * Gestion des évènements sur l'interface graphique
  8. */
  9. (function(APP, $, unused) {
  10.     APP.UI = {};
  11.     APP.UI.change_app_run = function(event) {
  12.         var val = APP.updateBoolVal("APP_RUN", APP.state.currentChannel);
  13.  $("#APP_RUN" ).text(val? "RUN":"STOP" );
  14.     }
  15.     APP.UI.change_osc_show = function(event) {
  16.         APP.updateBoolVal("OSC_SHOW_CH", APP.state.currentChannel, "checked" );
  17.     }
  18.     APP.UI.change_osc_invert = function(event) {
  19.         APP.updateBoolVal("OSC_INVERT_CH", APP.state.currentChannel, "checked" );
  20.     }
  21.     APP.UI.change_osc_prob = function(event) {
  22.         APP.updateIntVal("OSC_PROB_CH", APP.state.currentChannel);
  23.     }
  24.     APP.UI.change_osc_gain = function(event) {
  25.         APP.updateIntVal("OSC_GAIN_CH", APP.state.currentChannel);
  26.     }
  27.     APP.UI.change_gen_enable = function(event) {
  28.         APP.updateBoolVal("GEN_ENABLE_CH", APP.state.currentChannel);
  29.     }
  30.     APP.UI.change_gen_show = function(event) {
  31.         APP.updateBoolVal("GEN_SHOW_CH", APP.state.currentChannel, "checked" );
  32.     }
  33.     APP.UI.change_gen_frequency = function(event) {
  34.         APP.updateFloatVal("GEN_FREQUENCY_CH", APP.state.currentChannel);
  35.     }
  36.     APP.UI.change_gen_amplitude = function(event) {
  37.         APP.updateFloatVal("GEN_AMPLITUDE_CH", APP.state.currentChannel);
  38.     }
  39.     APP.UI.change_gen_offset = function(event) {
  40.         APP.updateFloatVal("GEN_OFFSET_CH", APP.state.currentChannel);
  41.     }
  42.     APP.UI.change_gen_waveform = function(event) {
  43.         var val = APP.updateIntVal("GEN_WAVEFORM_CH", APP.state.currentChannel);
  44.         APP.UI.update_gen_waveform_section(val);
  45.     }
  46.     APP.UI.change_gen_mode = function(event) {
  47.         var val = APP.updateIntVal("GEN_MODE_CH", APP.state.currentChannel);
  48.         APP.UI.update_gen_mode_section(val);
  49.     }
  50.     APP.UI.change_gen_duty_cycle = function(event) {
  51.         APP.updateFloatVal("GEN_DUTY_CYCLE_CH", APP.state.currentChannel);
  52.     }
  53.     APP.UI.change_gen_burst_count = function(event) {
  54.         APP.updateIntVal("GEN_BURST_COUNT_CH", APP.state.currentChannel);
  55.     }
  56.     APP.UI.change_gen_burst_per = function(event) {
  57.         APP.updateFloatVal("GEN_BURST_PER_CH", APP.state.currentChannel);
  58.     }
  59.     APP.UI.change_gen_burst_rep = function(event) {
  60.         APP.updateIntVal("GEN_BURST_REP_CH", APP.state.currentChannel);
  61.     }
  62.     APP.UI.update_osc_menu = function() {
  63.         APP.updateUI("OSC_SHOW_CH", APP.state.currentChannel, "checked" );
  64.         APP.updateUI("OSC_INVERT_CH", APP.state.currentChannel, "checked" );
  65.         APP.updateUI("OSC_PROB_CH", APP.state.currentChannel);
  66.         APP.updateUI("OSC_GAIN_CH", APP.state.currentChannel);
  67.     }
  68.     APP.UI.update_gen_menu = function() {
  69.         APP.updateUI("GEN_ENABLE_CH", APP.state.currentChannel, "checked" );
  70.         APP.updateUI("GEN_SHOW_CH", APP.state.currentChannel, "checked" );
  71.         APP.updateUI("GEN_AMPLITUDE_CH", APP.state.currentChannel);
  72.         APP.updateUI("GEN_FREQUENCY_CH", APP.state.currentChannel);
  73.         APP.updateUI("GEN_OFFSET_CH", APP.state.currentChannel);
  74.         APP.UI.update_gen_waveform_section(APP.updateUI("GEN_WAVEFORM_CH", APP.state.currentChannel));
  75.         APP.UI.update_gen_mode_section(APP.updateUI("GEN_MODE_CH", APP.state.currentChannel));
  76.         APP.updateUI("GEN_DUTY_CYCLE_CH", APP.state.currentChannel);
  77.         APP.updateUI("GEN_BURST_COUNT_CH", APP.state.currentChannel);
  78.         APP.updateUI("GEN_BURST_PER_CH", APP.state.currentChannel);
  79.         APP.updateUI("GEN_BURST_REP_CH", APP.state.currentChannel);
  80.     }
  81.     APP.UI.update_gen_waveform_section = function(waveform) {
  82.         if (waveform == Waveform.PWM) {
  83.             if ($("#pwm-setup" ).is(":hidden" ))
  84.                 $("#pwm-setup" ).slideDown(300);
  85.         } else if ($("#pwm-setup" ).is(":hidden" ) == false)
  86.             $("#pwm-setup" ).slideUp(300);
  87.         else
  88.             $("#pwm-setup" ).hide();
  89.     }
  90.     APP.UI.update_gen_mode_section = function(mode) {
  91.         // On affiche ou on masque les élements graphique permettant de configurer le burst mode
  92.         if (mode == GenMode.BURST) {
  93.             if ($("#burst-setup" ).is(":hidden" ))
  94.                 $("#burst-setup" ).slideDown(300);
  95.         } else if ($("#burst-setup" ).is(":hidden" ) == false)
  96.             $("#burst-setup" ).slideUp(300);
  97.         else
  98.             $("#burst-setup" ).hide();
  99.         // On affiche ou on masque les élements graphique permettant de configurer le sweep mode
  100.         if (mode == GenMode.SWEEP) {
  101.             if ($("#sweep-setup" ).is(":hidden" ))
  102.                 $("#sweep-setup" ).slideDown(300);
  103.         } else if ($("#sweep-setup" ).is(":hidden" ) == false)
  104.             $("#sweep-setup" ).slideUp(300);
  105.         else
  106.             $("#sweep-setup" ).hide();
  107.     }
  108.     APP.UI.update_math_menu = function() {
  109.         APP.updateUI("MATH_SHOW_CH", APP.state.currentChannel, "checked" );
  110.         APP.updateUI("MATH_OPERATOR_CH", APP.state.currentChannel);
  111.         APP.updateUI("MATH_FIRST_SIGN_CH", APP.state.currentChannel);
  112.         APP.updateUI("MATH_SECOND_SIGN_CH", APP.state.currentChannel);
  113.         APP.updateUI("MATH_CONST_CH", APP.state.currentChannel);
  114.     }
  115.     APP.UI.update_trigger_menu = function() {
  116.     }
  117.     APP.UI.update_save_menu = function() {
  118.     }
  119.     APP.UI.close_menu = function() {
  120.         // Close current menu
  121.         switch(APP.state.currentMenu) {
  122.             case Menu.INPUT_CHANNEL_1:
  123.                 $("#input-1-button" ).removeClass("active" );
  124.                 $("#setup-params-input" ).slideUp(300);
  125.                 break;
  126.             case Menu.INPUT_CHANNEL_2:
  127.                 $("#input-2-button" ).removeClass("active" );
  128.                 $("#setup-params-input" ).slideUp(300);
  129.                 break;
  130.             case Menu.OUTPUT_CHANNEL_1:
  131.                 $("#output-1-button" ).removeClass("active" );
  132.                 $("#setup-params-output" ).slideUp(300);
  133.                 break;
  134.             case Menu.OUTPUT_CHANNEL_2:
  135.                 $("#output-2-button" ).removeClass("active" );
  136.                 $("#setup-params-output" ).slideUp(300);
  137.                 break;
  138.             case Menu.MATH_CHANNEL_1:
  139.                 $("#math-1-button" ).removeClass("active" );
  140.                 $("#setup-params-math" ).slideUp(300);
  141.                 break;
  142.             case Menu.MATH_CHANNEL_2:
  143.                 $("#math-2-button" ).removeClass("active" );
  144.                 $("#setup-params-math" ).slideUp(300);
  145.                 break;
  146.             case Menu.TRIGGER:
  147.                 $("#trigger-button" ).removeClass("active" );
  148.                 $("#setup-params-trigger" ).slideUp(300);
  149.                 break;
  150.             case Menu.SAVE:
  151.                 $("#save-button" ).removeClass("active" );
  152.                 $("#setup-params-save" ).slideUp(300);
  153.                 break;
  154.             case Menu.CLOSE:
  155.                 $("#setup-params-input" ).hide();
  156.                 $("#setup-params-output" ).hide();
  157.                 $("#setup-params-math" ).hide();
  158.                 $("#setup-params-trigger" ).hide();
  159.                 $("#setup-params-save" ).hide();
  160.                 break;
  161.             default: return;
  162.         };
  163.         APP.state.currentMenu = Menu.CLOSE;
  164.     }
  165.     APP.UI.toggle_input_1_menu = function(event) {
  166.         console.log("toggle_input_1_menu" );
  167.         var old = APP.state.currentMenu;
  168.         APP.UI.close_menu();
  169.         if (old !== Menu.INPUT_CHANNEL_1) {
  170.             $("#input-1-button" ).addClass("active" );
  171.             $("#setup-params-input" ).slideDown(300);
  172.             APP.state.currentChannel = 1;
  173.             APP.state.currentMenu = Menu.INPUT_CHANNEL_1;
  174.             APP.UI.update_osc_menu();
  175.         }
  176.     }
  177.     APP.UI.toggle_input_2_menu = function(event) {
  178.         console.log("toggle_input_2_menu" );
  179.         var old = APP.state.currentMenu;
  180.         APP.UI.close_menu();
  181.         if (old !== Menu.INPUT_CHANNEL_2) {
  182.             $("#input-2-button" ).addClass("active" );
  183.             $("#setup-params-input" ).slideDown(300);
  184.             APP.state.currentChannel = 2;
  185.             APP.state.currentMenu = Menu.INPUT_CHANNEL_2;
  186.             APP.UI.update_osc_menu();
  187.         }
  188.     }
  189.     APP.UI.toggle_output_1_menu = function(event) {
  190.         console.log("toggle_output_1_menu" );
  191.         var old = APP.state.currentMenu;
  192.         APP.UI.close_menu();
  193.         if (old !== Menu.OUTPUT_CHANNEL_1) {
  194.             $("#output-1-button" ).addClass("active" );
  195.             $("#setup-params-output" ).slideDown(300);
  196.             APP.state.currentChannel = 1;
  197.             APP.state.currentMenu = Menu.OUTPUT_CHANNEL_1;
  198.             APP.UI.update_gen_menu();
  199.         }
  200.     }
  201.     APP.UI.toggle_output_2_menu = function(event) {
  202.         console.log("toggle_output_2_menu" );
  203.         var old = APP.state.currentMenu;
  204.         APP.UI.close_menu();
  205.         if (old !== Menu.OUTPUT_CHANNEL_2) {
  206.             $("#output-2-button" ).addClass("active" );
  207.             $("#setup-params-output" ).slideDown(300);
  208.             APP.state.currentChannel = 2;
  209.             APP.state.currentMenu = Menu.OUTPUT_CHANNEL_2;
  210.             APP.UI.update_gen_menu();
  211.         }
  212.     }
  213.     APP.UI.toggle_math_1_menu = function(event) {
  214.         console.log("toggle_math_1_menu" );
  215.         var old = APP.state.currentMenu;
  216.         APP.UI.close_menu();
  217.         if (old !== Menu.MATH_CHANNEL_1) {
  218.             $("#math-1-button" ).addClass("active" );
  219.             $("#setup-params-math" ).slideDown(300);
  220.             APP.state.currentChannel = 1;
  221.             APP.state.currentMenu = Menu.MATH_CHANNEL_1;
  222.             APP.UI.update_math_menu();
  223.         }
  224.     }
  225.     APP.UI.toggle_math_2_menu = function(event) {
  226.         console.log("toggle_math_2_menu" );
  227.         var old = APP.state.currentMenu;
  228.         APP.UI.close_menu();
  229.         if (old !== Menu.MATH_CHANNEL_2) {
  230.             $("#math-2-button" ).addClass("active" );
  231.             $("#setup-params-math" ).slideDown(300);
  232.             APP.state.currentChannel = 2;
  233.             APP.state.currentMenu = Menu.MATH_CHANNEL_2;
  234.             APP.UI.update_math_menu();
  235.         }
  236.     }
  237.     APP.UI.toggle_trigger_menu = function(event) {
  238.         var old = APP.state.currentMenu;
  239.         APP.UI.close_menu();
  240.         if (old !== Menu.TRIGGER) {
  241.             $("#trigger-button" ).addClass("active" );
  242.             $("#setup-params-trigger" ).slideDown(300);
  243.             APP.state.currentMenu = Menu.TRIGGER;
  244.             APP.UI.update_trigger_menu();
  245.         }
  246.     }
  247.     APP.UI.toggle_save_menu = function(event) {
  248.         var old = APP.state.currentMenu;
  249.         APP.UI.close_menu();
  250.         if (old !== Menu.SAVE) {
  251.             $("#save-button" ).addClass("active" );
  252.             $("#setup-params-save" ).slideDown(300);
  253.             APP.state.currentMenu = Menu.SAVE;
  254.             APP.UI.update_save_menu();
  255.         }
  256.     }
  257.     //Create callback
  258.     APP.UI.changeCallbacks = {}
  259.     APP.UI.changeCallbacks["OSC_SHOW_CH"]       = APP.UI.change_osc_show;
  260.     APP.UI.changeCallbacks["OSC_INVERT_CH"]     = APP.UI.change_osc_invert;
  261.     APP.UI.changeCallbacks["OSC_PROB_CH"]       = APP.UI.change_osc_prob;
  262.     APP.UI.changeCallbacks["OSC_GAIN_CH"]       = APP.UI.change_osc_gain;
  263.     APP.UI.changeCallbacks["GEN_ENABLE_CH"]     = APP.UI.change_gen_enable;
  264.     APP.UI.changeCallbacks["GEN_SHOW_CH"]       = APP.UI.change_gen_show;
  265.     APP.UI.changeCallbacks["GEN_FREQUENCY_CH"]  = APP.UI.change_gen_frequency;
  266.     APP.UI.changeCallbacks["GEN_AMPLITUDE_CH"]  = APP.UI.change_gen_amplitude;
  267.     APP.UI.changeCallbacks["GEN_OFFSET_CH"]     = APP.UI.change_gen_offset;
  268.     APP.UI.changeCallbacks["GEN_WAVEFORM_CH"]   = APP.UI.change_gen_waveform;
  269.     APP.UI.changeCallbacks["GEN_MODE_CH"]       = APP.UI.change_gen_mode;
  270.     APP.UI.changeCallbacks["GEN_DUTY_CYCLE_CH"] = APP.UI.change_gen_duty_cycle;
  271.     APP.UI.changeCallbacks["GEN_BURST_COUNT_CH"]= APP.UI.change_gen_burst_count;
  272.     APP.UI.changeCallbacks["GEN_BURST_PER_CH"]  = APP.UI.change_gen_burst_per;
  273.     APP.UI.changeCallbacks["GEN_BURST_REP_CH"]  = APP.UI.change_gen_burst_rep;
  274.     APP.UI.clickCallbacks = {}
  275.     APP.UI.clickCallbacks["APP_RUN"]           = APP.UI.change_app_run;
  276.     APP.UI.clickCallbacks["input-1-button"]    = APP.UI.toggle_input_1_menu;
  277.     APP.UI.clickCallbacks["input-2-button"]    = APP.UI.toggle_input_2_menu;
  278.     APP.UI.clickCallbacks["output-1-button"]   = APP.UI.toggle_output_1_menu;
  279.     APP.UI.clickCallbacks["output-2-button"]   = APP.UI.toggle_output_2_menu;
  280.     APP.UI.clickCallbacks["math-1-button"]     = APP.UI.toggle_math_1_menu;
  281.     APP.UI.clickCallbacks["math-2-button"]     = APP.UI.toggle_math_2_menu;
  282.     APP.UI.clickCallbacks["trigger-button"]    = APP.UI.toggle_trigger_menu;
  283.     APP.UI.clickCallbacks["save-button"]       = APP.UI.toggle_save_menu;
  284. }(window.APP = window.APP || {}, jQuery));


 
le fichier de compilation du projet total
Fichier Makefile

Code :
  1. #
  2. # Red Pitaya specific application Makefile.
  3. #
  4. APP=$(notdir $(CURDIR:%/=%))
  5. # Versioning system
  6. BUILD_NUMBER ?= 0
  7. REVISION ?= devbuild
  8. VER:=$(shell cat info/info.json | grep version | sed -e 's/.*:\ *\"//' | sed -e 's/-.*//')
  9. INSTALL_DIR ?= /opt/redpitaya
  10. CONTROLLERHF := controllerhf.so
  11. CFLAGS += -DVERSION=$(VER)-$(BUILD_NUMBER) -DREVISION=$(REVISION)
  12. export CFLAGS
  13. all: $(CONTROLLERHF)
  14. $(CONTROLLERHF):
  15. $(MAKE) -C src
  16. clean:
  17. $(MAKE) -C src clean
  18. -$(RM) *.so

Reply

Marsh Posté le 12-05-2024 à 12:09:35    

TotalRecall a écrit :

Hello,
Sympa de vouloir partager, mais ça serait une très bonne idée de créer un GitHub (ou assimilé) pour ça, parce que la c'est légèrement imbitable. Les forums c'est pas trop fait pour les côté coller de 10000 lignes...
 
En outre, je doute franchement qu'un problème comme "le front ne se connecte pas bien au backend" nécessite d'avoir le programme complet pour être identifié.


:o


---------------
Topic .Net - C# @ Prog
Reply

Marsh Posté le 12-05-2024 à 12:30:18    

Ceci n'est qu'une supposition, je pense que le problème vient de mon code.

Reply

Marsh Posté le 12-05-2024 à 14:29:46    

+1 pour TR et perso (qui ne pourrait répondre) je n'ai pas envie de lire tout ce code et toute cette prose aussi...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed