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

Monday, 4 August 2014

Arduino miniDUBsiren - compact pocket-sized dub siren



While i have to wait for some bits && pots to finish the other prototype, i decided to go back to Arduino Uno and do something quick; Ended up creating the Pocket sized miniDubSiren.
* I have even seen some 3D-printed cases for it here .



LCD Keypad Shield, Arduino Uno and you'd only have to worry about filtering the output. Cant get easier than that .
So, that makes it a shirt-pocket sized Dub Siren.
LFO is linear, for simplicity.
LCD displays top frequency/range and rate of LFO ( both with a minus - and a plus+ button for selection) and when sound is ON (triggered by the SELECT button: toggle action - one click ON , another OFF).
Also made a quick sounds FX generator for it, code to come soon ( even a "slightly slanted" sound wave LCD Char to go with it).
It was nice to work around the limitations of the available buttons and the frequency range in the tone function. Parameters can be changed during play, which creates some nice musical artifacts . A nice little toy.
While at it, developed a nice way of creating menus with this shield( despite not using it in this particular project, where simplicity was needed).

Button arrangement is : Trigger Toggle=Select  ; Freq= left/right ; Rate LFO=up/down .






//Sample using LiquidCrystal library
#include < LiquidCrystal.h >
//
byte wavform2[8] = {
  B01100,
  B10001,
  B10001,
  B00001,
  B00000,
  B00000,
  B00000,
};
byte wavform[8] = {
  B00000,
  B00000,
  B00000,
  B00001,
  B10001,
  B10010,
  B01100,
};
/*******************************************************

miniDubSiren by
Dubworks- Aug 2014
LCD KeyPad Code original by
Mark Bramwell- Jul 2010

********************************************************/// select the pins used on the LCD panel
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
uint16_t i = 100; // tone minimum
boolean play = false;
boolean down = false;
uint16_t topFreq = 864;
uint16_t rate = 0;

int outPin = 3; // define number of output pin
// define some values used by the panel and buttons
int lcd_key     = 0;
int adc_key_in  = 0;
#define btnRIGHT  0
#define btnUP     1
#define btnDOWN   2
#define btnLEFT   3
#define btnSELECT 4
#define btnNONE   5

// read the buttons
int read_LCD_buttons()
{
  adc_key_in = analogRead(0);      // read the value from the sensor
  // my buttons when read are centered at these valies: 0, 144, 329, 504, 741
  // we add approx 50 to those values and check to see if we are close
  if (adc_key_in > 1000) return btnNONE; // We make this the 1st option for speed reasons since it will be the most likely result
  //
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 250)  return btnUP;
  if (adc_key_in < 450)  return btnDOWN;
  if (adc_key_in < 650)  return btnLEFT;
  if (adc_key_in < 850)  return btnSELECT;

  return btnNONE;  // when all others fail, return this...
}

void setup()
{
  //  Serial.begin(9600);
  pinMode(outPin, OUTPUT);
  lcd.begin(16, 2);              // start the library
  lcd.createChar(0, wavform );
  lcd.createChar(1, wavform2 );
  lcdInit();
}

