loopytune

21 views
Skip to first unread message

kal9001

unread,
Oct 21, 2014, 10:25:35 PM10/21/14
to barns...@googlegroups.com
Don't worry I didn't forget I've just had a play with the code myself neatening it up and swapping more onto AVR C.
Added a loop to make things much more compact.
I will post you what the example code from the guy who did the 'instructions' and a few steps of my code so you can see what I've done with it.
but probably will be the evening by the time I'm finished tweaking and testing. With any luck will stumble onto the issue myself but will still post the code to satisfy your curiosity :p

kal9001

unread,
Oct 22, 2014, 10:45:25 AM10/22/14
to barns...@googlegroups.com
Okay so time for the follow up for those that may be interested.
Looks like the main issue that was affecting the LCD and the noise on the analogue inputs was because the code was trying to update the LCD too often. doing multiple lcd.prints to construct a line on is the display, Changing it to form a string and then output to the display all in one go has drastically reduced the instability of the display and the analogue inputs.
I never did find out what was wrong with the tempo acting up the way it was, I can only conclude it was some sort of issue with the map() function, The sound it was generating suggested that an integer was overflowing but changing to long types had to effect.
Ether way the tempo code has been written in a far more logical manner and seems to work perfectly.

The sample code provided by the projects initial creator can be found on his Project page. There are also pictures and schematics.

The initial build for us was a letter by letter recreation of what the instructions say and then I modified this to be, In my view, more efficient.
Changes from the origonal are:-
Added the missing wire you may notice on the tempo pot, This should be wired as a divider.
Changed from a serial LCD to a HD44780 based LCD.
Removed the pull down resistors from the buttons and used the Microcontollers built in pull up resistors instead.
Changed the function of the duration variable so that it saved a discrete value for each note to allow individual notes to be of a different length.
Changed the function of the tempo variable so that it acts to multiply the duration value to speed up or slow down the whole sequence.
Changed the frequency generation so that different frequency ranges can be more easily selected.
Changed message on the welcome screen.
Altered pin layouts for more efficient and neater layout.
Formed readSwitches into a loop that uses AVR C port register manipulation for faster execution.
Speaker output now uses AVR C Port register manipulation for faster execution.
Changed some pin and variables definitions so sound more logical
Various minor formatting changes for proper indenting...ect.

Things left to do:-

Convert readPots into its AVR C equivelent.
Convert the arduino LCD library into its AVR C equivelent.
Convert remaining pin definitions to register values.
Add an external reset button.
Allow a silent tone to be played, To insert pauses between notes.
Possibility of adding extra buttons for more positions in the sequence.

the current code is below. I am still in the process of converting the whole thing into AVR C so its still a bit of a mish mash at the moment.

/*

Loopytune Mk1 - 8 channel chip tune sequencer.

code origonally by Paul Badger, 
heavily modified by kal9001

#############################################
# Frequency range options are at the bottom #
# in the freqout function                   #
#############################################
*/

// Map all the input and output pins
#define duration_select A4    //Duration  PC3
#define frequency_select A3   //Frquency  PC4
#define tempo_select A5       //Tempo     PC5

#define audio_out A2   //speaker  PC2

//Buttons 1 - 8 on PD0 to 7
//Switch on/off  PC1

#include <LiquidCrystal.h> // include the LCD library code:

// misc housekeeping
int play = 1;
int lastPushedStep = -1;
int tempo = 512;
int tempo_out;
int duration[] = {250, 250, 250, 250, 250, 250, 250, 250}; // set up duration array
int note[] = {128, 256, 384, 512, 640, 768, 896, 1024}; // Set up note array
int tempo_display;
int duration_display;
int frequency_display;


LiquidCrystal lcd(8, 9, 13, 12, 11, 10); // initialize the library with the numbers of the interface pins

void setup()
{  
  DDRD   = 0x00;  //Port D all inputs
  PORTD  = 0xFF;  //port D pull up resistors active
  DDRC  &= 0xFD;  //port C1 as input
  PORTC |= 0x02;  //port C1 pull up resistor active
  
  pinMode (audio_out, OUTPUT); //PC2
  
  lcd.begin(16, 2); // set up the LCD's number of columns and rows:
  lcd.noCursor();
  welcome_lcd();

void loop() 
  for (int i = 0 ; i < 8 ; i++ )
  {   
    play = digitalRead(start_stop); //read start/stop switch
    readPots(); //read Potentiomiters
    readSwitches(); //read buttons
    update_lcd(); // Update LCD
    if (!play)
    {
      freqout (note[i], duration[i], tempo_display); //Play note for duration
    }
    else
    {
      delay(250);
    }
  }
}

///////////////////////functions//////////////////////////////////////////////

void welcome_lcd()
{
  lcd.clear();
  lcd.print ("Made by:");
  lcd.setCursor(0, 1);
  lcd.print ("Drakkn & kal9001");
  delay(2000);
  lcd.clear();
  lcd.print ("Loopytune Mk1");
  lcd.setCursor(0, 1);
  lcd.print ("V1.22");
  delay (2000);
}

