/* Programmable Signal Generator V2 - see http://www.technoblogy.com/show?26SM David Johnson-Davies - www.technoblogy.com - 21st October 2020 ATtiny85 @ 1 MHz (internal oscillator; BOD disabled) CC BY 4.0 Licensed under a Creative Commons Attribution 4.0 International license: http://creativecommons.org/licenses/by/4.0/ */ #include // Matrix keypad ******************************************************* const int Matrix = A2; const int nButtons = 12; const int SmallestGap = 40; int AnalogVals[] = {1023, 680, 640, 590, 547, 507, 464, 411, 351, 273, 180, 133, 0}; int Buttons[] = {-1, 11, 9, 6, 3, 0, 10, 8, 7, 5, 4, 2, 1}; // Returns the keypad character or -1 if no button pressed int ReadKeypad() { int val, lastval=0, count = 0; do { val = analogRead(Matrix); if (abs(val-lastval)<2) count++; else { lastval = val; count = 0; } } while (count < 3); val = val + SmallestGap/2; int i = 0; while (val < AnalogVals[i]) { i++; } return Buttons[i]; } // OLED I2C 128 x 32 monochrome display ********************************************** const int OLEDAddress = 0x3C; // Initialisation sequence for OLED module int const InitLen = 15; const unsigned char Init[InitLen] PROGMEM = { 0xA8, // Set multiplex 0x1F, // for 32 rows 0x8D, // Charge pump 0x14, 0x20, // Memory mode 0x01, // Vertical addressing 0xA1, // 0xA0/0xA1 flip horizontally 0xC8, // 0xC0/0xC8 flip vertically 0xDA, // Set comp ins 0x02, 0xD9, // Set pre charge 0xF1, 0xDB, // Set vcom deselect 0x40, 0xAF // Display on }; const int data = 0x40; const int single = 0x80; const int command = 0x00; void InitDisplay () { Wire.beginTransmission(OLEDAddress); Wire.write(command); for (uint8_t c=0; c=0; i--) { for (int j=1; j<3; j++) { if (((col0>>i & 0b11) == (3-j)) && ((col1>>i & 0b11) == j)) { col0R = col0R | 1<<((i*2)+j); col1L = col1L | 1<<((i*2)+3-j); } } } Wire.write(col0L); Wire.write(col0L>>8); Wire.write(col0R); Wire.write(col0R>>8); col0L = col1L; col0R = col1R; } col0 = col1; } if (Scale == 1) Wire.write(col0); else { Wire.write(col0L); Wire.write(col0L>>8); Wire.write(col0R); Wire.write(col0R>>8); } Wire.endTransmission(); } uint8_t DigitChar (unsigned int number, unsigned int divisor) { return (number/divisor) % 10; } // Display a 8-digit frequency starting at line, column void PlotFreq (long freq, int line, int column) { boolean dig = false; for (long d=10000000; d>0; d=d/10) { char c = freq/d % 10; if (c == 0 && !dig && d>1) c = Space; else dig = true; PlotChar(c, line, column); column = column + Scale; } } void PlotHz (int line, int column) { PlotChar(Hz, line, column); column = column + Scale; PlotChar(Hz+1, line, column); } // Set frequency ********************************************** const int OscAddress = 0x17; long Input; const long Mult = (long)2078 * 1024; int CalculateParameters (long target) { if (target < 1039) target = 1039; int oct = 0; while (target >= ((long)2078 * 1<>10 & 0x0F; long factor = (long)1<>8 & 0xFF); Wire.write(data & 0xFF); Wire.endTransmission(); } void SendSilence () { int cnf = 3; // Powered down Wire.beginTransmission(OscAddress); Wire.write(0); Wire.write(cnf); Wire.endTransmission(); } // Setup ********************************************** int Mode = 0; // 0 = enter frequency, 1 = generate output const int Star = 10; const int Hash = 11; void setup() { Wire.begin(); InitDisplay(); ClearDisplay(); SendSilence(); Input = 0; PlotFreq(Input, 0, 0); } void loop() { int key, parameters; // Wait for key do { key = ReadKeypad(); } while (key == -1); if (key <= 9 && Input < 9999999) { if (Mode) { PlotChar(Space, 0, 8*Scale); PlotChar(Space, 0, 9*Scale); Input = 0; Mode = 0; SendSilence(); } Input = Input*10 + key; } else if (key == Hash) { PlotChar(Space, 0, 8*Scale); PlotChar(Space, 0, 9*Scale); Input = 0; Mode = 0; SendSilence(); } else if (key == Star) { Mode = 1; parameters = CalculateParameters(Input); // Scale = 1; // PlotFreq(parameters & 0x3FF, 2, 0); // PlotFreq(parameters>>10, 2, 10); // Scale = 2; Input = GetFrequency(parameters); PlotHz(0, 8*Scale); SendFrequency(parameters); } PlotFreq(Input, 0, 0); // Wait for key up do { key = ReadKeypad(); } while (key != -1); }