Lets Make Tech

Arduino Music Box

Credit to David Mills http://webshed.org/wiki/AD9850_Arduino for the code to interface with the signal generator.   

Here is a video to show what to expect from this project. I got a couple of the notes wrong in this video but they have been corrected in the code below.  

 

 

Bill of Materials:

-1 Arduino

-1 LCD display (optional)

-1 AD9850 DDS signal generator

-1 pizzo electric buzzer

 

I will leave the LCD up to you, and just provide instructions on how to make some music with the AD9850 DDS and an Arduino.  

Note the connections between the arduino and the AD9850 DDS signal generator. Feel free to change them if you need.  

#define CLOCK 2 //pin connections for DDS
#define LOAD 3
#define DATA 7
#define RESET 8

Hook the pizzo buzzer to the square wave output and ground.

Now we need some notes, I referred to http://www.phy.mtu.edu/~suits/notefreqs.html to get a few. 

To play a note you can use this function: note(G*10, 750);  Place the desired note, the octave, then the length to play the note.

The octave scale is not linear.

Please note that I do not use real notes in the Waltz program, but it uses relative frequencies. The scale program does use real notes.

A*20 comes after G*10 however these will not be real musical notes.

 

To use real notes start with A*1, A*2, A*4, A*8, etc. If you are not worried about using real notes then just be sure that your are consistent relative the note you start on.  

This code is a little rushed and could be cleaned up a lot and is just for reference. If you use it be sure to credit David Mills http://webshed.org/wiki/AD9850_Arduino   for the part he wrote as well as me for the parts I wrote and don't claim the code as your own or try to prevent anyone else using it other than that do with it what you will. 

Below is the code to play Waltz From Sleeping Beauty and the code to play all of the real musical notes.

You can also turn this into a musical instrument by adding buttons that play notes.

Scale

#include <LiquidCrystal.h>

LiquidCrystal lcd(5, 6, 9, 10, 11, 12);


#define DDS_CLOCK 125000000

#define  CLOCK  2  //pin connections for DDS
#define  LOAD 3 
#define  DATA  7
#define  RESET 8
#define  POTPIN A0
#define  MODE 13

//Notes
#define A 27.5
#define AS 29.14
#define B 30.87
#define C 32.7
#define CS 34.65
#define D 36.71
#define DS 38.89
#define E 41.2
#define F 43.65
#define FS 46.25
#define G 49
#define GS 51.91

float hrz;
float time;
void setup()
{
  pinMode(DATA, OUTPUT); 
  pinMode(CLOCK, OUTPUT); 
  pinMode(LOAD, OUTPUT); 
  pinMode(RESET, OUTPUT); 
  pinMode(POTPIN, INPUT);
  pinMode(MODE, INPUT);
  AD9850_init();
  AD9850_reset();
  lcd.begin(16, 2);
  
  Serial.begin(9600);
    lcd.setCursor(0, 0);
    lcd.print("Note");
    lcd.setCursor(0, 1);
    lcd.print("Range");
  //SetFrequency(hrz);

}

void loop()
{ 
  int x=1;
  for (int i=0;i<10;i++)
  {
    intro(x);
    x=x*2;
  }
  for (int i=0;i<10;i++)
  {
    outro(x);
    x=x/2;
  }
} 


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

    digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}

void note(float hrz, float time)
{
   SetFrequency(hrz);
   delay(time);
}



void intro(int i)
{
    note(A*i, 250);
    note(AS*i, 250);
    note(B*i, 250);
    note(C*i, 250);
    note(CS*i, 250);
    note(D*i, 250);
    note(DS*i, 250);
    note(E*i, 250);
    note(F*i, 250);
    note(FS*i, 250);
    note(G*i, 250);
    note(GS*i, 250);    
}

void outro(int i)
{
  note(GS*i, 250);  
  note(G*i, 250);
  note(FS*i, 250); 
  note(F*i, 250);
  note(E*i, 250);
  note(DS*i, 250);
  note(D*i, 250);
  note(CS*i, 250);
  note(C*i, 250);
  note(B*i, 250);
  note(AS*i, 250);
  note(A*i, 250);


  
  
}

 

 

 

 

 

 

Waltz From Sleeping Beauty

#include <LiquidCrystal.h>

LiquidCrystal lcd(5, 6, 9, 10, 11, 12);


#define DDS_CLOCK 125000000

#define  CLOCK  2  //pin connections for DDS
#define  LOAD 3 
#define  DATA  7
#define  RESET 8


