creat1001

sig_gen.c

Jan 26th, 2021 (edited)
667
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 8.85 KB | None | 0 0
  1. /*
  2.     Simple AD9833 DDS based signal generator.
  3.  
  4.     Scott Beasley 2021
  5.  
  6.     Free for whatever.
  7.  
  8.     Parts:
  9.         MCU: STC15W404AS SSOP20
  10.         Max 7219 serial LED driver - 8 digit module
  11.         Keyes Rotary encoder module
  12.         Buck regulator set to 5v
  13.  
  14.     PlatformIO was used as the build system using the intel_mcs51 platform.
  15.     This uses SDCC as the C compiler. The STC chips have a built-in ISP
  16.     and only need a TTL serial connection to program them from the ISP tool
  17.     that PlatformIO uses (stcgal). No other ISP adaptor or programmer needed.
  18.  
  19.     No extra libraries are needed to compile it.  
  20. */
  21.  
  22. #include <stc12.h>
  23. #include <stdint.h>
  24. #include <stdio.h>
  25. #include <string.h>
  26.  
  27. #define SET_BIT(p,n) (p |= (1 << n))
  28. #define CLR_BIT(p,n) (p &= ~(1 << n))
  29.  
  30. // GPIO defines
  31. #define CLK_PIN P1_2
  32. #define DSPLY_DATA_PIN P1_6
  33. #define DSPLY_CSEL_PIN P1_5
  34. #define ENC_CLK_PIN P3_2
  35. #define ENC_DIR_PIN P3_3
  36. #define ENC_BUT_PIN P3_4
  37. #define FRQG_DATA P1_4
  38. #define FRQG_SYNC_PIN P1_7
  39.  
  40. #define LOW 0
  41. #define HIGH 1
  42.  
  43. // Prototype, prototype each and every day!
  44. void init (void);
  45. void delay_5us (int __data us);
  46. void set_7219_reg (int8_t reg, int8_t value);
  47. void lshift (int8_t val);
  48. void set_AD9833_reg (uint16_t dat);
  49. void AD9833_freq_set (long freq, uint16_t type, int running);
  50.  
  51. // Max7219 commands
  52. enum {  
  53.     REG_DECODE    = 0x09,  
  54.     REG_INTENSITY = 0x0A,
  55.     REG_SCANLIMIT = 0x0B,
  56.     REG_SHUTDOWN  = 0x0C,
  57.     REG_DISPTEST  = 0x0F
  58. };
  59.  
  60. // flag for encoder change int
  61. volatile uint8_t enc_changed = 0;
  62.  
  63. // INT0 handler function
  64. void exint0 (void) __interrupt 0
  65. {
  66.     enc_changed = 1;
  67. }
  68.  
  69. // Delay 5us'ish
  70. void delay_5us (int __data us)
  71. {
  72.     unsigned char __data i;
  73.     for (; us; us--)
  74.         for (i=13; i; i--)
  75.             __asm__ ("nop");
  76. }
  77.  
  78. void set_7219_reg (int8_t reg, int8_t value)  
  79. {
  80.     DSPLY_CSEL_PIN = 0;
  81.     lshift (reg);
  82.     lshift (value);
  83.     DSPLY_CSEL_PIN = 1;
  84. }
  85.  
  86. // Shift data left for LED display comm
  87. void lshift (int8_t val)
  88. {
  89.     int ndx;
  90.  
  91.     for (ndx = 0; ndx < 8; ndx++) {    
  92.         DSPLY_DATA_PIN = val & 0x80;
  93.  
  94.         CLK_PIN = 1;
  95.         delay_5us (2);
  96.         CLK_PIN = 0;
  97.         delay_5us (2);
  98.  
  99.         val = val << 1;
  100.     }
  101. }    
  102.  
  103. // Shift data left for AD9833 comm
  104. void set_AD9833_reg (uint16_t val)
  105. {
  106.     int ndx;
  107.  
  108.     CLK_PIN = LOW;
  109.     delay_5us (5);
  110.     CLK_PIN = HIGH;
  111.  
  112.     FRQG_SYNC_PIN = LOW;
  113.     delay_5us (2);
  114.     for (ndx = 0; ndx < 16; ndx++) {
  115.         FRQG_DATA = val & 0x8000;
  116.  
  117.         CLK_PIN = HIGH;
  118.         delay_5us (5);
  119.         CLK_PIN = LOW;
  120.         delay_5us (5);
  121.  
  122.         val = val << 1;
  123.     }
  124.  
  125.     FRQG_DATA = LOW;
  126.     CLK_PIN = HIGH;
  127.     FRQG_SYNC_PIN = HIGH;
  128. }
  129.  
  130. // Set the freq and wave type for the AD9833
  131. void AD9833_freq_set (long freq, uint16_t type, int running)
  132. {
  133.     unsigned long int freq_out = (freq * 268435456.0) / 25000000.0;
  134.  
  135.     // Type is the wave you want. The menu items line up on the DDS
  136.     // val for Sine and Tri, but not on Squre. This is agdusted below
  137.     if (type == 1) type = 40; // Type 1 = Square wave make 40 for DDS
  138.     set_AD9833_reg ((running == 0 ? 0x2000 | type : 0x2100));
  139.     set_AD9833_reg ((uint16_t)((freq_out & 0x3FFF) | 0x4000));
  140.     set_AD9833_reg ((uint16_t)(((freq_out & 0xFFFC000) >> 14) | 0x4000));
  141.     if (running == 1) {
  142.         set_AD9833_reg ((uint16_t)0xC000);
  143.         set_AD9833_reg (type);
  144.     }
  145. }
  146.  
  147. // Setup in the 'Duino world
  148. void init (void)
  149. {
  150.     int ndx;
  151.  
  152.     // Set INT0 up for the encoder
  153.     INT0 = 1;
  154.     IT0 = 1; // Set to "change"
  155.     EX0 = 1; // Enable INT0 interrupt
  156.     EA = 1;  
  157.  
  158.     // Set input pins to quasi-bidirectional
  159.     CLR_BIT (P3M0, 2);
  160.     CLR_BIT (P3M1, 2);
  161.     CLR_BIT (P3M0, 3);
  162.     CLR_BIT (P3M1, 3);
  163.     CLR_BIT (P3M0, 4);
  164.     CLR_BIT (P3M1, 4);    
  165.  
  166.     // Init the display
  167.     set_7219_reg (REG_SHUTDOWN, 0);
  168.     set_7219_reg (REG_INTENSITY, 0x02);
  169.     set_7219_reg (REG_SCANLIMIT, 7);
  170.     set_7219_reg (REG_DECODE, 0b11111100);
  171.  
  172.     // Populate the display at start
  173.     for (ndx = 1; ndx < 9; ndx++) {
  174.         set_7219_reg (ndx, 0);
  175.     }
  176.  
  177.     set_7219_reg (2, 0b00000001); // NOP
  178.     set_7219_reg (1, 0b01101101); // Sine wave
  179.     set_7219_reg (REG_SHUTDOWN, 1);  
  180.     set_AD9833_reg (0x100); // Reset the AD9833
  181. }
  182.  
  183. int main ( )
  184. {
  185.     int8_t freq[8];
  186.     uint8_t opt[8];
  187.     int ndx = 0, enc_clk_state = -1, last_clk_state = -1, is_running = 0;
  188.     long int out_freq = 0;
  189.  
  190.     // Set the freq array to all 0's
  191.     memset (&freq, 0, sizeof (int8_t) * 8);
  192.  
  193.     // Set the Power option
  194.     freq[6] = 4; // Start at NOP
  195.  
  196.     // Set the wave type
  197.     freq[7] = 0; // Start at Sine
  198.  
  199.     init ();
  200.  
  201.     // Non-numeric chars for digit 7 and 8
  202.     opt[0] = 0b01101101; // Sine wave
  203.     opt[1] = 0b01010011; // Square
  204.     opt[2] = 0b00110001; // Triangle
  205.     opt[3] = 0b01000000; // On
  206.     opt[4] = 0b00000001; // Nop
  207.     opt[5] = 0b00001000; // Off
  208.     opt[6] = 0b10000000; // One extra... Not used.    
  209.  
  210.     DSPLY_CSEL_PIN = 1;
  211.     // Set the first cursor pos for start up.
  212.     set_7219_reg (REG_SHUTDOWN, 0);
  213.     set_7219_reg (8 - ndx, freq[ndx] | 0x80);      
  214.     set_7219_reg (REG_SHUTDOWN, 1);
  215.  
  216.     while (1) {    
  217.         if (ENC_BUT_PIN == 0) {
  218.             delay_5us (12500); // Debounce delay
  219.             if (ENC_BUT_PIN == 0) {
  220.                 // If on digit 7, look for on/off options  
  221.                 if (ndx == 6) {
  222.                     switch (freq[ndx]) {
  223.                         case 3: // Turn on AD9833 (Top seg on)
  224.                             out_freq = (freq[0] * 100000);
  225.                             out_freq += (freq[1] * 10000);
  226.                             out_freq += (freq[2] * 1000);
  227.                             out_freq += (freq[3] * 100);
  228.                             out_freq += (freq[4] * 10);
  229.                             out_freq += freq[5];
  230.                             // Outside this compiler, this code is fine
  231.                             // If freq[1] > 3 then the out_freq cals is off
  232.                             // by 65,530.  Silly fix for a silly problem.
  233.                             if (freq[1] > 3)      
  234.                                 out_freq += 65530;
  235.                             AD9833_freq_set (out_freq, freq[7], is_running);
  236.                             is_running = 1;
  237.                             continue;                                    
  238.                      
  239.                         case 5: // Bottom seg on
  240.                             set_AD9833_reg (0x100); // Reset the AD9833
  241.                             is_running = 0;
  242.                             continue;    
  243.  
  244.                         case 4: // NOP (skip to next). Middle seg on
  245.                             break;  
  246.  
  247.                         default:
  248.                             continue;
  249.                     }  
  250.                 }
  251.  
  252.                 set_7219_reg (REG_SHUTDOWN, 0);
  253.                 set_7219_reg (8 - ndx, (ndx < 6 ? freq[ndx] : opt[freq[ndx]]));  
  254.                 set_7219_reg (REG_SHUTDOWN, 1);    
  255.                 ndx++;
  256.                 if (ndx >= 8)
  257.                     ndx = 0;
  258.             }
  259.  
  260.             set_7219_reg (REG_SHUTDOWN, 0);
  261.             set_7219_reg (8 - ndx, (ndx < 6 ? freq[ndx] : opt[freq[ndx]]) | 0x80);    
  262.             set_7219_reg (REG_SHUTDOWN, 1);
  263.             continue;            
  264.         }
  265.  
  266.         // Handle any encoder changes
  267.         if (enc_changed == 1) {
  268.             if ((ENC_DIR_PIN == 1 && ENC_CLK_PIN == 0) ||
  269.                 (ENC_DIR_PIN == 0 && ENC_CLK_PIN == 1))
  270.                 freq[ndx]--;
  271.             if ((ENC_DIR_PIN == 0 && ENC_CLK_PIN == 0) ||
  272.                 (ENC_DIR_PIN == 1 && ENC_CLK_PIN == 1))
  273.                 freq[ndx]++;
  274.  
  275.             // Edits for Freq numbers (0-9)
  276.             if (ndx < 6) {
  277.                 if (freq[ndx] > 9)
  278.                     freq[ndx] = 0;
  279.                 if (freq[ndx] < 0)
  280.                     freq[ndx] = 9;  
  281.             }
  282.  
  283.             // Edits for ON/OFF options
  284.             if (ndx == 6) {
  285.                 if (freq[ndx] == 6) {
  286.                     freq[ndx] = 3;
  287.                 }
  288.  
  289.                 if (freq[ndx] < 3) {
  290.                     freq[ndx] = 5;
  291.                 }                
  292.             }
  293.  
  294.             // Edits for Wave type
  295.             if (ndx == 7) {
  296.                 if (freq[ndx] == 3) {
  297.                     freq[ndx] = 0;
  298.                 }
  299.  
  300.                 if (freq[ndx] < 0) {
  301.                     freq[ndx] = 2;
  302.                 }                
  303.             }
  304.  
  305.             // Send the change to the display with the
  306.             // current digit with the '.' for the cursor
  307.             set_7219_reg (REG_SHUTDOWN, 0);
  308.             set_7219_reg (8 - ndx, (ndx < 6 ? freq[ndx] : opt[freq[ndx]]) | 0x80);
  309.             set_7219_reg (REG_SHUTDOWN, 1);  
  310.             delay_5us (14500);  // Debounce delay  
  311.             enc_changed = 0;    
  312.         }
  313.     }
  314. }
  315.  
Advertisement
Add Comment
Please, Sign In to add comment