DSP STA013 Interfacing

This article shows how to interface DSP STA013 with the synchronous serial port (/dev/syncser1) of the ETRAX100LX (devboard_lx).

  1. Linux kernel 2.4.31
  2. SDK 2.01

kernelconfig

#
# Hardware setup
#
....
CONFIG_ETRAX_DEF_R_PORT_PA_DIR=0xff
CONFIG_ETRAX_DEF_R_PORT_PA_DATA=0xf0
CONFIG_ETRAX_DEF_R_PORT_PB_CONFIG=0x00
CONFIG_ETRAX_DEF_R_PORT_PB_DIR=0x1e
CONFIG_ETRAX_DEF_R_PORT_PB_DATA=0xf3
...
#
# Drivers for ETRAX 100LX built-in interfaces
#
...
# CONFIG_ETRAX_SERIAL_PORT1 is not set
# CONFIG_ETRAX_SERIAL_PORT2 is not set
# CONFIG_ETRAX_SERIAL_PORT3 is not set
...
CONFIG_ETRAX_SYNCHRONOUS_SERIAL=y
CONFIG_ETRAX_SYNCHRONOUS_SERIAL_PORT1=y
CONFIG_ETRAX_SYNCHRONOUS_SERIAL1_DMA=y
...
CONFIG_ETRAX_GPIO=y
CONFIG_ETRAX_PA_BUTTON_BITMASK=0x02
CONFIG_ETRAX_PA_CHANGEABLE_DIR=0xFF
CONFIG_ETRAX_PA_CHANGEABLE_BITS=0xFF
CONFIG_ETRAX_PB_CHANGEABLE_DIR=0xFF
CONFIG_ETRAX_PB_CHANGEABLE_BITS=0xFF
...
CONFIG_USB=y
# CONFIG_ETRAX_USB_HOST_PORT1 is not set
CONFIG_ETRAX_USB_HOST_PORT2=y
...

Hardware modifications on devboard_lx

6 signals are required

  1. 4 (ss3status, ss3clk, ss3data, and ss3frame) for syncserial
  2. 2 (SDA and SCL) for I2C emulation

In order to bring theses signals to X25 and X4 connectors, make aditionnal hardware modifications on devboard_lx :

  1. S21 = A (pin4 X25 = ss3status)
  2. S17 = A (pin2 X25 = ss3clock)
  3. S16 = A (pin3 X25 = ss3data)
  4. ss3frame on pin1 X4 (pb7)
  5. SCL on pin7 X18 (pa4)
  6. SDA on pin8 X18 (pa5)
  7. remove resistor r127 and r39=4K7 to disconnect D11

DSP STA013/ETRAX100LX signals

STA013 ETRAX100LX
BIT_EN ss3Frame
DRQST ss3Status
SCKR ss3Clk
SDI ss3Data
SDA pa4
SCL pa5

ioctl's on syncserial and test program

/* ioctl's */

….

FILE *file;
unsigned char buf[512];
int fd, err, tmp;
 
if((fd = open("/dev/syncser1", O_RDWR | O_SYNC)) <0)	
  {
    fprintf(stderr, "impossible d'ouvrir syncser1\n");
    exit(1);
  }
fprintf(stderr, "Ouverture syncser1 reussie\n");
 
ioctl (fd, SSP_SPI, SPI_MASTER);
tmp = NORMAL_SYNC | WORD_SYNC | SYNC_ON |
  WORD_SIZE_8 | BIT_ORDER_MSB | 
  FLOW_CONTROL_ENABLE | CLOCK_NOT_GATED;
if (ioctl(fd, SSP_FRAME_SYNC, tmp)) 
  {
    fprintf(stderr, "Couldn't change sync SSP_FRAME_SYNC\n");
    err++;
  }  
tmp = CLOCK_NORMAL | FRAME_NORMAL | STATUS_NORMAL;
if (ioctl(fd, SSP_IPOLARITY, tmp)) 
  {
    fprintf(stderr, "Couldn't change polarity SSP_IPOLARITY\n");
    err++;
  }
tmp = CLOCK_NORMAL | FRAME_NORMAL | STATUS_NORMAL;
if (ioctl(fd, SSP_OPOLARITY, tmp)) 
  {
    fprintf(stderr, "Couldn't change polarity SSP_OPOLARITY\n");
    err++;
  }
if (ioctl(fd, SSP_INBUFCHUNK, 4096))
  {
    fprintf(stderr, "Couldn't change sync SSP_BUFCHUNK\n");
    err++;
  }
 
