CY7C68013A

Tags: électronique

Si vous cherchez un analyseur logique USB pas cher, vous avez peut être trouvé le Cypress FX2LP CY7C68013A (comme celui là ou similaire) pour 3-4 euros sur aliexpress.

Cela marche très bien sous linux avec "sigrok" et "pulseview". Mais peut être auriez-vous voulu pourvoir l'utiliser directement depuis un programme C/C++, pour faire les choses bien. (Il existe apparemment pas mal de modules Python pour décoder différents protocoles, mais vous avez décidé, bien à raison, à 10 ans de ne plus investir du temps que dans la pratique de vrais langages de programmation.) Il est possible d'utiliser la librairie "libsigrok" pour cela, mais elle est plutôt mal documentée.

Dans l'espoir de minimiser vos maux de crane, voici un exemple simple de code permettant de le faire, qui pourra facilement servir de base pour tout autre bidouille (comme par exemple un analyseur de bus I2C...). Le programme prend 2 arguments: le premier est la vitesse d'échantillonnage (par exemple 4Mhz), et le second est un fichier où seront logués les changements sur les entrées.

Il est possible de capturer jusqu'à 16 entrées. 0 correspond à PB0, 1 à PB1... 7 à PB7, 8 à PD0, 15 à PD7. Dans le programme, "mask" est le masque binaire des entrées qu'on surveille. Dans l'exemple, mask=3, on ne surveille donc que PB0 et PB1.

/*
  Cypress FX2LP CY7C68013A with libsigrok sample code

  Compile with:
	g++ test.cpp `pkg-config --cflags glib-2.0 --libs glib-2.0` -lsigrok
*/

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <unistd.h>
#include <libsigrok/libsigrok.h>

#include <map>
#include <vector>
#include <iostream>
using namespace std;

vector<pair<long long,unsigned short> > mm;
unsigned short old=0,mask=3;

long long t=0,lt=0;

FILE *out=NULL;

void foo(const struct sr_dev_inst *sdi,const struct sr_datafeed_packet *packet, void *cb_data)
{
  if(packet->type==SR_DF_LOGIC) {
    const sr_datafeed_logic *logic=(const sr_datafeed_logic *) packet->payload;
    unsigned short *d=(unsigned short *)(logic->data);
    for(int i=0;2*i<logic->length;i++) {
      unsigned short dd=d[i]&mask;
      if(dd!=old) {
	mm.push_back(make_pair(t,dd));
	old=dd;
      }
      t++;
    }
    cout<<t<<" : "<<mm.size()<<endl;
    for(;lt<mm.size();lt++) {
      fprintf(out,"%Ld %4X\n",mm[lt].first,int(mm[lt].second));
    }
    fflush(out);
    return;
  }

  if(packet->type==SR_DF_HEADER) {
    // print samplerate
    GVariant *gvar;
    if (sr_config_get(sdi->driver, sdi, NULL, SR_CONF_SAMPLERATE,
		      &gvar) == SR_OK) {
      int samplerate = g_variant_get_uint64(gvar);
      fprintf(stderr,"samplerate=%lu\n",samplerate);
      g_variant_unref(gvar);
    }

    return;
  }

  if (packet->type == SR_DF_END)
    return;

  printf("TODO %d\n",packet->type);
}

int main(int ac, char **av)
// first argument : sample rate (0 kHz, 25 kHz, 50 kHz, 100 kHz, 200 kHz, 250 kHz, 500 kHz, 1 MHz, 2 MHz, 3 MHz, 4 MHz, 6 MHz, 8 MHz, 12 MHz ... ?)
// second argument : log file
{
  assert(ac==3);
  
  out=fopen(av[2],"w");
  assert(out);
  
  sr_loglevel(SR_LOG_SPEW); //log everything 

  sr_context *ctx;
  sr_init(&ctx);

  sr_dev_driver **l;
  l=sr_driver_list();

  //Select 'fx2lafw' driver
  sr_dev_driver *driver=NULL;
  for(int i=0;l[i];i++) {
    if(0==strcmp(l[i]->name,"fx2lafw"))
      driver=l[i];
  }
  assert(driver);

  sr_driver_init(ctx,driver);

  GSList *a=sr_driver_scan(driver,NULL);

  // take the first device for fx2lafw driver
  struct sr_dev_inst *sdi=NULL;
  while(a) {
    sr_dev_inst *xd=(sr_dev_inst *)a->data;
    printf("found: %s %s %s \n",xd->vendor,xd->model,xd->version);
    sdi=xd;
    a=a->next;
  }
  assert(sdi);

  sr_session *ses=sr_session_new();

  //set the callback function
  sr_session_datafeed_callback_add(foo,NULL);

  sr_dev_open(sdi);

  // set samplerate
  {
    const struct sr_config_info *srci;
    int ret;
    
    srci = sr_config_info_name_get ("samplerate");
    assert(srci);
    assert(srci->datatype==SR_T_UINT64);
    uint64_t tmp_u64;
    ret = sr_parse_sizestring (av[1], &tmp_u64);
    assert(ret==0);
    ret = sr_config_set (sdi, NULL, srci->key, g_variant_new_uint64 (tmp_u64));
    assert(ret==0);
  };

  sr_session_dev_add(sdi);
    
  // set maximal number of samples
  sr_config_set(sdi, NULL, SR_CONF_LIMIT_SAMPLES,g_variant_new_uint64(1000000000));
  
  sr_session_start();
  sr_session_run ();
  
  sr_exit(ctx);
  return 0;
}