Showing posts with label DAC. Show all posts
Showing posts with label DAC. Show all posts

Wednesday, 29 April 2015

chipKIT DP32 Simple dub Siren Code



Sampling Rate 22.050 kHz, with 12 bit DAC MCP4725 ( breakout board)
Using button 2(Pin 17) on DP32 and Variable pot (A2).
For the signal out, the ac coupling circuit from previous post is necessary.
*Check also I2C Speed post HERE





















#include <sys/attribs.h>
#include <Wire.h>
#define MCP4725_DID 96 // define device id - see datasheet
//
#define SYS_FREQ            (40000000L)
#define PB_DIV              4
#define PRESCALE            2
#define FRQ                 22050 //21504
#define T1_TICK             (SYS_FREQ/PB_DIV/PRESCALE/FRQ)

#define WAVE_SAMPLES 256
const int buttonPin = 17; 
// variables will change:
int buttonState = 0;         // variable to read the pushbutton status
uint8_t playOn=0;            // Variable of play state/button state
volatile uint16_t a;
uint16_t b;
uint16_t d;
uint16_t e=0;
uint16_t inc;
uint8_t statedown=0;
boolean c;
boolean togg;
uint16_t sineData [WAVE_SAMPLES];
//


void setup()
{
  // Serial.begin(57600);
  initTmr();
  pinMode(A2, INPUT); //
  pinMode(13, OUTPUT); //
  //set pins to output because they are addressed in the main loop
  sine ();  
  Wire.begin() ;
}

void loop()
{
  uint16_t aIn =analogRead(A2);
  inc=aIn >>4;
  buttonState = digitalRead(buttonPin);

  // check if the pushbutton is pressed.
  // if it is, the buttonState is HIGH:
  if (buttonState == HIGH) {  
    playOn=1;   
    // play is On    
  } 
  else{
    playOn=0;
    // play is Off

  }
  if(c !=togg){

    if(playOn==1){

      a = a++  ;
      a+= (inc+(e >>4));
      if(a>=WAVE_SAMPLES){
        a-=WAVE_SAMPLES;
        // ramp up or down variables
        if (statedown==0){
          e++;
          if(e>=1023){
            statedown=1;
            e--;
          }
        }
        else{
          e--;
          if (e==0){
            statedown=0;
            e++;
          }
        }
      }
      //
      Wire.beginTransmission(MCP4725_DID); //device adress
      Wire.send(64);                     // cmd to update the DAC
      Wire.send(sineData[a] >> 4);        // the 8 most significant bits...
      Wire.send((sineData[a] & 15) << 4); /* the 4 least significant bis...*/
      Wire.endTransmission();
      /*
       */
    } 
  }//
  c=togg;
}

// call interrupt handling vector
extern "C" {

  void __ISR(16, ipl6) int1Handler(void) 
  {
    togg= !togg;
    //
    //
    IFS0CLR = 0x80000;// Clear the T4 interrupt flag Bit 19
    //
  }
}

void initTmr(){
  // 
  T4CON=0x0; //Stop timer and clear registers
  T4CONSET = 0x0010; // set prescalar 1:2 ox60 to experiment
  TMR4 = 0x0; //Clear Timer 4 register
  PR4 = T1_TICK ; //0x17; // set timer to 23 
  IFS0CLR = 0x80000;// Clear the T4 interrupt flag Bit 19
  IPC4SET = 0x00000016;// Interrupt priority 5, 2
  IEC0SET = 0x80000;// Enable T4 interrupt Bit 19
  T4CONSET = 0x8000;// Enable Timer4  
}
void sine (){
  uint16_t i;
  for(i=0;i<WAVE_SAMPLES;i++){
    b = 2047*sin((2*PI/WAVE_SAMPLES)*i);
    b+=2047;
    sineData [i]=b;
  }
}


ChipKIT DP32 I2C Bus Speed with a MCP4725 DAC

Both arduino and MPIDE seem to have the I2C bus speed set to 100 kHz by default. So, here it is how to change it to 400kHz.
Inside the MPIDE folder, go to hardware\pic32\libraries\Wire\utility.
Inside file twi.h Find the string #define TWI_FREQ 100000 and change it to:  #defineTWI_FREQ 400000.
In my simple test i went from a 20Hz sinewave to a 72Hz just by effecting this change to the bus speed.
On the DP32 Board, SDA is assigned to Pin RB9 and SCL to Pin RB8.





Friday, 5 September 2014

Example Saw waveform generator with R2R DAC ATmega328

/*
Example Saw waveform generator with 8 bit R2R DAC pin 0-7
Timer1 Interrupt
*/