//Notes
#define A 27.5
#define As 29.14
#define B 30.87
#define C 32.7
#define Cs 34.65
#define D 36.71
#define Ds 38.89
#define E 41.2
#define F 43.65
#define Fs 46.25
#define G 49
#define Gs 51.91

float hrz;
float time;
void setup()
{
  pinMode(DATA, OUTPUT); 
  pinMode(CLOCK, OUTPUT); 
  pinMode(LOAD, OUTPUT); 
  pinMode(RESET, OUTPUT); 
  pinMode(POTPIN, INPUT);
  pinMode(MODE, INPUT);
  AD9850_init();
  AD9850_reset();
  lcd.begin(16, 2);
  
  Serial.begin(9600);
    lcd.setCursor(0, 0);
    lcd.print("Waltz From");
    lcd.setCursor(0, 1);
    lcd.print("Sleeping Beauty");
  //SetFrequency(hrz);

}

void loop()
{ 
  intro();
  //Start repeat sign
  repeatedmusic();
  repeatedone();
  repeatedmusic();
  repeatedtwo();
  ending();
} 


void SetFrequency(unsigned long frequency)
{
  unsigned long tuning_word = (frequency * pow(2, 32)) / DDS_CLOCK;
  digitalWrite (LOAD, LOW); 

  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 8);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 16);
  shiftOut(DATA, CLOCK, LSBFIRST, tuning_word >> 24);
  shiftOut(DATA, CLOCK, LSBFIRST, 0x0);
  digitalWrite (LOAD, HIGH); 
}

void AD9850_init()
{

  digitalWrite(RESET, LOW);
  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);
  digitalWrite(DATA, LOW);
}

void AD9850_reset()
{
  //reset sequence is:
  // CLOCK & LOAD = LOW
  //  Pulse RESET high for a few uS (use 5 uS here)
  //  Pulse CLOCK high for a few uS (use 5 uS here)
  //  Set DATA to ZERO and pulse LOAD for a few uS (use 5 uS here)

  // data sheet diagrams show only RESET and CLOCK being used to reset the device, but I see no output unless I also
  // toggle the LOAD line here.

  digitalWrite(CLOCK, LOW);
  digitalWrite(LOAD, LOW);

  digitalWrite(RESET, LOW);
  delay(5);
  digitalWrite(RESET, HIGH);  //pulse RESET
  delay(5);
  digitalWrite(RESET, LOW);
  delay(5);

  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(CLOCK, HIGH);  //pulse CLOCK
  delay(5);
  digitalWrite(CLOCK, LOW);
  delay(5);
  digitalWrite(DATA, LOW);    //make sure DATA pin is LOW

    digitalWrite(LOAD, LOW);
  delay(5);
  digitalWrite(LOAD, HIGH);  //pulse LOAD
  delay(5);
  digitalWrite(LOAD, LOW);
  // Chip is RESET now
}

void note(float hrz, float time)
{
   SetFrequency(hrz);
   delay(time);
}