...
 
  /* Open mp3 file as a input arg (not parsed for the moment) */
  if((df=fileno(stdin))==-1)
    {
      fprintf(stderr, "Unknow file\n");
      exit(1);
    }
  fprintf(stderr, "Open mp3 file \n");
 
  file = fdopen(df, "r");
 
  fprintf (stderr, "Playing ...\n");
 
  /* Flush DSP FIFO ? */
  size = write(fd, 0, 2048);
  fprintf (stderr, "Sending 2048 0x00 \n");
 
  /* TEST */ 
  while(1)
    {
      while(!feof(file))
	{
	  n =  fread(buf, 1, sizeof(buf), file);
	  //	  fprintf (stderr, "Blocs read from input stream %d \n", n);
 
	  size = write(fd, buf, sizeof(buf));
	  //	  fprintf (stderr, "Write bloc %d \n", size);
 
         }
      fprintf (stderr, "Rewind \n");
    }

I2C STA013 bootload

Before running the test program above it is mandatory to upload first a config file to DSP STA013 (via I2C) avaliable on st.com site.

Here a code that make it :

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <asm/etraxgpio.h>
 
/* 
 * Configure STA013 par I2C 
 * avec le fichier config.hex
 *
 */
 
/* Adresse et commande I2C */
#define STA_READ_CMD 0x87
#define STA_WRITE_CMD 0x86
 
/* Fichier de configuration */
#define STA_CONF_FILE "config.hex"
 
/* PA4 = SCL, PA5 = SDA */
#define I2C_DATA_LINE 1<<4
#define I2C_CLOCK_LINE 1<<5
 
 
int i2c_fd;
 
/* I2C CODE FROM ACMESYSTEMS */
 
/*
 * Get the SDA line state
 */
int
i2c_getbit(void) 
{
  unsigned int value;
 
  value=ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_READBITS));
  if ((value&(I2C_DATA_LINE))==0) 
    return 0;
  else 
    return 1;
}	
 
/*
 * Set the SDA line state
 */
void
i2c_data(int state) 
{
  if (state==1) 
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), I2C_DATA_LINE);
  else 
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_DATA_LINE);
}
 
/*
 * Set the SCL line state
 */
void
i2c_clk(int state) {
  if (state==1) 
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETBITS), I2C_CLOCK_LINE);
  else 
    ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_CLRBITS), I2C_CLOCK_LINE);
}
 
/*
 * Set the SDA line as output
 */
void
i2c_dir_out(void) 
{
  int iomask;
  iomask = I2C_DATA_LINE;
  ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_OUTPUT), &iomask);
}
 
/*
 * Set the SDA line as input
 */
void
i2c_dir_in(void) 
{
  int iomask;
  iomask = I2C_DATA_LINE;
  ioctl(i2c_fd, _IO(ETRAXGPIO_IOCTYPE, IO_SETGET_INPUT), &iomask);
}
 
 
 
/*
 * Software delay in us 
 */
void
udelay(int us)
{
  int a;
  int b;
  int delayvar=1111;
 
  for (b=0; b<33; b++) 
    {
      for (a=0;a<us;a++) 
	{
	  delayvar*=3;
	  delayvar/=3;
	}
    }  
}   
 
 
/*
 * Read a byte from I2C bus and send the ack sequence 
 */
unsigned char
i2c_inbyte(void) 
{
  unsigned char value = 0;
  int bitvalue;
  int i;
 
  /* Read data byte */
  i2c_dir_in();
 
  for (i=0;i<8;i++)
    {
      i2c_clk(1);
      bitvalue = i2c_getbit();
      value |= bitvalue;
      if (i<7)
	value <<= 1;
      i2c_clk(0);
    }
 
  /* Send Ack */
 
  i2c_data(0);
  i2c_dir_out();
  i2c_data(0);
 
  i2c_clk(1);
  i2c_clk(0);
 
  udelay(1);	
  return value;
}
 
/*
 * ouvrir /dev/gpioa
 */
int
i2c_open(void) 
{
 
  if(( i2c_fd = open("/dev/gpioa", O_RDWR)) <0)
    {
      fprintf(stderr, "Impossible d'ouvrir le port gpioa\n");
      return -1;
    }
  fprintf(stderr, "Ouverture gpioa reussie\n");
 
 
  udelay(10);
 
  /*
   * SDA output = 1
   * SCL output = 1
   */
  i2c_dir_out();  
  i2c_clk(1);
  udelay(10);
  i2c_data(1);
 
  return i2c_fd;
}
 
/*
 * Close the GPIOA dev 
 */
void
i2c_close(void) 
{
  close(i2c_fd);
}
 
/*
 * Send a start sequence to I2C bus 
 */
