// ---- Function generator (square, saw, triangle, sine) ---
// ---- DAC (resistor ladder) on port D, buttons on A2 - A5, frequency pot. A5
// ---- More about resistor ladder: https://en.wikipedia.org/wiki/Resistor_ladder
// ---- Indication LED on half of port B.
int func_state=0; // --- function indicator.
// --- Data for sine (generated by Excel, or AI).
byte sinTable[361]={100,102,104,106,107,109,111,113,114,116,118,120,121,123,125,126,128,130,131,133,135,136,138,140,141,143,144,146,147,149,150,152,153,155,156,158,159,161,162,163,165,166,167,169,170,171,172,174,175,176,177,178,179,180,181,182,183,184,185,186,187,188,189,190,190,191,192,193,193,194,194,195,196,196,197,197,198,198,198,199,199,199,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,200,199,199,199,198,198,198,197,197,196,196,195,194,194,193,193,192,191,190,190,189,188,187,186,185,184,183,182,181,180,179,178,177,176,175,174,172,171,170,169,167,166,165,163,162,161,159,158,156,155,153,152,150,149,147,146,144,143,141,140,138,136,135,133,131,130,128,126,125,123,121,120,118,116,114,113,111,109,107,106,104,102,100,99,97,95,94,92,90,88,87,85,83,81,80,78,76,75,73,71,70,68,66,65,63,61,60,58,57,55,54,52,50,49,48,46,45,43,42,40,39,38,36,35,34,32,31,30,29,27,26,25,24,23,22,21,20,19,18,17,16,15,14,13,12,11,11,10,9,8,8,7,7,6,5,5,4,4,3,3,3,2,2,2,1,1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,2,2,2,3,3,3,4,4,5,5,6,7,7,8,8,9,10,11,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,29,30,31,32,34,35,36,38,39,40,42,43,45,46,48,49,50,52,54,55,57,58,60,61,63,65,66,68,70,71,73,75,76,78,80,81,83,85,87,88,90,92,94,95,97,99,100};
void setup()
{
DDRB = B00001111; // - Set first 4 bites port B to output.
DDRD = B11111111; // - Set port D for output (resistor DAC).
DDRC = B00000000; // - Set port C for input.
PORTC = B00111100; // - Set PULL-UP on pin A2 - A5.
}
// --- wait function - read potentiometer analog value and retur value 0 - 400.
int wait ()
{
int avalue=analogRead(A0);
return (map(avalue,0,1023,0,400));
}
// --- function - Square generator - one period of pulse UP and DOWN.
void genSquare(int wait_time)
{
PORTD=255;
delay(wait_time);
PORTD=0;
delay(wait_time);
}
// --- function - Saw generator - raise value (output voltage) from 0 to 255.
void genSaw(int wait_time)
{
for (int step=0;step<255;step++)
{
PORTD=step;
delayMicroseconds(wait_time);
}
}
// --- function - Triangle generator - raise from 0-255 and fall from 255-0.
void genTriangle(int wait_time)
{
for (int step=0;step<255;step++)
{
PORTD=step;
delayMicroseconds(wait_time);
}
for (int step=255;step>0;step--)
{
PORTD=step;
delayMicroseconds(wait_time);
}
}
// --- function - Sine generator - read value from table and write to port D - make sine on output.
void genSine(int wait_time)
{
for (int step=0;step<=360;step++)
{
PORTD=sinTable[step];
delayMicroseconds(wait_time);
}
}
// --- function - reading buttons state and prepare for other procedure.
byte readButtons()
{
int bin_value = PINC; // - read raw value from port C
bin_value = ~bin_value; // - binary NEG (PULL-UP :) ).
bin_value = bin_value & B00111100; // - we need specific bits only.
bin_value = bin_value >> 2; // - and shift right (we have combinations 0,1,2,4,8 now).
return (bin_value);
}
// --- MAIN LOOP ---
void loop()
{
int buttons=readButtons(); // --- read all buttons
if (buttons) // --- was pressed?
{
delay(150); // --- debounce time
if (!func_state) // --- is NOT runnig?
{
func_state = buttons; // --- select function from buttons.
PORTB=buttons; // --- switch on control LED.
}
else // --- is running? Stop it.
{
func_state=0;
}
}
switch (func_state) // --- Which position was chosen?
{
case 0: // --- stoping - switch off control LEDs.
PORTB = 0;
break;
case 1:
genSquare(wait());
break;
case 2:
genSaw(wait());
break;
case 4:
genTriangle(wait());
break;
case 8:
genSine(wait());
break;
}
}