void loop()
{
  lcd_key = read_LCD_buttons();  // read the buttons

  switch (lcd_key)               // depending on which button was pushed, we perform an action
  {
    case btnRIGHT:
      {
        topFreq += 13;
        if (topFreq > 4000)
          topFreq = 4000;
        lcdFnct();
        delay(40);
        break;
      }
    case btnLEFT:
      {
        if (topFreq < 100)
          topFreq = 100;
        else
          topFreq -= 13 ;
        lcdFnct();
        delay(40);
        break;
      }
    case btnUP:
      {
        rate += 1 ;
        if (rate > 150) {
          rate = 150;
        }
        lcdFnct();
        delay(40);
        break;
      }
    case btnDOWN:
      {
        if (rate < 1)
          rate = 0;
        else
          rate -= 1 ;
        delay(40);
        lcdFnct();
        break;
      }
    case btnSELECT:
      {
        play = !play;
        if (play == false) {
          i = 100;
          noTone(3);
          delay(50);
        }
        delay(100);
        lcdFnct();
        break;
      }
    case btnNONE:
      {
        break;
      }
  }
  if (play == true) {
    tone(outPin, i);
    delay(5); // !!
  }
  else if (play == false) {
    i = 100;
    noTone(3);
    delay(50);
  }
  if (down == false) {
    i++;
    i += rate;
  }
  else if (down == true) {
    i--;
    i -= rate;
  }
  if (i > topFreq) {
    down = true;
    i = topFreq;
  }
  else if (i < 180) {
    down = false;
    i = 180;
  }
}
void lcdFnct() {
  lcd.clear();
  lcd.setCursor(0, 0);           //
  lcd.print("F= ");
  lcd.setCursor(4, 0);
  lcd.print(topFreq);
  lcd.setCursor(0, 1);
  lcd.print("R= ");
  lcd.setCursor(4, 1);
  lcd.print(rate);

  if (play == 1) {
    lcd.setCursor(10, 0);
    lcd.write(byte(0)); //
    lcd.setCursor(11, 0);
    lcd.write(byte(1));
    lcd.setCursor(10, 1);
    lcd.print("ON");
  }
}
void lcdInit() {
  lcd.setCursor(0, 0);
  lcd.print(" =  DubWorks  = "); // 
  lcd.setCursor(0, 1);
  lcd.print(" mini Dub Siren ");
  // scroll 12 positions to the right
  // to move it offscreen left:
  for (int positionCounter = 0; positionCounter < 12; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(50);
  }

  // scroll 26 positions to the right
  // to move it offscreen right:
  for (int positionCounter = 0; positionCounter < 26; positionCounter++) {
    // scroll one position right:
    lcd.scrollDisplayRight();
    // wait a bit:
    delay(50);
  }

  // scroll 14 positions to the left
  // to move it back to center:
  for (int positionCounter = 0; positionCounter < 14; positionCounter++) {
    // scroll one position left:
    lcd.scrollDisplayLeft();
    // wait a bit:
    delay(50);
  }

  // delay at the end of the full loop:
  delay(500);

}



3D-Printed case : http://apcmag.com/arduino-project-digital-clock.htm
LCD KEYPAD : http://www.dfrobot.com/wiki/index.phptitle=Arduino_LCD_KeyPad_Shield_(SKU:_DFR0009)

Wednesday, 30 July 2014

quick experiment with chipKit DP32 timers

quick experiment with chipKit DP32 timers



#include <sys/attribs.h>
#define WAVE_SAMPLES 256
uint16_t a;
uint16_t b;
uint16_t d;
uint16_t inc;
boolean c;
boolean togg;
uint16_t sineData [WAVE_SAMPLES]; // void setup() {   Serial.begin(19200);   initTmr();   pinMode(A2, INPUT); //   pinMode(13, OUTPUT); //LED   sine ();   } void loop() {   uint16_t aIn =analogRead(A2);   inc=aIn>>2;   d=sineData[a];   // if(c !=togg){   // Serial.println(a);   // Serial.println(d);   // Serial.println("inc");   // Serial.println(inc);   //   // //Serial.println("togg");   // //Serial.println(togg,DEC);   // } //   c=togg; } // call interrupt handling vector extern "C" {   void __ISR(16, ipl6) int1Handler(void)   {     togg= !togg;     analogWrite(13, d); //a++;     //     //     a++;     a+=inc;     if(a>=WAVE_SAMPLES)       a-=WAVE_SAMPLES;     IFS0CLR = 0x80000;// Clear the T4 interrupt flag Bit 19     //   } } void initTmr(){   //   T4CON=0x0; //Stop timer and clear registers   T4CONSET = 0x0070; // set prescalar 1:256   TMR4 = 0x0; //Clear Timer 4 register   PR4 = 0x1D1; // set timer to 465   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 = 127*sin((2*PI/WAVE_SAMPLES)*i);     b+=127;     sineData [i]=b;   } }

Tuesday, 29 July 2014

Dub && Wise Synth


*some decoupling capacitors 100nFclose to the analog pins should be added.




My initial intention was to create something focused for the soundsystem culture. This turned out to be much more difficult than i thought .
Dub siren/Elec tom synth/And oscilattor+ MAD Lfos (some trying to recreate some of the sounds in a synare that Jah Shaka got us all used to)...All this synthesized on the fly with the help of some wavetables (all created during the start up)
.
Pots for :
-Oscillator wave selector ( Sine,cosine  Saw, Inverted Saw, Square wave, triangle and 1 extra slots for now )
-LFO rate
-LFO modulator type select ( Any of the above tables, plus a few more specific and tailored options)
-Attack
-Release
* Both attack and release can interact with the LFO
- Mode selector ( Dub Siren, Sound effects " a la Synare", Elec-Tom synth)

This video is just as an update on the proceedings.
Here i am using the Arduino Due.
Due to its complexity, i ended up re-writing the whole code from scratch and fresh to suit this specific idea.
Already started porting a similar idea to the chipKit DP32, and Pinguino and an Xmos version also soon to come, subject to availability of spare time.