void
i2c_start(void)
{
  i2c_clk(1);
  udelay(10);
  i2c_data(1);
  udelay(10);
  i2c_data(0);
  udelay(10);
  i2c_clk(0);
}
 
/*
 * Send a stop sequence to I2C bus 
 */
void i2c_stop(void) 
{
  i2c_clk(1);
  udelay(10);
  i2c_data(1);
}
 
/*
 * Send a byte to the I2C bus and return the ack sequence from slave
 * rtc
 * 0 = Nack, 1=Ack
 */
int 
i2c_outbyte(unsigned char x) 
{
  int i=8;
  int ack;
 
  while(i) 
    {
      if (!(x & 0x80))
	i2c_data(0); 
      else
	i2c_data(1);
 
      udelay(10);
      i2c_clk(1);
      udelay(10);
      i2c_clk(0);
      i--; x=x<<1;
    }
 
  i2c_dir_in();
  udelay(10);
  i2c_clk(1);
 
  ack=i2c_getbit();	/* Attends un ack I2C */
  i2c_clk(0);
  i2c_dir_out();
 
  if (ack==0)
    return 1;
  else
    return 0;
}
 
/*
 * Charge un octet sur I2C
 */
void
load_i2c(char adresse, char val)
{
  i2c_start();
  i2c_outbyte(STA_WRITE_CMD);
  i2c_outbyte(adresse);
  i2c_outbyte(val);
  i2c_stop();
}
 
/* I2C CODE FROM ACMESYSTEMS */
 
/*
 * Conversion de 2 caracteres ASCII en un binaire 8 bits
 */
unsigned char
asciitoint(unsigned char msb, unsigned char lsb)
{
  unsigned value;
 
  if(msb <= 0x39)
    msb = msb << 4;
  else
    {
      msb = msb - 7;
      msb = msb << 4;
    }
 
  if(lsb <= 0x39)
    lsb = lsb & 0x0F;
  else
    {
      lsb = lsb - 7;
      lsb = lsb & 0x0F;
    }
  value = msb | lsb;
  return value;
}
 
 
/*
 * Configure DSP STA013
 * avec le fichier config.hex
 */
int
configure_sta013(void) 
{
  FILE *fd;
  unsigned char sub_ad, val, lsb, msb;
  unsigned char buf[20000];
  int n=0, i=0;
 
  time_t t;
 
  /* Ouverture du port /dev/gpiob */  
  if (i2c_open()<0)
    return -1;
 
  /*
   * Ouverture du fichier et tlchargement 
   * sur le DSP STA013 par I2C
   */
  if ((fd = fopen(STA_CONF_FILE, "r"))== NULL)
    {
      fprintf(stderr, "Fichier inexistant\n");
      exit(1);
    }
 
  else
    { 
      fprintf(stderr, "Ouverture du fichier de config russie\n");
 
      while (!feof(fd))
	n = fread(&buf, 1, sizeof(buf), fd);
      //      fprintf(stderr, "taille=%d \n", n);      
 
      /* Recuperation de l'heure systeme */
      time(&t);
      printf("Nbre de secondes depuis le 1er Janvier 1970 : %ld\n", t);  
 
 
      while(i<n)
      	{
	  msb = buf[i++];
	  lsb = buf[i++];
 
	  sub_ad = asciitoint(msb, lsb);
 
	  msb = buf[i++];
	  lsb = buf[i++];
	  val = asciitoint(msb, lsb);
	  /*	  
	  fprintf(stderr, "adresse=%d ", sub_ad);
	  fprintf(stderr, "valeur=%d \n\n", val);      
	  */
	  load_i2c(sub_ad, val);
	}
 
      /*      fprintf(stderr, "nb iterations = %d \n\n", i);   */
    }
 
 
  /* Param specifiques au matriel */
  load_i2c(7, 0);       /* Non document */
  load_i2c(58, 0);      /* Non documente */
  load_i2c(85, 33);     /* PCMCONF I2S format */
  load_i2c(84, 1);	/* PCMDIV 256fc, 32 bits */
  load_i2c(13, 4);      /* CLK POL */
  load_i2c(24, 4);      /* REQ POL */
  load_i2c(114, 1); 	/* RUN */
 
  /* Recuperation de l'heure systeme */
  time(&t);
  printf("Nbre de secondes depuis le 1er Janvier 1970 : %ld\n", t);
 
  /* Ferme le flux et le port */
  fclose(fd);
  i2c_close();
  return 0;
}

Schematics

habib.bouaziz@gmail.com

Author

habib.bouaziz@gmail.com

 
sta013.txt · Last modified: 2008/11/30 11:00 by habib
 
All text is available under the terms of the GNU Free Documentation License (see Copyrights for details).