void update_lcd()
{
  lcd.clear();
  lcd.print(("T:" + (String)tempo_display));
  lcd.setCursor(0, 1);
  lcd.print((((("D:" + (String)duration_display) + " F:") + (String)(frequency_display * 2))+ "Hz"));
  if (lastPushedStep != -1)
  {
    lcd.setCursor(13, 0);
    lcd.print(("*" + (String)lastPushedStep));
  }
}

void readPots()
{
  tempo_display = analogRead(tempo_select);
  duration_display = analogRead(duration_select);
  frequency_display = analogRead(frequency_select);    
}

void readSwitches()
{
  lastPushedStep = -1;  //reset variable
  for (int i = 0 ; i <= 7 ; i++ )
  {
    if (!(PIND & (1<<i))) //read port D pins one at a time
    {
      note[i] = frequency_display;
      duration[i] = duration_display;
      lastPushedStep = (i + 1); //set variable
    }
  }
}

void freqout(int f, long d, int t)
  int tempo = t;
  int period;
  long cycles, i;
    
  if(t == 0) { t = (t + 1); } //avoid any * or / by zero shenanigans
  d = d * (t/ 50);
  if(d <= 100 ) { d = 100; }  // durations less than 100 are just clicks anyway
  if(d >= 5000) { d = 5000; } // sets maximum duration to stop things getting silly

  // Scale can use any values, lower is higher frequency but resolution is lost.
  // lowfq sets the low threshold, low 'scale' needs lower ofset to maintain the same overall level
  // Some useful values are listed.
  // 500,000L + 40 = 1044 Hz max = 40Hz min ~1Hz/step
  // 250,000L + 20 = 2070 Hz max = 40Hz min ~2Hz/step
  // 125,000L + 10 = 4132 Hz max = 40Hz min ~4Hz/step
  // 62,500L + 5 = 8264 Hz max = 40Hz min ~8hz/step
  long scale = 250000;
  int ofset = 20;
  
  period = (int)(scale / (f + ofset)); // calculate note period in us          
  cycles = (int)((f * d) / 1000); //how many loop itterations does it last
  
  for ( i=0 ; i < cycles ; i++ )
  {
    PORTC |= 0x04;   //fast write to audio out pin
    delayMicroseconds(period);  // delay for half note period
    PORTC &= 0xFB;  //fast write to audio out pin
    delayMicroseconds(period);  //delay for half not period
  }
}

As always, comments and suggestions are welcome.
 

Paul Beard

unread,
Oct 23, 2014, 5:57:45 PM10/23/14
to barns...@googlegroups.com


On Wednesday, 22 October 2014 15:45:25 UTC+1, kal9001 wrote:
Things left to do:-

Possibility of adding extra buttons for more positions in the sequence.


Hi Kev, here's a way to increase the number of buttons AND free up some digital inputs. In the diagram below, 12 buttons are connected using only 4 inputs. 5 inputs would allow 20 buttons, 6 would allow 30, 7 would allow 42 and all 8 would allow 56 buttons using this method.

Paul
 

Paul Beard

unread,
Oct 23, 2014, 6:01:56 PM10/23/14
to barns...@googlegroups.com


On Wednesday, 22 October 2014 15:45:25 UTC+1, kal9001 wrote:

  long scale = 250000;

You missed the "L" off that constant.

kal9001 .

unread,
Oct 23, 2014, 6:11:28 PM10/23/14
to barns...@googlegroups.com
Well the code works anyway :P I'm in the process of learning myself C and C++ which is interesting...I've started with this very same code and moving it over to AVR C as you know and there are certainly some challenges. Quite a lot of it is going smoothly just a few bits holding everything up, namely 3rd party libraries that are written in a more advanced state than I can readily understand, coupled with bloat and the linker/compiler shouting at me for not putting stuff in headers properly or some other such crap....

I've only done bits and bobs with C before nothing close to creating an application. Personally I don't think I'm doing too badly with it considering how long I've actively been working on it (Couple of days)...How long does it normally take to learn C and/or C++?

Taking a break now for a few days anyway going to begin working on a new project...something nice and simple for the ATtiny85, Atleast I have the chips sat here for those and I can SEE them working right now.
(The 328Ps still havent arrived yet....Nor have my shift registers! >:( my external cat6 did though so this weekend the workshop will finally have GBE and I can stop using the wifi bridge, Just in time for my fibre internet to come back alive too!)

--
You received this message because you are subscribed to a topic in the Google Groups "BARNSLEY.IO" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/barnsleyio/9T6e8uW89pY/unsubscribe.
To unsubscribe from this group and all its topics, send an email to barnsleyio+...@googlegroups.com.
To post to this group, send email to barns...@googlegroups.com.
Visit this group at http://groups.google.com/group/barnsleyio.
To view this discussion on the web, visit https://groups.google.com/d/msgid/barnsleyio/62bd4f57-4242-44df-868c-04f82c09b27b%40googlegroups.com.

For more options, visit https://groups.google.com/d/optout.

Reply all
Reply to author
Forward
0 new messages