#define WAVE_SAMPLES 256
volatile uint16_t a;
uint8_t sample = 0;
boolean c;
boolean togg;
int timer1_counter;

void setup()
{
  DDRD = 0xFF; //b11111111 d255

  // initialize timer1
  cli();           // disable all interrupts
  TCCR1A = 0;
  TCCR1B = 0;

  // Set timer1_counter to the correct value for our interrupt interval
  timer1_counter = 65443;   // preload timer 65536-16MHz/8/21504 Hz

  TCNT1 = timer1_counter;   // preload timer
  TCCR1B |= (1 << CS11);    // clk/8 prescaler
  TIMSK1 |= (1 << TOIE1);   // enable timer overflow interrupt
  sei();          // enable all interrupts
}

ISR(TIMER1_OVF_vect)        // interrupt service routine
{
  TCNT1 = timer1_counter;   // preload timer
  PORTD = sample;
  togg = !togg;
}

void loop()
{
  if (c != togg) {
    a++;
    if (a >= WAVE_SAMPLES) {
      a =0;
    }
    sample =a;
  } //
  c = togg;
}

Tuesday, 2 September 2014

Binary counter- 6 bit r2r DAC example for chipKit DP32 - PIC32MX250F128B

/*
Dubworks 6 bit r2r DAC example u4 LSB's using board leds 
 to display ;for chipKit DP32 board - PIC32MX250F128B
 @2014
 */
unsigned int i=0;
void setup(){
  Serial.begin(19200);
  LATBCLR = 0x3F;  // BIN 111111 ; 0xF for 4 leds only
  TRISBCLR =0x3F;  // Ports RB0-RB5 as Output ; 0xF for 4 leds only
}
void loop(){
  LATBCLR = 0x3F; //  clear 0xF for 4 leds only
  LATB |= i ;
  int a;
  a=PORTB;

  Serial.println(" I DEC ");
  Serial.println(i,DEC);
  Serial.println(" PORTD BIN ");
  Serial.println(a,BIN);

  i++;
  /* if you want to use the 5 bits of port B 0-4 */
  //  if(i < = 32){
  //    i=0; 
  //  }

  if(i < = 64){
    i=0;  
  }

  delay(250); //

}




note : P0-05 == RB0-RB5 ports

Monday, 1 September 2014

Digital to analog converters wise Pt 1/2

For audio purposes, it is quite common to find R2R-ladder Digital to analog converters (DAC's).
With microcontrollers, it is often a good idea to use a 595 Shift Register instead of direct ports not only to save ports but also because the 595 does a good job .
595 shift register can both source current when on a HIGH state and sink current when LOW. This is essential to create a more linear response and achieve monotonicity of output.
uC's like the ATMega328/Arduino Uno .do a good job at using a whole 8 bit port, as they can sink current as well, but that is reduced with the 3.3 V generation of chips ( average 20 mA, as opposed to 40 mA (milliamps) of current with an Arduino Uno).
The simplest textbook example of a Resistor-ladder DAC is a R/2nR DAC, also known as Binary Weighted DAC. This architecture is the most limited as well, and not inherently monotonic. Also to note that fact that impedance changes with input.
The method uses a sequence of ratios R, 2R, 4R, 8R. 16R , etc (R/16, R/8, R/4, R/2 and R for 5 bits is the usual way to refer to it).
And the difficulty of matching the ratios with resistors is one of the main reasons why its used mainly for small count bit solutions .
In theory, it looks to keep its monotonicity, but in reality tends to be somewhat different.


R2R Resistor ladder method, solves some of these problems by using resistors of only two different values, and their ratio is 2:1. It can also be achieved with resistors of just one value ( as in the example of a 6 bit solution, below).



So the theoretical schematic would be as in the next example  ( check live interactive simulator circuit on link; Circuit starts representing decimal 35 / binary 100011- Use the switches, most significant bit is on the left)





A good point to understand how it all works as far as circuit goes, would be TTL Logic basics( where each pin is the equivalent of two transistors and can both sink and source current..



*during some tests, i was able to derive 24 values out of 3 bits, with a log-like response using a theoretical tristate circuit. While this worked on paper, im still to try its concept :) Maybe i just rediscovered someone else's wheel !

Let this be a taster, while i build a 16 bit DAC ( a bit oversized if we compare it with a 12 bit MCP4725, for example :)
 I now know the real meaning behind the expression " Resistor's graveyard" eh eh




http://en.wikipedia.org/wiki/Resistor_ladder
http://www.dtic.mil/dtic/tr/fulltext/u2/019278.pdf