void intro()
{
    note(G*10, 1000);
  
  note(Fs*10, 1000);
  
  note(G*10, 750);
  note(E*10, 250);
  
  note(Fs*10, 250);
  note(G*10, 250);
  note(E*10, 250);
  
  note(Fs*10, 500);
  note(A*20, 250);
  
  note(B*20, 500);
  note(Gs*10, 250);
  
  note(A*20, 1500);
  
  note(D*20, 750);
  
  note(Cs*20, 750);

  note(C*20, 500);
  note(A*20, 250);
  
  note(C*20, 250);
  note(B*20, 250);
  note(A*20, 250);
  
  note(E*20, 500);
  note(D*20, 250);
  
  note(C*20, 500);
  note(B*20, 250);
  note(0,1);
  
  note(B*20,250);
  note(A*20,250);
  note(Gs*10, 250);
  
  note(A*20,250);
  note(E*10,250);
  note(Fs*10,250); 
  
  note(G*10,750);
  
  note(Fs*10,750);
  
  note(G*10,500);
  note(E*10,250);
 
  note(Fs*10,250);
  note(G*10, 250);
  note(E*10,250);
  
  note(Fs*10,500);
  note(A*20,250);
  
  note(B*20,500);
  note(Gs*10, 250);
  
  note(A*20,1500);
  
  note(B*20,500);
  note(C*20,250);
  
  note(C*20,250);
  note(Cs*20,500);
  
  note(E*20,500);
  note(D*20,250);
  
  note(D*20,250);
  note(Fs*20,500);
  
  note(G*20,500);
  note(Fs*20,250);
  
  note(Fs*20,250);
  note(E*20,500);
  note(0, 10);
  
  note(D*20,125);
  note(0,125);
  note(Cs*20,125);
  note(D*20,125);
  note(E*20,125);
  
  note(D*20,125);
  note(B*20,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  note(Fs*10,125);
  
  note(D*10,125);
  note(0,125);
  note(D*20,500);
  
  note(E*20,500);
  note(Fs*20,250);
}


void repeatedmusic()
{
  note(G*20,125);  
  note(0,125);
  note(As*20,125);
  note(B*20,125);
  note(C*20,125);
  note(B*20,125);
  
  note(D*20,125);
  note(0,125);
  note(G*10,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(B*20,125);
  note(0,125);
  note(Fs*10,125);
  note(G*10,125);
  note(A*20,125);
  note(G*10,125);
  
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(E*10,125);
  
  note(D*10,125);
  note(0,125);
  note(Cs*20,125);
  note(D*20,125);
  note(E*20,125);
  note(D*20,125);
  
  note(Fs*20,125);
  note(E*20,125);
  note(D*20,125);
  note(Cs*20,125);
  note(D*20,125);
  note(As*20,125);
  
  note(B*20,125);
  note(0,125);
  note(D*20,500);
  
  note(E*20,500);
  note(Fs*20,250);
  
  note(G*20,125);
  note(0,125);
  note(As*20,125);
  note(B*20,125);
  note(C*20,125);
  note(B*20,125);
  
  note(D*20,125);
  note(0,125);
  note(Gs*10,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(B*20,125);
  note(0,125);
  note(Fs*10,125);
  note(G*10,125);
  note(A*20,125);
  note(G*10,125);
  
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(E*10,125);
  
  note(Cs*10,125);
  note(0,125);
  note(C*20,125);
  note(Cs*20,125);
  note(D*20,125);
  note(Cs*20,125);
  
}


void repeatedone()
{
    note(Fs*20,125);
    note(E*20,125);
    note(D*20,125);
    note(Cs*20,125);
    note(B*20,125);
    note(A*20,125);
    
    note(D*20,125);
    note(0,125);
    note(D*20,500);
    
    note(E*20,500);
    note(Fs*20,250);
}

void repeatedtwo()
{
  note(D*20,125);
  note(Cs*20,125);
  note(B*20,125);
  note(A*20,125);
  note(G*10,125);
  note(Fs*10,125); 
  
}

void ending()
{
  note(D*20,125);
  note(C*20,125);
  note(B*20,125);
  note(A*20,125);
  note(B*20,125);
  note(A*20,125);
  
  note(G*10,125);
  note(Fs*10,125);
  note(G*10,125);
  note(Fs*10,125);
  note(E*10,125);
  note(D*10,125);
  
  note(Fs*10,125);
  note(E*10,125);
  note(D*10,125);
  note(C*10,125);
  note(E*10,125);
  note(D*10,125);
  
  note(C*10,125);
  note(B*10,125);
  note(D*10,125);
  note(C*10,125);
  note(B*10,125);
  note(D*10,125);
  
  note(G*10,750);
  
  note(Fs*10,750);
  
  note(G*10,500);
  note(C*10,250);
  
  note(E*10,250);
  note(E*10,250);
  
  note(Fs*10,250);
  note(G*10,250);
  note(E*10,250);
  
  note(F*10,500);
  note(A*20,250);
  
  note(B*20,500);
  note(G*10,250);
  
  note(A*20,1500);
  
  note(Ds*20,750);
  
  note(D*20,750);
  
  note(C*20,500);
  note(A*20,250);
  
  note(C*20,250);
  note(B*20,250);
  note(A*20,250);
  
  note(E*20,500);
  note(D*20,250);
  
  note(C*20,500);
  note(B*20,250);
  delay(1);
  
  note(B*20,250);
  note(A*20,250);
  note(G*10,250);
  
  note(A*20,250);
  note(E*10,250);
  note(F*10,250);
  
  note(G*10,750);
  
  note(F*10,750);
  
  note(G*10,500);
  note(E*10,250);
  
  note(Fs*10,250);
  note(G*10,250);
  note(Gs*10,250);
  
  note(A*20,500);
  note(Fs*10,250);
  
  note(B*20,500);
  note(Gs*20,250);
  
  note(A*20,125);
  note(0,125);
  note(E*10,125);
  note(Gs*5,125);
  note(A*10,125);
  note(C*10,125);
  
  note(E*10,125);
  note(Ds*10,125);
  note(E*10,125);
  note(Gs*10,125);
  note(A*20,125);
  note(C*20,125);
  
  note(Ds*20,500);
  note(E*20,250);
  
  note(E*20,250);
  note(Fs*20,500);
  
  note(A*40,250);
  note(G*20,250);
  
  note(G*20,250); 
  note(B*40,500);
  
  note(C*40,500);
  note(B*40,250);
  
  note(B*40,250);
  note(A*40,500);
  
  note(G*20,125);
  note(0,125);
  note(Fs*20,125);
  note(G*20,125);
  note(D*20,125);
  note(B*20,125);
  
  note(G*10,125);
  note(0,625);
}

Circular Buffer Pointer Addition and Subtraction

This tutorial is to teach you how to add and subtract a value to a pointer value in a circular buffer without going over the size, or below 0, so that it loops back around. The goal is to do this without using any loops, negative numbers, or if statements. We just want a generic mathematical formula that can be used. We also want one formula that does both addition or subtraction depending on if you pass a positive or negative number. 

Circular Buffer

As an example we will use one with a size of 8 (0-7). Lets call it var[buffersize] buffersize=7 Size=buffersize+1. 

7
6
5
4
3
2
1
0

Now to add or subtract to this we need to know a few things the size (S), the current pointer location (P), and the value we are adding or subtracting(X) and we will call the new value N. 

We can't just say N=P-X or N=P+X. It works in some cases but in others it causes the value to exceed 7 or drop below 0, and we can't have that. We could use if statements and loops but that is slow. 

If you want you can try to solve it yourself then check back and see if we came up with the same formula. If you come up with a better solution, let me know in the comments. Just remember, no negative numbers, 'if' statements, loops, and it must be compatible in across programming languages. 

Here are some example values and their solutions:

S=8, P=5, and X=1

We know that 5+1=6 and 5-1=4. It stays inside the boundaries so it is ok.

Now lets try S=8, P=5, X=15. Now we have a problem, if you add 15 to 5 you exceed 7 and if you subtract 15 from 5 you drop below 0. This is bad, we want it to loop around. Count the tiles and loop back, you will find that adding you get 4 and subtracting you get 6.

So we are going to make one formula for addition, which is fairly easy to do, then another for subtraction which is not so easy.   

 

Addition 

I came up with N=(P+X)%S 

Lets test it out on the previous examples.

1.S=8, P=5, and X=1

(5+1)%8=6%8=6. 

2.S=8, P=5, X=15

(5+15)%8=20%8=4

The answers match up with what we found counting. Awesome, now for subtraction which is a little more tricky because we don't want to deal with any negative numbers. 

Subtraction 

Language Differences

So you may say alright subtraction must be N=(P-X)%S. Lets look at why N=(P-X)%S does not work in C based languages. 

To understand this we have to understand the difference between "%" in C and "%" in other languages. 

In C "%" is a remainder operator. The remainder will share the same sign as the division solution.

In other languages "%" is a modulo operator and will always give a positive result.

This causes -2%8 to either equal 2 or -6 depending on which language you are using.

You may notice that to get the correct answer with C, you just need to add that answer to the size and you will also get 2.   

Solution

The formula I came up with is N=(S-(X%S)+P)%S

So lets test it out on those examples again. 

1.S=8, P=5, and X=1

(8-(1%8)+P)%8=(8-1+5)%8=12%8=4

So far so good! Now to test one of cases that causes all the trouble.

2.S=8, P=5, X=15

(8-(15%8)+5)%8=(8-7+5)%8=6%8=6

It works! This should speed up your code if you have been using if statements or something like that previously. 

Universal Formula

So if you want a formula that does both addition and subtraction so you can just pass a positive or negative value to a function. 

((s*x*x)+(p + x)) % s

 

Formula List

S=buffer size, X=value being added (negative for subtraction), and P= the current pointer position. 

Addition

N=(P+X)%S

Subtraction

 

Non C Languages Only:

N=(P+X)%S

 

C Languages Only:

N=(S+(P-X))%S

 

All Languages (Don't quote me on that, test to make sure)

N=(S-(X%S)+P)%S

Or if you prefer you can write it like this:

N=((S+P)-(X%S))%S

Universal, Addition and Subtraction

((s*x*x)+(p + x)) % s

 

Lets test it out with a sample program. I wrote this in c++ as a windows console app in visual studio. 

In this program the value for each pointer is the same as the pointer. For example var[6]=6, var[5]=5. This is just to demonstrate that it is working correctly. 

 So here it is with the different equations 

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
const int buffersize = 7;
int var[buffersize];
int p;
int s;
int quit;
void setup();
void loop();
void add(int x);
void sub(int x);

int _tmain(int argc, _TCHAR* argv[])
{
	while (1)
	{
		setup();//this gives each pointer the same value as its address. We will print it later.
		loop();//test a bunch of values being added or subtracted to each pointer.
		cout << "Enter \"0\" to quit:";
		cin >> quit;
		if (quit == 0)
		{
			return 0;
		}
	}
}

void setup()
{
	s = buffersize + 1;
	for (int i = 0; i < 7; i++)
	{
		var[i] = i;
	}
}

void loop()
{
	for (int i = 0; i < 7; i++)
	{
		p = i;
		for (int j = 0; j < 21; j++)
		{
			add(j);
			sub(j);
		}
	}
}

void add(int x)
{
	cout << p << "+" << x << "=" <<(p + x) % s<<endl;
}

void sub(int x)
{
	cout << p << "-" << x << "=" << (s - (x%s) + p) % s<<endl;
}

 

And here is the output

0+0=0
0-0=0
0+1=1
0-1=7
0+2=2
0-2=6
0+3=3
0-3=5
0+4=4
0-4=4
0+5=5
0-5=3
0+6=6
0-6=2
0+7=7
0-7=1
0+8=0
0-8=0
0+9=1
0-9=7
0+10=2
0-10=6
0+11=3
0-11=5
0+12=4
0-12=4
0+13=5
0-13=3
0+14=6
0-14=2
0+15=7
0-15=1
0+16=0
0-16=0
0+17=1
0-17=7
0+18=2
0-18=6
0+19=3
0-19=5
0+20=4
0-20=4
1+0=1
1-0=1
1+1=2
1-1=0
1+2=3
1-2=7
1+3=4
1-3=6
1+4=5
1-4=5
1+5=6
1-5=4
1+6=7
1-6=3
1+7=0
1-7=2
1+8=1
1-8=1
1+9=2
1-9=0
1+10=3
1-10=7
1+11=4
1-11=6
1+12=5
1-12=5
1+13=6
1-13=4
1+14=7
1-14=3
1+15=0
1-15=2
1+16=1
1-16=1
1+17=2
1-17=0
1+18=3
1-18=7
1+19=4
1-19=6
1+20=5
1-20=5
2+0=2
2-0=2
2+1=3
2-1=1
2+2=4
2-2=0
2+3=5
2-3=7
2+4=6
2-4=6
2+5=7
2-5=5
2+6=0
2-6=4
2+7=1
2-7=3
2+8=2
2-8=2
2+9=3
2-9=1
2+10=4
2-10=0
2+11=5
2-11=7
2+12=6
2-12=6
2+13=7
2-13=5
2+14=0
2-14=4
2+15=1
2-15=3
2+16=2
2-16=2
2+17=3
2-17=1
2+18=4
2-18=0
2+19=5
2-19=7
2+20=6
2-20=6
3+0=3
3-0=3
3+1=4
3-1=2
3+2=5
3-2=1
3+3=6
3-3=0
3+4=7
3-4=7
3+5=0
3-5=6
3+6=1
3-6=5
3+7=2
3-7=4
3+8=3
3-8=3
3+9=4
3-9=2
3+10=5
3-10=1
3+11=6
3-11=0
3+12=7
3-12=7
3+13=0
3-13=6
3+14=1
3-14=5
3+15=2
3-15=4
3+16=3
3-16=3
3+17=4
3-17=2
3+18=5
3-18=1
3+19=6
3-19=0
3+20=7
3-20=7
4+0=4
4-0=4
4+1=5
4-1=3
4+2=6
4-2=2
4+3=7
4-3=1
4+4=0
4-4=0
4+5=1
4-5=7
4+6=2
4-6=6
4+7=3
4-7=5
4+8=4
4-8=4
4+9=5
4-9=3
4+10=6
4-10=2
4+11=7
4-11=1
4+12=0
4-12=0
4+13=1
4-13=7
4+14=2
4-14=6
4+15=3
4-15=5
4+16=4
4-16=4
4+17=5
4-17=3
4+18=6
4-18=2
4+19=7
4-19=1
4+20=0
4-20=0
5+0=5
5-0=5
5+1=6
5-1=4
5+2=7
5-2=3
5+3=0
5-3=2
5+4=1
5-4=1
5+5=2
5-5=0
5+6=3
5-6=7
5+7=4
5-7=6
5+8=5
5-8=5
5+9=6
5-9=4
5+10=7
5-10=3
5+11=0
5-11=2
5+12=1
5-12=1
5+13=2
5-13=0
5+14=3
5-14=7
5+15=4
5-15=6
5+16=5
5-16=5
5+17=6
5-17=4
5+18=7
5-18=3
5+19=0
5-19=2
5+20=1
5-20=1
6+0=6
6-0=6
6+1=7
6-1=5
6+2=0
6-2=4
6+3=1
6-3=3
6+4=2
6-4=2
6+5=3
6-5=1
6+6=4
6-6=0
6+7=5
6-7=7
6+8=6
6-8=6
6+9=7
6-9=5
6+10=0
6-10=4
6+11=1
6-11=3
6+12=2
6-12=2
6+13=3
6-13=1
6+14=4
6-14=0
6+15=5
6-15=7
6+16=6
6-16=6
6+17=7
6-17=5
6+18=0
6-18=4
6+19=1
6-19=3
6+20=2
6-20=2
Enter "0" to quit:

 And here it is with the universal formula 

// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
using namespace std;
const int buffersize = 7;
int var[buffersize];
int p;
int s;
int quit;
void setup();
void loop();
void add(int x);
void sub(int x);

int _tmain(int argc, _TCHAR* argv[])
{
	while (1)
	{
		setup();//this gives each pointer the same value as its address. We will print it later.
		loop();//test a bunch of values being added or subtracted to each pointer.
		cout << "Enter \"0\" to quit:";
		cin >> quit;
		if (quit == 0)
		{
			return 0;
		}
	}
}

void setup()
{
	s = buffersize + 1;
	for (int i = 0; i < 7; i++)
	{
		var[i] = i;
	}
}

void loop()
{
	for (int i = 0; i < 7; i++)
	{
		p = i;
		for (int j = 0; j < 20; j++)
		{
			add(j);
			sub(j);
		}
	}
}

void add(int x)
{
	cout << "Add" << s << "  Pointer:" << p << "+" << x << "=" << ((s*x*x) + (p + x)) % s << endl;
}

void sub(int x)
{
	x = x*-1;
	//cout <<"correct"<< p << "-" << x << "=" << (s - (x%s) + p) % s<<endl;
	//cout << "Buffer Size:" << s << "  Pointer:" << p << "-" << x << "=" << ((s*x) + (p - x)) % s << endl;
	//cout << "Test" << s << "  Pointer:" << p << "-" << x << "=" << ((s + p) - (x%s)) % s << endl;

	cout << "Sub" << s << "  Pointer:" << p << "-" << x << "=" << ((s*x*x)+(p + x)) % s <<endl;

	

}

 

Add8  Pointer:0+0=0
Sub8  Pointer:00=0
Add8  Pointer:0+1=1
Sub8  Pointer:0-1=7
Add8  Pointer:0+2=2
Sub8  Pointer:0-2=6
Add8  Pointer:0+3=3
Sub8  Pointer:0-3=5
Add8  Pointer:0+4=4
Sub8  Pointer:0-4=4
Add8  Pointer:0+5=5
Sub8  Pointer:0-5=3
Add8  Pointer:0+6=6
Sub8  Pointer:0-6=2
Add8  Pointer:0+7=7
Sub8  Pointer:0-7=1
Add8  Pointer:0+8=0
Sub8  Pointer:0-8=0
Add8  Pointer:0+9=1
Sub8  Pointer:0-9=7
Add8  Pointer:0+10=2
Sub8  Pointer:0-10=6
Add8  Pointer:0+11=3
Sub8  Pointer:0-11=5
Add8  Pointer:0+12=4
Sub8  Pointer:0-12=4
Add8  Pointer:0+13=5
Sub8  Pointer:0-13=3
Add8  Pointer:0+14=6
Sub8  Pointer:0-14=2
Add8  Pointer:0+15=7
Sub8  Pointer:0-15=1
Add8  Pointer:0+16=0
Sub8  Pointer:0-16=0
Add8  Pointer:0+17=1
Sub8  Pointer:0-17=7
Add8  Pointer:0+18=2
Sub8  Pointer:0-18=6
Add8  Pointer:0+19=3
Sub8  Pointer:0-19=5
Add8  Pointer:1+0=1
Sub8  Pointer:10=1
Add8  Pointer:1+1=2
Sub8  Pointer:1-1=0
Add8  Pointer:1+2=3
Sub8  Pointer:1-2=7
Add8  Pointer:1+3=4
Sub8  Pointer:1-3=6
Add8  Pointer:1+4=5
Sub8  Pointer:1-4=5
Add8  Pointer:1+5=6
Sub8  Pointer:1-5=4
Add8  Pointer:1+6=7
Sub8  Pointer:1-6=3
Add8  Pointer:1+7=0
Sub8  Pointer:1-7=2
Add8  Pointer:1+8=1
Sub8  Pointer:1-8=1
Add8  Pointer:1+9=2
Sub8  Pointer:1-9=0
Add8  Pointer:1+10=3
Sub8  Pointer:1-10=7
Add8  Pointer:1+11=4
Sub8  Pointer:1-11=6
Add8  Pointer:1+12=5
Sub8  Pointer:1-12=5
Add8  Pointer:1+13=6
Sub8  Pointer:1-13=4
Add8  Pointer:1+14=7
Sub8  Pointer:1-14=3
Add8  Pointer:1+15=0
Sub8  Pointer:1-15=2
Add8  Pointer:1+16=1
Sub8  Pointer:1-16=1
Add8  Pointer:1+17=2
Sub8  Pointer:1-17=0
Add8  Pointer:1+18=3
Sub8  Pointer:1-18=7
Add8  Pointer:1+19=4
Sub8  Pointer:1-19=6
Add8  Pointer:2+0=2
Sub8  Pointer:20=2
Add8  Pointer:2+1=3
Sub8  Pointer:2-1=1
Add8  Pointer:2+2=4
Sub8  Pointer:2-2=0
Add8  Pointer:2+3=5
Sub8  Pointer:2-3=7
Add8  Pointer:2+4=6
Sub8  Pointer:2-4=6
Add8  Pointer:2+5=7
Sub8  Pointer:2-5=5
Add8  Pointer:2+6=0
Sub8  Pointer:2-6=4
Add8  Pointer:2+7=1
Sub8  Pointer:2-7=3
Add8  Pointer:2+8=2
Sub8  Pointer:2-8=2
Add8  Pointer:2+9=3
Sub8  Pointer:2-9=1
Add8  Pointer:2+10=4
Sub8  Pointer:2-10=0
Add8  Pointer:2+11=5
Sub8  Pointer:2-11=7
Add8  Pointer:2+12=6
Sub8  Pointer:2-12=6
Add8  Pointer:2+13=7
Sub8  Pointer:2-13=5
Add8  Pointer:2+14=0
Sub8  Pointer:2-14=4
Add8  Pointer:2+15=1
Sub8  Pointer:2-15=3
Add8  Pointer:2+16=2
Sub8  Pointer:2-16=2
Add8  Pointer:2+17=3
Sub8  Pointer:2-17=1
Add8  Pointer:2+18=4
Sub8  Pointer:2-18=0
Add8  Pointer:2+19=5
Sub8  Pointer:2-19=7
Add8  Pointer:3+0=3
Sub8  Pointer:30=3
Add8  Pointer:3+1=4
Sub8  Pointer:3-1=2
Add8  Pointer:3+2=5
Sub8  Pointer:3-2=1
Add8  Pointer:3+3=6
Sub8  Pointer:3-3=0
Add8  Pointer:3+4=7
Sub8  Pointer:3-4=7
Add8  Pointer:3+5=0
Sub8  Pointer:3-5=6
Add8  Pointer:3+6=1
Sub8  Pointer:3-6=5
Add8  Pointer:3+7=2
Sub8  Pointer:3-7=4
Add8  Pointer:3+8=3
Sub8  Pointer:3-8=3
Add8  Pointer:3+9=4
Sub8  Pointer:3-9=2
Add8  Pointer:3+10=5
Sub8  Pointer:3-10=1
Add8  Pointer:3+11=6
Sub8  Pointer:3-11=0
Add8  Pointer:3+12=7
Sub8  Pointer:3-12=7
Add8  Pointer:3+13=0
Sub8  Pointer:3-13=6
Add8  Pointer:3+14=1
Sub8  Pointer:3-14=5
Add8  Pointer:3+15=2
Sub8  Pointer:3-15=4
Add8  Pointer:3+16=3
Sub8  Pointer:3-16=3
Add8  Pointer:3+17=4
Sub8  Pointer:3-17=2
Add8  Pointer:3+18=5
Sub8  Pointer:3-18=1
Add8  Pointer:3+19=6
Sub8  Pointer:3-19=0
Add8  Pointer:4+0=4
Sub8  Pointer:40=4
Add8  Pointer:4+1=5
Sub8  Pointer:4-1=3
Add8  Pointer:4+2=6
Sub8  Pointer:4-2=2
Add8  Pointer:4+3=7
Sub8  Pointer:4-3=1
Add8  Pointer:4+4=0
Sub8  Pointer:4-4=0
Add8  Pointer:4+5=1
Sub8  Pointer:4-5=7
Add8  Pointer:4+6=2
Sub8  Pointer:4-6=6
Add8  Pointer:4+7=3
Sub8  Pointer:4-7=5
Add8  Pointer:4+8=4
Sub8  Pointer:4-8=4
Add8  Pointer:4+9=5
Sub8  Pointer:4-9=3
Add8  Pointer:4+10=6
Sub8  Pointer:4-10=2
Add8  Pointer:4+11=7
Sub8  Pointer:4-11=1
Add8  Pointer:4+12=0
Sub8  Pointer:4-12=0
Add8  Pointer:4+13=1
Sub8  Pointer:4-13=7
Add8  Pointer:4+14=2
Sub8  Pointer:4-14=6
Add8  Pointer:4+15=3
Sub8  Pointer:4-15=5
Add8  Pointer:4+16=4
Sub8  Pointer:4-16=4
Add8  Pointer:4+17=5
Sub8  Pointer:4-17=3
Add8  Pointer:4+18=6
Sub8  Pointer:4-18=2
Add8  Pointer:4+19=7
Sub8  Pointer:4-19=1
Add8  Pointer:5+0=5
Sub8  Pointer:50=5
Add8  Pointer:5+1=6
Sub8  Pointer:5-1=4
Add8  Pointer:5+2=7
Sub8  Pointer:5-2=3
Add8  Pointer:5+3=0
Sub8  Pointer:5-3=2
Add8  Pointer:5+4=1
Sub8  Pointer:5-4=1
Add8  Pointer:5+5=2
Sub8  Pointer:5-5=0
Add8  Pointer:5+6=3
Sub8  Pointer:5-6=7
Add8  Pointer:5+7=4
Sub8  Pointer:5-7=6
Add8  Pointer:5+8=5
Sub8  Pointer:5-8=5
Add8  Pointer:5+9=6
Sub8  Pointer:5-9=4
Add8  Pointer:5+10=7
Sub8  Pointer:5-10=3
Add8  Pointer:5+11=0
Sub8  Pointer:5-11=2
Add8  Pointer:5+12=1
Sub8  Pointer:5-12=1
Add8  Pointer:5+13=2
Sub8  Pointer:5-13=0
Add8  Pointer:5+14=3
Sub8  Pointer:5-14=7
Add8  Pointer:5+15=4
Sub8  Pointer:5-15=6
Add8  Pointer:5+16=5
Sub8  Pointer:5-16=5
Add8  Pointer:5+17=6
Sub8  Pointer:5-17=4
Add8  Pointer:5+18=7
Sub8  Pointer:5-18=3
Add8  Pointer:5+19=0
Sub8  Pointer:5-19=2
Add8  Pointer:6+0=6
Sub8  Pointer:60=6
Add8  Pointer:6+1=7
Sub8  Pointer:6-1=5
Add8  Pointer:6+2=0
Sub8  Pointer:6-2=4
Add8  Pointer:6+3=1
Sub8  Pointer:6-3=3
Add8  Pointer:6+4=2
Sub8  Pointer:6-4=2
Add8  Pointer:6+5=3
Sub8  Pointer:6-5=1
Add8  Pointer:6+6=4
Sub8  Pointer:6-6=0
Add8  Pointer:6+7=5
Sub8  Pointer:6-7=7
Add8  Pointer:6+8=6
Sub8  Pointer:6-8=6
Add8  Pointer:6+9=7
Sub8  Pointer:6-9=5
Add8  Pointer:6+10=0
Sub8  Pointer:6-10=4
Add8  Pointer:6+11=1
Sub8  Pointer:6-11=3
Add8  Pointer:6+12=2
Sub8  Pointer:6-12=2
Add8  Pointer:6+13=3
Sub8  Pointer:6-13=1
Add8  Pointer:6+14=4
Sub8  Pointer:6-14=0
Add8  Pointer:6+15=5
Sub8  Pointer:6-15=7
Add8  Pointer:6+16=6
Sub8  Pointer:6-16=6
Add8  Pointer:6+17=7
Sub8  Pointer:6-17=5
Add8  Pointer:6+18=0
Sub8  Pointer:6-18=4
Add8  Pointer:6+19=1
Sub8  Pointer:6-19=3
Enter "0" to quit:

Alright, if you can think of a better formula that adds or subtracts a pointer value in a circular buffer let me know.  

Newer posts → Home ← Older posts