Improved Phase Lock

master
Tony 2023-09-19 13:08:59 +01:00
rodzic 2f277b4448
commit 17c262526c
4 zmienionych plików z 207 dodań i 240 usunięć

Wyświetl plik

@ -31,6 +31,7 @@ void pio_DAC_program_init(PIO pio, uint sm, uint offset, uint start_pin) {
pio_sm_config c = pio_DAC_program_get_default_config(offset); // Define PIO Configuration structure pio_sm_config c = pio_DAC_program_get_default_config(offset); // Define PIO Configuration structure
sm_config_set_out_pins(&c, start_pin, 8); // Configure pins to be targeted by the OUT (and MOV) commands sm_config_set_out_pins(&c, start_pin, 8); // Configure pins to be targeted by the OUT (and MOV) commands
sm_config_set_out_shift(&c, true, true, 8); // Shift right, Autopull enabled, 6/8 bits sm_config_set_out_shift(&c, true, true, 8); // Shift right, Autopull enabled, 6/8 bits
sm_config_set_fifo_join(&c, PIO_FIFO_JOIN_TX); // Set TX_FIFO to 8. Improves stability at high frequencies
pio_sm_init(pio, sm, offset, &c); // Load configuration and jump to start of the program pio_sm_init(pio, sm, offset, &c); // Load configuration and jump to start of the program
pio_sm_set_enabled(pio, sm, true); pio_sm_set_enabled(pio, sm, true);
} }

Wyświetl plik

@ -1,3 +1,7 @@
// TBD: 1) SPI read connecton
// 2) Capacitors on op-amps
// 3) Issue with phase lock - red/writes to serial port affecting phase lock at high frequencies
#include <stdio.h> #include <stdio.h>
#include <string.h> #include <string.h>
#include <ctype.h> #include <ctype.h>
@ -9,7 +13,6 @@
#include "hardware/dma.h" #include "hardware/dma.h"
#include "blink.pio.h" #include "blink.pio.h"
#include "DAC.pio.h" #include "DAC.pio.h"
#include "hardware/gpio.h" // Required for manually toggling GPIO pins (clock) #include "hardware/gpio.h" // Required for manually toggling GPIO pins (clock)
////////////////////////////////////// //////////////////////////////////////
@ -53,17 +56,25 @@
//#define SysClock 250 // System clock x 2 for 0.977 MHz DAC output //#define SysClock 250 // System clock x 2 for 0.977 MHz DAC output
#define SysClock 280 // Overclock for 1.000 MHz DAC output #define SysClock 280 // Overclock for 1.000 MHz DAC output
// Data for clock face generated by Excel spreadsheet... // Data for the clock face is generated externally using an Excel spreadsheet...
uint8_t FaceX[] = {235,239,243,247,251,255,255,254,254,254,254,254,254,254,253,253,253,252,252,251,251,250,250,249,248,248,247,246,245,244,244,243,242,241,240,239,221,224,227,231,234,238,236,235,234,233,232,230,229,228,226,225,224,222,221,219,218,216,214,213,211,209,208,206,204,203,201,199,197,195,193,182,184,186,188,190,191,190,188,186,184,182,180,178,176,174,172,170,167,165,163,161,159,157,155,153,150,148,146,144,142,139,137,135,133,131,128,128,128,128,128,128,126,124,122,120,117,115,113,111,109,107,104,102,100,98,96,94,92,90,87,85,83,81,79,77,75,73,71,69,67,75,73,71,69,67,65,64,62,60,58,56,54,53,51,49,47,46,44,43,41,39,38,36,35,33,32,31,29,28,27,25,24,23,22,20,36,33,30,26,23,19,18,17,16,15,14,13,12,12,11,10,9,9,8,7,7,6,6,5,5,4,4,4,3,3,3,3,3,3,2,22,18,14,10,6,2,2,3,3,3,3,3,3,4,4,4,5,5,6,6,7,7,8,9,9,10,11,12,12,13,14,15,16,17,18,36,33,30,26,23,19,20,22,23,24,25,27,28,29,31,32,33,35,36,38,39,41,43,44,46,47,49,51,53,54,56,58,60,62,64,75,73,71,69,67,65,67,69,71,73,75,77,79,81,83,85,87,90,92,94,96,98,100,102, uint8_t FaceX[] = {
104,107,109,111,113,115,117,120,122,124,126,128,128,128,128,128,128,131,133,135,137,139,142,144,146,148,150,153,155,157,159,161,163,165,167,170,172,174,176,178,180,182,184,186,188,190,182,184,186,188,190,191,193,195,197,199,201,203,204,206,208,209,211,213,214,216,218,219,221,222,224,225,226,228,229,230,232,233,234,235,236,221,224,227,231,234,238,239,240,241,242,243,244,244,245,246,247,248,248,249,250,250,251,251,252,252,253,253,253,254,254,254,254,254,254,254} ; 0xfa,0xfb,0xfc,0xfd,0xfe,0xff,0xff,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfd,0xfd,0xfd,0xfc,0xfc,0xfb,0xfb,0xfa,0xfa,0xf9,0xf8,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf3,0xf2,0xf1,0xf0,0xef,0xe9,0xea,0xeb,0xec,0xed,0xed,0xec,0xeb,0xea,0xe9,0xe7,0xe6,0xe5,0xe3,0xe2,0xe1,0xdf,0xde,0xdc,0xdb,0xd9,0xd8,0xd6,0xd4,0xd3,0xd1,0xcf,0xcd,0xcc,0xca,0xc8,0xc6,0xc4,0xc3,0xc1,0xbc,0xbd,0xbd,0xbe,0xbe,0xbf,0xbd,0xbb,0xb9,0xb7,0xb5,0xb3,0xb1,0xaf,0xad,0xab,0xa9,0xa6,0xa4,0xa2,0xa0,0x9e,0x9c,0x9a,0x97,0x95,0x93,0x91,0x8f,0x8c,0x8a,0x88,0x86,0x83,0x81,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7d,0x7b,0x78,0x76,0x74,0x72,0x6f,0x6d,0x6b,0x69,0x67,0x64,0x62,0x60,0x5e,0x5c,0x5a,0x58,0x55,0x53,0x51,0x4f,0x4d,0x4b,0x49,0x47,0x45,0x43,0x41,0x42,0x41,0x41,0x40,0x40,0x3f,0x3d,0x3b,0x3a,0x38,0x36,0x34,0x32,0x31,0x2f,0x2d,0x2b,0x2a,0x28,0x26,0x25,0x23,0x22,0x20,0x1f,0x1d,0x1c,0x1b,0x19,0x18,0x17,0x15,0x14,0x13,0x12,0x15,0x14,0x13,0x12,0x11,0x11,0x0f,0x0e,0x0d,0x0c,0x0b,0x0b,0x0a,0x09,0x08,0x07,0x06,0x06,0x05,0x04,0x04,0x03,0x03,0x02,
uint8_t FaceY[] = {128,128,128,128,128,128,128,126,124,122,120,117,115,113,111,109,107,104,102,100,98,96,94,92,90,87,85,83,81,79,77,75,73,71,69,67,75,73,71,69,67,65,64,62,60,58,56,54,53,51,49,47,46,44,43,41,39,38,36,35,33,32,31,29,28,27,25,24,23,22,20,36,33,30,26,23,19,18,17,16,15,14,13,12,12,11,10,9,9,8,7,7,6,6,5,5,4,4,4,3,3,3,3,3,3,2,22,18,14,10,6,2,2,3,3,3,3,3,3,4,4,4,5,5,6,6,7,7,8,9,9,10,11,12,12,13,14,15,16,17,18,36,33,30,26,23,19,20,22,23,24,25,27,28,29,31,32,33,35,36,38,39,41,43,44,46,47,49,51,53,54,56,58,60,62,64,75,73,71,69,67,65,67,69,71,73,75,77,79,81,83,85,87,90,92,94,96,98,100,102,104,107,109,111,113,115,117,120,122,124,126,128,128,128,128,128,128,131,133,135,137,139,142,144,146,148,150,153,155,157,159,161,163,165,167,170,172,174,176,178,180,182,184,186,188,190,182,184,186,188,190,191,193,195,197,199,201,203,204,206,208,209,211,213,214,216,218,219,221,222,224,225,226,228,229,230,232,233,234,235,236,221,224,227,231,234,238,239,240,241,242,243,244,244,245,246,247,248,248,249,250,250,251,251,252, 0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x04,0x03,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x15,0x14,0x13,0x12,0x11,0x11,0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1b,0x1c,0x1d,0x1f,0x20,0x22,0x23,0x25,0x26,0x28,0x2a,0x2b,0x2d,0x2f,0x31,0x32,0x34,0x36,0x38,0x3a,0x3b,0x3d,0x42,0x41,0x41,0x40,0x40,0x3f,0x41,0x43,0x45,0x47,0x49,0x4b,0x4d,0x4f,0x51,0x53,0x55,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,0x67,0x69,0x6b,0x6d,0x6f,0x72,0x74,0x76,0x78,0x7b,0x7d,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x81,0x83,0x86,0x88,0x8a,0x8c,0x8f,0x91,0x93,0x95,0x97,0x9a,0x9c,0x9e,0xa0,0xa2,0xa4,0xa6,0xa9,0xab,0xad,0xaf,0xb1,0xb3,0xb5,0xb7,0xb9,0xbb,0xbd,0xbc,0xbd,0xbd,0xbe,0xbe,0xbf,0xc1,0xc3,0xc4,0xc6,0xc8,0xca,0xcc,0xcd,0xcf,0xd1,0xd3,0xd4,0xd6,0xd8,0xd9,0xdb,0xdc,0xde,0xdf,0xe1,0xe2,0xe3,0xe5,0xe6,0xe7,0xe9,0xea,0xeb,0xec,0xe9,0xea,0xeb,0xec,0xed,0xed,0xef,0xf0,0xf1,0xf2,0xf3,0xf3,0xf4,0xf5,
252,253,253,253,254,254,254,254,254,254,254,235,239,243,247,251,255,254,254,254,254,254,254,254,253,253,253,252,252,251,251,250,250,249,248,248,247,246,245,244,244,243,242,241,240,239,221,224,227,231,234,238,236,235,234,233,232,230,229,228,226,225,224,222,221,219,218,216,214,213,211,209,208,206,204,203,201,199,197,195,193,182,184,186,188,190,191,190,188,186,184,182,180,178,176,174,172,170,167,165,163,161,159,157,155,153,150,148,146,144,142,139,137,135,133,131} ; 0xf6,0xf7,0xf8,0xf8,0xf9,0xfa,0xfa,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x4c,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1c,0x1c,0x1c,0x1c,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x28,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x18,0x17,0x16,0x15,0x14,0x13,0x12,0x11,0x10,0x0f,0x0e,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x0e,0x0d,0x0c,0x0c,0x0c,0x0c,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x27,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x1e,0x26,0x25,0x24,0x23,0x22,0x21,0x20,0x1f,0x1e,0x1d,0x1c,0x1b,0x52,0x51,0x50,0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x46,0x46,0x46,0x46,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x50,0x51,
// (Number of pixels: 421) 0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x52,0x51,0x50,0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x83,0x82,0x81,0x80,0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x77,0x77,0x77,0x77,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x82,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb6,0xb5,0xb4,0xb3,0xb2,0xb1,0xb0,0xaf,0xaf,0xaf,0xaf,0xaf,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xe0,0xe1,0xe2,0xe3,0xe3,0xe3,0xe3,0xe3,0xe3,0xe2,0xe1,0xe0,0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd7,0xd7,0xd7,0xd7,0xd7,0xd8,0xd9,0xda,0xdb,0xdc,0xdd,0xde,0xdf,0xe1,0xe2,0xe3,0xe3,0xe3,0xe3,0xe2,0xe1,0xe0,0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd7,0xd7,0xd7,0xd8,0xd9,0xf0,0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,
0xeb,0xec,0xed,0xee,0xef,0xf0,0xf0,0xf0,0xf0,0xf0,0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe5,0xe4,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xe2,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd0,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xcf,0xd0,0xd1,0xd2,0xd3,0xd4,0xd5,0xd6,0xd7,0xd8,0xd9,0xda,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xb5,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x86,0x81,0x80,0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,0x75,0x75,0x75,0x75,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x81,0x80,0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x75,} ;
uint8_t FaceY[] = {
0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7d,0x7b,0x78,0x76,0x74,0x72,0x6f,0x6d,0x6b,0x69,0x67,0x64,0x62,0x60,0x5e,0x5c,0x5a,0x58,0x55,0x53,0x51,0x4f,0x4d,0x4b,0x49,0x47,0x45,0x43,0x41,0x42,0x41,0x41,0x40,0x40,0x3f,0x3d,0x3b,0x3a,0x38,0x36,0x34,0x32,0x31,0x2f,0x2d,0x2b,0x2a,0x28,0x26,0x25,0x23,0x22,0x20,0x1f,0x1d,0x1c,0x1b,0x19,0x18,0x17,0x15,0x14,0x13,0x12,0x15,0x14,0x13,0x12,0x11,0x11,0x0f,0x0e,0x0d,0x0c,0x0b,0x0b,0x0a,0x09,0x08,0x07,0x06,0x06,0x05,0x04,0x04,0x03,0x03,0x02,0x02,0x01,0x01,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x05,0x04,0x03,0x02,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x01,0x02,0x02,0x03,0x03,0x04,0x04,0x05,0x06,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x15,0x14,0x13,0x12,0x11,0x11,0x12,0x13,0x14,0x15,0x17,0x18,0x19,0x1b,0x1c,0x1d,0x1f,0x20,0x22,0x23,0x25,0x26,0x28,0x2a,0x2b,0x2d,0x2f,0x31,0x32,0x34,0x36,0x38,0x3a,0x3b,0x3d,0x42,0x41,0x41,0x40,0x40,0x3f,0x41,0x43,0x45,0x47,0x49,0x4b,0x4d,0x4f,0x51,0x53,0x55,0x58,0x5a,0x5c,0x5e,0x60,0x62,0x64,
0x67,0x69,0x6b,0x6d,0x6f,0x72,0x74,0x76,0x78,0x7b,0x7d,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x81,0x83,0x86,0x88,0x8a,0x8c,0x8f,0x91,0x93,0x95,0x97,0x9a,0x9c,0x9e,0xa0,0xa2,0xa4,0xa6,0xa9,0xab,0xad,0xaf,0xb1,0xb3,0xb5,0xb7,0xb9,0xbb,0xbd,0xbc,0xbd,0xbd,0xbe,0xbe,0xbf,0xc1,0xc3,0xc4,0xc6,0xc8,0xca,0xcc,0xcd,0xcf,0xd1,0xd3,0xd4,0xd6,0xd8,0xd9,0xdb,0xdc,0xde,0xdf,0xe1,0xe2,0xe3,0xe5,0xe6,0xe7,0xe9,0xea,0xeb,0xec,0xe9,0xea,0xeb,0xec,0xed,0xed,0xef,0xf0,0xf1,0xf2,0xf3,0xf3,0xf4,0xf5,0xf6,0xf7,0xf8,0xf8,0xf9,0xfa,0xfa,0xfb,0xfb,0xfc,0xfc,0xfd,0xfd,0xfd,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfa,0xfb,0xfc,0xfd,0xfe,0xff,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfe,0xfd,0xfd,0xfd,0xfc,0xfc,0xfb,0xfb,0xfa,0xfa,0xf9,0xf8,0xf8,0xf7,0xf6,0xf5,0xf4,0xf3,0xf3,0xf2,0xf1,0xf0,0xef,0xe9,0xea,0xeb,0xec,0xed,0xed,0xec,0xeb,0xea,0xe9,0xe7,0xe6,0xe5,0xe3,0xe2,0xe1,0xdf,0xde,0xdc,0xdb,0xd9,0xd8,0xd6,0xd4,0xd3,0xd1,0xcf,0xcd,0xcc,0xca,0xc8,0xc6,0xc4,0xc3,0xc1,0xbc,0xbd,0xbd,0xbe,0xbe,0xbf,0xbd,0xbb,0xb9,0xb7,0xb5,0xb3,0xb1,0xaf,
0xad,0xab,0xa9,0xa6,0xa4,0xa2,0xa0,0x9e,0x9c,0x9a,0x97,0x95,0x93,0x91,0x8f,0x8c,0x8a,0x88,0x86,0x83,0x81,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x3e,0x3d,0x3c,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x78,0x77,0x76,0x75,0x75,0x75,0x75,0x75,0x75,0x75,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x7f,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x89,0x89,0x89,0x89,0x89,0x89,0x89,0x88,0x87,0x86,0xb3,0xb2,0xb1,0xb0,0xaf,0xae,0xad,0xac,0xab,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xe2,0xe3,0xe4,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,0xda,
0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xe0,0xdf,0xde,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xdd,0xde,0xdf,0xe0,0xe1,0xe2,0xe3,0xe4,0xe5,0xe6,0xe7,0xe8,0xe9,0xea,0xeb,0xec,0xed,0xee,0xef,0xf0,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf1,0xf0,0xef,0xee,0xed,0xec,0xeb,0xea,0xe9,0xe8,0xe7,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe6,0xe7,0xe8,0xe5,0xe4,0xe3,0xe2,0xe1,0xe0,0xdf,0xde,0xdd,0xdc,0xdb,0xda,0xd9,0xd8,0xd7,0xd6,0xd5,0xd4,0xd3,0xd2,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xd1,0xb3,0xb4,0xb5,0xb6,0xb7,0xb8,0xb9,0xba,0xbb,0xbc,0xbd,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbe,0xbd,0xbc,0xbb,0xba,0xb9,0xb8,0xb7,0xb6,0xb5,0xb4,0xb3,0xb3,0xb3,0xb3,0xb3,0xb3,0xb2,0xb1,0xb0,0xaf,0xae,0xad,0xac,0xab,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xaa,0xab,0xac,0xad,0xae,0xaf,0xb0,0xb1,0xb2,0x87,0x88,0x89,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x8a,0x89,0x88,0x87,0x86,0x85,0x84,0x83,0x82,0x81,0x80,0x7f,0x7e,0x7d,0x7c,0x7b,0x7a,0x79,0x78,0x77,0x76,0x76,0x76,0x76,
0x76,0x76,0x76,0x77,0x78,0x79,0x7a,0x7b,0x7c,0x7d,0x7e,0x7f,0x80,0x80,0x80,0x80,0x80,0x80,0x80,0x7f,0x7e,0x7d,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f,0x4d,0x4e,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4f,0x4e,0x4d,0x4c,0x4b,0x4a,0x49,0x48,0x47,0x46,0x45,0x44,0x43,0x42,0x41,0x40,0x3f,0x3e,0x3d,0x3c,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3b,0x3c,0x3d,0x3e,0x3f,0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x20,0x21,0x22,0x23,0x24,0x25,0x26,0x27,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x0e,0x0d,0x0c,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0b,0x0c,0x0d,0x0e,0x0f,0x10,0x11,0x12,0x13,0x14,0x15,0x16,0x17,0x18,0x19,0x1a,0x1b,0x1c,0x1d,0x1e,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,0x1f,} ;
// (Number of pixels: 1000)
// Store clock hands co-ordinates... // Store clock hands co-ordinates...
uint8_t HandsX[192] = {} ; // Each hand requires 64 bytes - 3x64=192 uint8_t HandsX[192] = {} ; // Each hand requires 64 bytes - 3x64=192
uint8_t HandsY[192] = {} ; uint8_t HandsY[192] = {} ;
int Hours=0, Mins=0, Secs=0, Angle, StartX, StartY, Radius ; int Hours=0, Mins=0, Secs=0, LEDCtr=0, Angle, StartX, StartY, Radius ;
float Radians ; float Radians ;
int tmp ; int tmp ;
@ -129,32 +140,14 @@ public:
MarginCount = 0 ; MarginCount = 0 ;
} }
// Setter functions...
void ReInit () {
// Re-initialises DMA channels to their initial state.
// Note: 1) DMA channels are not restarted, allowing for atomic (simultaneous) restart of both DAC channels later.
// 2) Cannot use dma_hw->abort on chained DMA channels, so using disable and re-enable instead.
// 3) This needs to be performed across both DAC channels to ensure phase sync is maintained.
// Disable both DMA channels associated with this DAC...
hw_clear_bits(&dma_hw->ch[data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_clear_bits(&dma_hw->ch[ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
// Reset the data transfer DMA's to the start of the data Bitmap...
dma_channel_set_read_addr(data_chan, &DAC_data[0], false);
// Re-enable both DMA channels associated with this DAC...
hw_set_bits(&dma_hw->ch[data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_set_bits(&dma_hw->ch[ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
}
int Set(int _type, int _val) { int Set(int _type, int _val) {
switch (_type) { switch (_type) {
case _Freq_: case _Freq_:
Freq = _val ; // Frequency (numeric) Freq = _val ; // Frequency (numeric)
ReInit() ; // Stop and reset the DAC channel (no restart)
DACspeed(Freq * Range) ; // Update State machine run speed DACspeed(Freq * Range) ; // Update State machine run speed
break ; break ;
case _Phase_: case _Phase_:
Phase = _val ; // Phase shift (0->355 degrees) Phase = _val ; // Phase shift (0->355 degrees)
ReInit() ; // Stop and reset the DAC channel (no restart)
DataCalc() ; // Recalc Bitmap and apply new phase value DataCalc() ; // Recalc Bitmap and apply new phase value
break ; break ;
case _Level_: case _Level_:
@ -194,7 +187,7 @@ public:
strcpy(ResultStr,MarginVW) ; strcpy(ResultStr,MarginVW) ;
strcat(ResultStr,"Error - Minimum Frequency\n") ; strcat(ResultStr,"Error - Minimum Frequency\n") ;
} }
// TBD - remove hardcoded Max frequency // TBD - remove hardcoded Max frequency
else if ((Freq*Range==1000000) && (_dirn==_Up)) { // Attempt to bump above upper limit else if ((Freq*Range==1000000) && (_dirn==_Up)) { // Attempt to bump above upper limit
// else if ((Freq*Range>=MaxDACfreq) && (_dirn==_Up)) { // Attempt to bump above upper limit // else if ((Freq*Range>=MaxDACfreq) && (_dirn==_Up)) { // Attempt to bump above upper limit
MarginVW[MWidth - MarginCount] = '\0' ; // Calculate padding required for command characters and cursor MarginVW[MWidth - MarginCount] = '\0' ; // Calculate padding required for command characters and cursor
@ -260,9 +253,9 @@ public:
if (_frequency >= 34) { // Fast DAC ( Frequency range from 34Hz to 999Khz ) if (_frequency >= 34) { // Fast DAC ( Frequency range from 34Hz to 999Khz )
SM_WrapTop = SM_WrapBot ; // SM program memory = 1 op-code SM_WrapTop = SM_WrapBot ; // SM program memory = 1 op-code
pio_sm_set_wrap (pio, StateMachine, SM_WrapBot, SM_WrapTop) ; // Fast loop (1 clock cycle) pio_sm_set_wrap (pio, StateMachine, SM_WrapBot, SM_WrapTop) ; // Fast loop (1 clock cycle)
// If the previous frequency was < 33Hz, we will have just shrunk the assembler from 4 op-codes down to 1. // If the previous frequency was < 33Hz, we will have just shrunk the assembler from 4 op-codes down to 1.
// This leaves the State Machine program counter pointing outside of the new WRAP statement, which crashes the SM. // This leaves the State Machine program counter pointing outside of the new WRAP statement, which crashes the SM.
// To avoid this, we need to also reset the State Machine program counter... // To avoid this, we need to also reset the State Machine program counter...
pio->sm[StateMachine].instr = SM_WrapBot ; // Reset State Machine PC to start of code pio->sm[StateMachine].instr = SM_WrapBot ; // Reset State Machine PC to start of code
pio_sm_set_clkdiv(pio, StateMachine, DAC_div); // Set the State Machine clock pio_sm_set_clkdiv(pio, StateMachine, DAC_div); // Set the State Machine clock
} else { // Slow DAC ( 1Hz=>33Hz ) } else { // Slow DAC ( 1Hz=>33Hz )
@ -270,8 +263,8 @@ public:
DAC_freq = DAC_freq * 64; DAC_freq = DAC_freq * 64;
SM_WrapTop = SM_WrapBot + 3 ; // SM program memory = 4 op-codes SM_WrapTop = SM_WrapBot + 3 ; // SM program memory = 4 op-codes
pio_sm_set_wrap (pio, StateMachine, SM_WrapBot, SM_WrapTop) ; // slow loop (64 clock cycles) pio_sm_set_wrap (pio, StateMachine, SM_WrapBot, SM_WrapTop) ; // slow loop (64 clock cycles)
// If the previous frequency was >= 34Hz, we will have just expanded the assembler code from 1 op-code up to 4. // If the previous frequency was >= 34Hz, we will have just expanded the assembler code from 1 op-code up to 4.
// The State Machine program counter will still be pointing to an op-code within the new WRAP statement, so will not crash. // The State Machine program counter will still be pointing to an op-code within the new WRAP statement, so will not crash.
pio_sm_set_clkdiv(pio, StateMachine, DAC_div); // Set the State Machine clock speed pio_sm_set_clkdiv(pio, StateMachine, DAC_div); // Set the State Machine clock speed
} }
StatusString () ; // Update the terminal session StatusString () ; // Update the terminal session
@ -282,7 +275,7 @@ public:
int _phase; int _phase;
float a,b,x1,x2,g1,g2; float a,b,x1,x2,g1,g2;
// Scale the phase shift to match data size... // Scale the phase shift to match data size...
_phase = Phase * BitMapSize / 360 ; // Input range: 0 -> 360 (degrees) _phase = Phase * BitMapSize / 360 ; // Input range: 0 -> 360 (degrees)
// Output range: 0 -> 255 (bytes) // Output range: 0 -> 255 (bytes)
switch (Funct) { switch (Funct) {
@ -398,69 +391,58 @@ public:
} }
}; };
class blink_forever { // Class to initialise a state machine to blink a GPIO pin
PIO pio ; // Class wide variables to share value with setter function
public:
uint pioNum, StateMachine, Freq, _offset ;
blink_forever(PIO _pio) {
pio = _pio; // transfer parameter to class wide var
pioNum = pio_get_index(_pio);
StateMachine = pio_claim_unused_sm(_pio, true); // Find a free state machine on the specified PIO - error if there are none.
_offset = pio_add_program(_pio, &pio_blink_program);
blink_program_init(_pio, StateMachine, _offset, PICO_DEFAULT_LED_PIN );
pio_sm_set_enabled(_pio, StateMachine, true);
}
// Setter function...
void Set_Frequency(int _frequency){
Freq = _frequency; // Copy parm to class var
// Frequency scaled by 2000 as blink.pio requires this number of cycles to complete...
float DAC_div = (float)clock_get_hz(clk_sys) /((float)_frequency*2000);
pio_sm_set_clkdiv(pio, StateMachine, DAC_div); // Set the State Machine clock speed
}
};
bool Repeating_Timer_Callback(struct repeating_timer *t) { bool Repeating_Timer_Callback(struct repeating_timer *t) {
// Routine called 5 times per second...
int i, steps=64, MidX=128, MidY=128 ; int i, steps=64, MidX=128, MidY=128 ;
// Bump the time... // printf("%d\n",LEDCtr) ; // Debug
if ((++Secs)>59) Secs=0 ; // Always bump seconds LEDCtr -- ;
if (Secs==0) { if ((++Mins)>59 ) Mins=0 ; } // Bump minutes when seconds = 0 if (LEDCtr>0) {
if ((Mins==0) && (Secs==0)) { if ((++Hours)>24) Hours=0 ; } // Bump hours when minutes and seconds = 0 // LED off, and no change to the time for 4 out of 5 cycles...
gpio_put(PICO_DEFAULT_LED_PIN, 0); // LED is connected to PICO_DEFAULT_LED_PIN
} else {
// Falls through here once per second.
LEDCtr = 5 ;
gpio_put(PICO_DEFAULT_LED_PIN, 1); // LED is connected to PICO_DEFAULT_LED_PIN
// Calculate seconds hand... // Bump the clock...
i=0, Radius=127 ; // Radius=Length of seconds hand if ((++Secs)>59) Secs=0 ; // Always bump seconds
Angle=270-(Secs*6) ; // Angle in degrees, shifted 90 degree anti-clockwise if (Secs==0) { if ((++Mins)>59 ) Mins=0 ; } // Bump minutes when seconds = 0
Radians=Angle*3.14159/180 ; // Angle in radians if ((Mins==0) && (Secs==0)) { if ((++Hours)>24) Hours=0 ; } // Bump hours when minutes and seconds = 0
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
while(i<steps) { HandsX[i]=StartX+i*(MidX-StartX)/steps ;
HandsY[i]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// Calculate minutes hand...
i=0, Radius=95 ; // Radius=Length of minutes hand
Angle=270-(Mins*6) ; // Angle in degrees, shifted 90 degree anti-clockwise
Radians=Angle*3.14159/180 ; // Angle in radians
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
i=0 ;
while(i<steps) { HandsX[i+steps]=StartX+i*(MidX-StartX)/steps ;
HandsY[i+steps]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// Calculate hours hand...
i=0, Radius=64 ; // Radius=Length of hours hand
// Note: Hours hand progresses between hours in 5 partial increments, each measuring 12 minutes.
// Each 12 minute increment adds an additional 6 degrees of rotation to the hours hand.
Angle=5*(270-(((Hours%12)*6)+(Mins/12)%5)) ; // Angle in degrees, shifted 90 degree anti-clockwise,
// and scaled by 5 to provide range 0=>12
Radians=Angle*3.14159/180 ; // Angle in radians
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
while(i<steps) { HandsX[i+2*steps]=StartX+i*(MidX-StartX)/steps ;
HandsY[i+2*steps]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// printf("%s%d:%d:%d - %d\n",MarginFW,Hours,Mins,Secs,tmp) ; // Debug // Calculate seconds hand...
i=0, Radius=127 ; // Radius=Length of seconds hand
Angle=270-(Secs*6) ; // Angle in degrees, shifted 90 degree anti-clockwise
Radians=Angle*3.14159/180 ; // Angle in radians
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
while(i<steps) { HandsX[i]=StartX+i*(MidX-StartX)/steps ;
HandsY[i]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// Calculate minutes hand...
i=0, Radius=95 ; // Radius=Length of minutes hand
Angle=270-(Mins*6) ; // Angle in degrees, shifted 90 degree anti-clockwise
Radians=Angle*3.14159/180 ; // Angle in radians
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
i=0 ;
while(i<steps) { HandsX[i+steps]=StartX+i*(MidX-StartX)/steps ;
HandsY[i+steps]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// Calculate hours hand...
i=0, Radius=64 ; // Radius=Length of hours hand
// Note: Hours hand progresses between hours in 5 partial increments, each increment measuring 12 minutes.
// Each 12 minute increment adds an additional 6 degrees of rotation to the hours hand.
Angle=5*(270-(((Hours%12)*6)+(Mins/12)%5)) ; // Angle in degrees, shifted 90 degree anti-clockwise,
// and scaled by 5 to provide range 0=>12
Radians=Angle*3.14159/180 ; // Angle in radians
StartX=Radius*cos(Radians)+MidX ;
StartY=Radius*sin(Radians)+MidY ;
while(i<steps) { HandsX[i+2*steps]=StartX+i*(MidX-StartX)/steps ;
HandsY[i+2*steps]=StartY+i*(MidY-StartY)/steps ;
i++ ; }
// printf("%s%d:%d:%d - %d\n",MarginFW,Hours,Mins,Secs,tmp) ; // Debug
}
return true; return true;
} }
@ -469,11 +451,11 @@ void VerText () {
tmp = strlen(inStr) ; // Get number of command line characters tmp = strlen(inStr) ; // Get number of command line characters
if (tmp != 0) tmp ++ ; // If there are characters, Bump to also allow for cursor if (tmp != 0) tmp ++ ; // If there are characters, Bump to also allow for cursor
MarginVW[MWidth - tmp] = '\0' ; // Calculate padding required for command characters and cursor MarginVW[MWidth - tmp] = '\0' ; // Calculate padding required for command characters and cursor
sprintf(ResultStr, "%s|--------------------|\n" sprintf(ResultStr, "%s|---------------------|\n"
"%s| Function Generator |\n" "%s| Function Generator |\n"
"%s| Version 1.0.0 |\n" "%s| Version 1.0.0 |\n"
"%s| 11th August 2023 |\n" "%s| 19th September 2023 |\n"
"%s|--------------------|\n", "%s|---------------------|\n",
MarginVW, MarginFW, MarginFW, MarginFW, MarginFW ) ; MarginVW, MarginFW, MarginFW, MarginFW, MarginFW ) ;
} }
@ -512,16 +494,18 @@ void HlpText () {
"%s<A/B/C>lennn - Level = nnn ( 0->100%%%% )\n" "%s<A/B/C>lennn - Level = nnn ( 0->100%%%% )\n"
"%s<A/B/C>le+ - Level + 1\n" "%s<A/B/C>le+ - Level + 1\n"
"%s<A/B/C>le- - Level - 1\n" "%s<A/B/C>le- - Level - 1\n"
"%s<A/B/C>ti - Time mode (display analog clock)\n"
"%swhere...\n" "%swhere...\n"
"%s<A/B/C> = DAC channel A,B or Both\n" "%s<A/B/C> = DAC channel A,B or C=both\n"
"%snnn = Three digit numeric value\n", "%snnn = Three digit numeric value\n",
MarginVW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginVW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW,
MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW,
MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW,
MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW ) ; MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW,
MarginFW ) ;
} }
void SysInfo (DAC DACobj[], blink_forever LED_blinky) { void SysInfo (DAC DACobj[] ) {
// Print System Info and resource allocation detils, aligned to current margin settings... // Print System Info and resource allocation detils, aligned to current margin settings...
// Note: 1) The following string requires '%%%%' to print '%' because... // Note: 1) The following string requires '%%%%' to print '%' because...
// a) ResultStr is copied to outStr using sprintf - this reduces '%%%%' to '%%' // a) ResultStr is copied to outStr using sprintf - this reduces '%%%%' to '%%'
@ -534,15 +518,9 @@ void SysInfo (DAC DACobj[], blink_forever LED_blinky) {
sprintf(ResultStr,"%s|----------------------------------------------------------|\n" sprintf(ResultStr,"%s|----------------------------------------------------------|\n"
"%s| System Info... |\n" "%s| System Info... |\n"
"%s|----------------------------------------------------------|\n" "%s|----------------------------------------------------------|\n"
"%s| Target board: Pico |\n"
"%s| RP2040 clock frequency: %7.3fMHz |\n" "%s| RP2040 clock frequency: %7.3fMHz |\n"
"%s| Max DAC frequency: %7.3fMHz |\n" "%s| Max DAC frequency: %7.3fMHz |\n"
"%s|----------------------------|-----------------------------|\n"
"%s| LED blinker | |\n"
"%s|----------------------------| |\n"
"%s| PIO: %2d | |\n"
"%s| State machine: %2d | |\n"
"%s| GPIO: %2d | |\n"
"%s| Frequency: %2dHz | |\n"
"%s|----------------------------|-----------------------------|\n" "%s|----------------------------|-----------------------------|\n"
"%s| DAC Channel A | DAC Channel B |\n" "%s| DAC Channel A | DAC Channel B |\n"
"%s|----------------------------|-----------------------------|\n" "%s|----------------------------|-----------------------------|\n"
@ -553,15 +531,10 @@ void SysInfo (DAC DACobj[], blink_forever LED_blinky) {
"%s| Duty cycle: %3d%%%% | Duty cycle: %3d%%%% |\n" "%s| Duty cycle: %3d%%%% | Duty cycle: %3d%%%% |\n"
"%s| Sine harmonic: %1d | Sine harmonic: %1d |\n" "%s| Sine harmonic: %1d | Sine harmonic: %1d |\n"
"%s| Triangle Rise: %3d%%%% | Triangle Rise: %3d%%%% |\n", "%s| Triangle Rise: %3d%%%% | Triangle Rise: %3d%%%% |\n",
MarginVW, MarginFW, MarginFW, MarginVW, MarginFW, MarginFW, MarginFW,
MarginFW, (float)clock_get_hz(clk_sys)/1000000, MarginFW, (float)clock_get_hz(clk_sys)/1000000,
MarginFW, MaxDACfreq/1000000, MarginFW, MaxDACfreq/1000000,
MarginFW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW,
MarginFW, LED_blinky.pioNum,
MarginFW, LED_blinky.StateMachine,
MarginFW, PICO_DEFAULT_LED_PIN,
MarginFW, LED_blinky.Freq,
MarginFW, MarginFW, MarginFW,
MarginFW, DACobj[_DAC_A].Level, DACobj[_DAC_B].Level, MarginFW, DACobj[_DAC_A].Level, DACobj[_DAC_B].Level,
MarginFW, DACobj[_DAC_A].Freq, DACobj[_DAC_B].Freq, MarginFW, DACobj[_DAC_A].Freq, DACobj[_DAC_B].Freq,
MarginFW, DACobj[_DAC_A].Range, DACobj[_DAC_B].Range, MarginFW, DACobj[_DAC_A].Range, DACobj[_DAC_B].Range,
@ -631,11 +604,6 @@ static void MCP41020_Write (uint8_t _ctrl, uint8_t _data) {
// Scale the data byte to be in the range 0->255. // Scale the data byte to be in the range 0->255.
// Transmit data over the SPI bus to the Digi-Pot. // Transmit data over the SPI bus to the Digi-Pot.
uint8_t buff[2]; uint8_t buff[2];
// Depending on wiring, the MCP41020 Digi-Pot may have the channel selection bits reversed. If so, we will need to...
// if (_ctrl == 0x01) _ctrl = 0x02 ; // Swap channel A/B bits
// else if (_ctrl == 0x02) _ctrl = 0x01 ; // Note: Do not change if both channels are selected (code = 0x03)
buff[0] = _ctrl | 0x10 ; // Set command bit to Write data buff[0] = _ctrl | 0x10 ; // Set command bit to Write data
buff[1] = _data * 2.55 ; // Scale data byte (100%->255) buff[1] = _data * 2.55 ; // Scale data byte (100%->255)
cs_select(Level_CS) ; // Transmit data to Digi-Pot cs_select(Level_CS) ; // Transmit data to Digi-Pot
@ -659,8 +627,8 @@ static void getLine() {
} }
int SetVal(DAC DACobj[], int _Parm) { int SetVal(DAC DACobj[], int _Parm) {
// Common code for setting frequency, duty cycle, phase, waaveform and level. // Common code for setting frequency, duty cycle, phase, waveform and level.
// Handles options to set a specific value or bump up/down... // Handles options to set a specific value or bump up/down...
if (inStr[3] == '+') { // Bump up and grab result for SPI display... if (inStr[3] == '+') { // Bump up and grab result for SPI display...
if (SelectedChan & 0b01) result = DACobj[_DAC_A].Bump(_Parm,_Up); if (SelectedChan & 0b01) result = DACobj[_DAC_A].Bump(_Parm,_Up);
if (SelectedChan & 0b10) result = DACobj[_DAC_B].Bump(_Parm,_Up) ; if (SelectedChan & 0b10) result = DACobj[_DAC_B].Bump(_Parm,_Up) ;
@ -670,73 +638,85 @@ int SetVal(DAC DACobj[], int _Parm) {
} else { // Not a bump, so set the absolute value from Parm[0]... } else { // Not a bump, so set the absolute value from Parm[0]...
if (SelectedChan & 0b01) result = DACobj[_DAC_A].Set(_Parm,Parm[0]) ; if (SelectedChan & 0b01) result = DACobj[_DAC_A].Set(_Parm,Parm[0]) ;
if (SelectedChan & 0b10) result = DACobj[_DAC_B].Set(_Parm,Parm[0]) ; if (SelectedChan & 0b10) result = DACobj[_DAC_B].Set(_Parm,Parm[0]) ;
dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels
} }
// Disable the Ctrl channels...
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
// wait for Busy flag to clear...
// Abort the data channels...
dma_channel_abort(DACobj[_DAC_A].data_chan);
dma_channel_abort(DACobj[_DAC_B].data_chan);
// Reset the data transfer DMA's to the start of the data Bitmap...
dma_channel_set_read_addr(DACobj[_DAC_A].data_chan, &DACobj[_DAC_A].DAC_data[0], false);
dma_channel_set_read_addr(DACobj[_DAC_B].data_chan, &DACobj[_DAC_B].DAC_data[0], false);
// Re-enable the Ctrl channels (doesn't restart data transfer)...
hw_set_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_set_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels
return result ; return result ;
} }
int main() { int main() {
bool InvX=false, InvY=false ; // Clock mode flags to allow inverted output bool InvX=false, InvY=false ; // Clock display mode flags to allow inverted output
set_sys_clock_khz(SysClock*1000, true) ; // Set Pico clock speed set_sys_clock_khz(SysClock*1000, true) ; // Set Pico clock speed
MaxDACfreq = clock_get_hz(clk_sys) / BitMapSize ; // Calculate Maximum DAC output frequency for given CPU clock speed MaxDACfreq = clock_get_hz(clk_sys) / BitMapSize ; // Calculate Maximum DAC output frequency for given CPU clock speed
stdio_init_all() ; stdio_init_all() ;
spi_init(SPI_PORT, 500000); // Set SPI0 at 0.5MHz.
spi_init(SPI_PORT, 500000); // Set SPI0 at 0.5MHz...
gpio_set_function(PIN_CLK, GPIO_FUNC_SPI); gpio_set_function(PIN_CLK, GPIO_FUNC_SPI);
gpio_set_function(PIN_TX, GPIO_FUNC_SPI); gpio_set_function(PIN_TX, GPIO_FUNC_SPI);
// Chip select is active-low, so initialise to a driven-high state... gpio_init(Display_CS) ; // Initailse the required GPIO ports...
gpio_init(Display_CS); gpio_set_dir(Display_CS, GPIO_OUT) ;
gpio_set_dir(Display_CS, GPIO_OUT); gpio_put(Display_CS, 1) ; // Chip select is active-low, so initialise to high state
gpio_put(Display_CS, 1); gpio_init(Level_CS) ;
gpio_init(Level_CS); gpio_set_dir(Level_CS, GPIO_OUT) ;
gpio_set_dir(Level_CS, GPIO_OUT); gpio_put(Level_CS, 1) ; // Chip select is active-low, so initialise to high state
gpio_put(Level_CS, 1); gpio_init(PICO_DEFAULT_LED_PIN) ;
gpio_set_dir(PICO_DEFAULT_LED_PIN, GPIO_OUT) ;
gpio_set_dir(PIN_CLK, GPIO_OUT) ; // Initialise remaining SPI connections...
gpio_set_dir(PIN_TX, GPIO_OUT) ;
// Setting Max slew rate and gpio drive strength keeps output linear at high frequencies...
for (int i=0; i<16; i++) { for (int i=0; i<16; i++) {
gpio_set_slew_rate(i, GPIO_SLEW_RATE_FAST); gpio_set_slew_rate(i, GPIO_SLEW_RATE_FAST); // Setting Max slew rate and gpio drive strength keeps output
gpio_set_drive_strength(i, GPIO_DRIVE_STRENGTH_12MA); gpio_set_drive_strength(i, GPIO_DRIVE_STRENGTH_12MA); // linear at high frequencies...
} }
// Initialise remaining SPI connections...
gpio_set_dir(PIN_CLK, GPIO_OUT);
gpio_set_dir(PIN_TX, GPIO_OUT);
struct repeating_timer timer;
add_repeating_timer_ms(-1000, Repeating_Timer_Callback, NULL, &timer); // 7ms - Short enough to prevent Nixie tube flicker
memset(MarginFW,' ',MWidth) ; // Initialise Fixed Width margin... memset(MarginFW,' ',MWidth) ; // Initialise Fixed Width margin...
MarginFW[MWidth] = '\0' ; // ... and terminate MarginFW[MWidth] = '\0' ; // ... and terminate
memset(MarginVW,' ',MWidth) ; // Initialise Variable Width margin... memset(MarginVW,' ',MWidth) ; // Initialise Variable Width margin...
MarginVW[MWidth] = '\0' ; // ... and terminate MarginVW[MWidth] = '\0' ; // ... and terminate
ResultStr[0] = '\0' ; // Reset string ResultStr[0] = '\0' ; // Reset string
// Instantiate objects to control the various State Machines... // Instantiate objects to control the various State Machines...
// Note: Both DAC channels need to be on the same PIO to achieve // Note: Both DAC channels need to be on the same PIO to achieve
// Atomic restarts for accurate phase sync. // Atomic restarts for accurate phase sync.
DAC DACobj[2]; // Array to hold the two DAC channel objects DAC DACobj[2]; // Array to hold the two DAC channel objects
DACobj[_DAC_A].DAC_chan('A',pio1,0); // First DAC channel object in array - resistor network connected to GPIO0->8 DACobj[_DAC_A].DAC_chan('A',pio1,0); // First DAC channel object in array - resistor network connected to GPIO0->8
DACobj[_DAC_B].DAC_chan('B',pio1,8); // Second DAC channel object in array - resistor network connected to GPIO8->16 DACobj[_DAC_B].DAC_chan('B',pio1,8); // Second DAC channel object in array - resistor network connected to GPIO8->16
blink_forever LED_blinky(pio0); // Onboard LED blinky object
strcpy(LastCmd,"?") ; // Hitting return will give 'Help' strcpy(LastCmd,"?") ; // Hitting return will give 'Help'
SPI_Display_Write(SysClock) ; // Pico system clock speed (in MHz) SPI_Display_Write(SysClock) ; // Pico system clock speed (in MHz)
MCP41020_Write(0x3, 50) ; // Both channels -> 50% output level MCP41020_Write(0x3, 50) ; // Both channels -> 50% output level
LED_blinky.Set_Frequency(1); // Flash LED at 1Hz- waiting for USB connection
while (!stdio_usb_connected()) { sleep_ms(100); } // Wait for USB connection... while (!stdio_usb_connected()) { sleep_ms(100); } // Wait for USB connection...
LED_blinky.Set_Frequency(10); // Flash LED at 10Hz - USB connected.
SPI_Display_Write(DACobj[_DAC_A].Freq) ; // Frequency => SPI display SPI_Display_Write(DACobj[_DAC_A].Freq) ; // Frequency => SPI display
// Send (optional) start-up messages to terminal... // Send (optional) start-up messages to terminal...
VerText() ; // Version text VerText() ; // Version text
printf(ResultStr) ; // Update terminal printf(ResultStr) ; // Update terminal
// Atomic Restart - starting all 4 DMA channels simultaneously ensures phase sync between both DAC channels // Atomic Restart - starting all 4 DMA channels simultaneously ensures phase sync between both DAC channels
dma_start_channel_mask(DAC_channel_mask); dma_start_channel_mask(DAC_channel_mask); // Sets the 'Busy' flag in Ctrl reg
struct repeating_timer timer;
add_repeating_timer_ms(-200, Repeating_Timer_Callback, NULL, &timer) ; // 5 x per second to blink LED
while(1) { while(1) {
ParmCnt=0, Parm[0]=0, Parm[1]=0, Parm[2]=0, Parm[3]=0 ; // Reset all command line parameters ParmCnt=0, Parm[0]=0, Parm[1]=0, Parm[2]=0, Parm[3]=0 ; // Reset all command line parameters
@ -760,7 +740,7 @@ int main() {
DACobj[_DAC_A].StatusString() ; DACobj[_DAC_A].StatusString() ;
DACobj[_DAC_B].StatusString() ; DACobj[_DAC_B].StatusString() ;
} }
if (inStr[0] == 'I') SysInfo(DACobj, LED_blinky); // TBD - inconsitant - make these global ?? if (inStr[0] == 'I') SysInfo(DACobj); // TBD - inconsitant - make these global ??
} }
// For all remaining commands, the first character selects DAC channel A or B... // For all remaining commands, the first character selects DAC channel A or B...
@ -797,57 +777,61 @@ int main() {
} }
// Next two chars select the command... // Next two chars select the command...
if ((inStr[1]=='p')&(inStr[2]=='h')) SetVal(DACobj,_Phase_) ; // Phase if ((inStr[1]=='p')&(inStr[2]=='h')) SetVal(DACobj,_Phase_) ; // Phase
if ((inStr[1]=='l')&(inStr[2]=='e')) SetVal(DACobj,_Level_) ; // Level if ((inStr[1]=='l')&(inStr[2]=='e')) SetVal(DACobj,_Level_) ; // Level
if ((inStr[1]=='s')&(inStr[2]=='i')) SetVal(DACobj,_Sine_) ; // Sine wave (optional harmonic parameter) if ((inStr[1]=='s')&(inStr[2]=='i')) SetVal(DACobj,_Sine_) ; // Sine wave (optional harmonic parameter)
if ((inStr[1]=='f')&(inStr[2]=='r')) { // Frequency if ((inStr[1]=='f')&(inStr[2]=='r')) SetVal(DACobj,_Freq_) ; // Frequency
SetVal(DACobj,_Freq_) ; // Set value
dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels
}
// The next two commands need different default values... // The next two commands need different default values...
if (strlen(inStr)==3) Parm[0] = 50 ; // If no value provided, set default to 50 if (strlen(inStr)==3) Parm[0] = 50 ; // If no value provided, set default to 50
if ((inStr[1]=='s')&(inStr[2]=='q')) SetVal(DACobj,_Square_) ; // Set Square wave (optional duty cycle parameter) if ((inStr[1]=='s')&(inStr[2]=='q')) SetVal(DACobj,_Square_) ; // Set Square wave (optional duty cycle parameter)
if ((inStr[1]=='t')&(inStr[2]=='r')) SetVal(DACobj,_Triangle_) ; // Set Triangle wave (optional duty cycle parameter) if ((inStr[1]=='t')&(inStr[2]=='r')) SetVal(DACobj,_Triangle_) ; // Set Triangle wave (optional duty cycle parameter)
if ((inStr[1]=='t')&(inStr[2]=='i')) { // Time display... if ((inStr[1]=='t')&(inStr[2]=='i')) { // Time display...
DACobj[_DAC_A].Set(_Phase_, 0) ; // Phase lock // Disable the Ctrl channels...
DACobj[_DAC_B].Set(_Phase_, 0) ; hw_clear_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
// wait for Busy flag to clear...
for (int gpio = 0; gpio < 16; gpio++) { // Grabs the GPIO back from the State machines // Abort the data channels...
gpio_init(gpio); dma_channel_abort(DACobj[_DAC_A].data_chan);
gpio_set_dir(gpio, GPIO_OUT); dma_channel_abort(DACobj[_DAC_B].data_chan);
}
// Disable both DMA channels associated with this DAC... // Re-enable the Ctrl channels (doesn't restart data transfer)...
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_A].data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS); hw_set_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_B].data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS); hw_set_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
// Reset the data transfer DMA's to the start of the data Bitmap...
dma_channel_set_read_addr(DACobj[_DAC_A].data_chan, &DACobj[_DAC_A].DAC_data[0], false);
dma_channel_set_read_addr(DACobj[_DAC_B].data_chan, &DACobj[_DAC_B].DAC_data[0], false);
pio_sm_set_enabled(pio1,0,false) ; // disable State machine 0 !! HARD CODED !! pio_sm_set_enabled(pio1,0,false) ; // disable State machine 0 !! HARD CODED !!
pio_sm_set_enabled(pio1,1,false) ; // disable State machine 1 pio_sm_set_enabled(pio1,1,false) ; // disable State machine 1
for (uint i=0; i<16; i++) { // Grab the GPIO back from the State machines
gpio_init(i);
gpio_set_dir(i, GPIO_OUT);
}
gpio_clr_mask(0xff) ; // clear first 16 GPIO outputs gpio_clr_mask(0xff) ; // clear first 16 GPIO outputs
ResultStr[0] = '\0' ; // String also used as a flag, so needs to be cleared ResultStr[0] = '\0' ; // String also used as a flag, so needs to be cleared
while (ResultStr[0] == '\0') { // exit on keypress while (ResultStr[0] == '\0') { // exit on keypress
float Radians ; float Radians ;
int outX, outY ;
// Draw the clock face... // Draw the clock face...
for (int i=0; i<sizeof(FaceX); i++) { for (int i=0; i<sizeof(FaceX); i++) {
if (InvX) { gpio_put_masked(0x00ff,FaceX[i]) ; } // Write inverted data byte to DAC A outX=FaceX[i] * DACobj[_DAC_A].Level / 100 ; // Scale output to match state machine settings
else { gpio_put_masked(0x00ff,255-FaceX[i]) ; } // Write non-inverted data byte to DAC A outY=FaceY[i] * DACobj[_DAC_B].Level / 100 ;
if (InvY) { gpio_put_masked(0xff00,FaceY[i]<<8) ; } // Write inverted data byte to DAC B if (InvX) { gpio_put_masked(0x00ff,outX) ; } // Write inverted data byte to DAC A
else { gpio_put_masked(0xff00,255-FaceY[i]<<8) ; } // Write non-inverted data byte to DAC B else { gpio_put_masked(0x00ff,255-outX) ; } // Write non-inverted data byte to DAC A
if (InvY) { gpio_put_masked(0xff00,outY<<8) ; } // Write inverted data byte to DAC B
else { gpio_put_masked(0xff00,255-outY<<8) ; } // Write non-inverted data byte to DAC B
sleep_us(2) ; // Pause for on-screen persistance sleep_us(2) ; // Pause for on-screen persistance
} }
// Draw the clock hands... // Draw the clock hands...
for (i=0; i<192; i++) { // 3 hands @ 64 pixels each = 192 for (i=0; i<192; i++) { // 3 hands @ 64 pixels each = 192
if (InvX) { gpio_put_masked(0x00ff,HandsX[i]) ; } // Write inverted data byte to DAC A outX=HandsX[i] * DACobj[_DAC_A].Level / 100 ; // Scale output to match state machine settings
else { gpio_put_masked(0x00ff,255-HandsX[i]) ; } // Write non-inverted data byte to DAC A outY=HandsY[i] * DACobj[_DAC_B].Level / 100 ;
if (InvY) { gpio_put_masked(0xff00,HandsY[i]<<8) ; } // Write inverted data byte to DAC B if (InvX) { gpio_put_masked(0x00ff,outX) ; } // Write inverted data byte to DAC A
else { gpio_put_masked(0xff00,255-HandsY[i]<<8) ; } // Write non-inverted data byte to DAC B else { gpio_put_masked(0x00ff,255-outX) ; } // Write non-inverted data byte to DAC A
if (InvY) { gpio_put_masked(0xff00,outY<<8) ; } // Write inverted data byte to DAC B
else { gpio_put_masked(0xff00,255-outY<<8) ; } // Write non-inverted data byte to DAC B
sleep_us(2) ; // Pause for on-screen persistance sleep_us(2) ; // Pause for on-screen persistance
} }
@ -878,17 +862,21 @@ int main() {
} }
inStr[0]='\0' ; // Reset input buffer inStr[0]='\0' ; // Reset input buffer
Hours=Parm[0]%24 ; Mins=Parm[1]%60 ; Secs=Parm[2]%60 ; // Set the time from parameters Hours=Parm[0]%24 ; Mins=Parm[1]%60 ; Secs=Parm[2]%60 ; // Set the time from parameters
LEDCtr=0 ; // Force update and do it now
Repeating_Timer_Callback(&timer) ;
printf("\n%sClock set to %02d:%02d:%02d\n>",MarginFW,Hours,Mins,Secs) ; printf("\n%sClock set to %02d:%02d:%02d\n>",MarginFW,Hours,Mins,Secs) ;
} }
else if ((c=='q') or (c=='Q')) { else if ((c=='q') or (c=='Q')) {
strcpy(ResultStr," Quit clock mode\n") ; // Prevents error message for (uint i=0; i<16; i++) { pio_gpio_init(pio1, i); } // Hand the GPIO's back to the state machines
// Re-enable both DMA channels associated with this DAC...
hw_set_bits(&dma_hw->ch[DACobj[_DAC_A].data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS); // Reset the data transfer DMA's to the start of the data Bitmap...
hw_set_bits(&dma_hw->ch[DACobj[_DAC_B].data_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS); dma_channel_set_read_addr(DACobj[_DAC_A].data_chan, &DACobj[_DAC_A].DAC_data[0], false);
dma_channel_set_read_addr(DACobj[_DAC_B].data_chan, &DACobj[_DAC_B].DAC_data[0], false);
pio_sm_set_enabled(pio1,0,true) ; // Re-enable State machine 0 !! HARD CODED !! pio_sm_set_enabled(pio1,0,true) ; // Re-enable State machine 0 !! HARD CODED !!
pio_sm_set_enabled(pio1,1,true) ; // Re-enable State machine 1 pio_sm_set_enabled(pio1,1,true) ; // Re-enable State machine 1
// Re-init the state machines ???? dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels
strcpy(ResultStr," Quit clock mode\n") ; // Prevents error message
} }
} }
} }
@ -896,31 +884,44 @@ int main() {
// The final command is a continual loop creating the sweep function... // The final command is a continual loop creating the sweep function...
if ((inStr[1] == 's') & (inStr[2] == 'w')) { // Sweep if ((inStr[1] == 's') & (inStr[2] == 'w')) { // Sweep
// Parm[0]=Low frequency, Parm[1]=High frequency, Parm[2]=Scan speed, Parm[3]=Low/High pause // Parm[0]=Low frequency, Parm[1]=High frequency, Parm[2]=Scan speed, Parm[3]=Low/High pause
i = Parm[0]; i = Parm[0];
for (;;) { for (;;) {
if (SelectedChan & 0b01) result = DACobj[_DAC_A].Set(_Freq_,i) ; // Set frequency, display status if (SelectedChan & 0b01) result = DACobj[_DAC_A].Set(_Freq_,i) ; // Set frequency, display status
if (SelectedChan & 0b10) result = DACobj[_DAC_B].Set(_Freq_,i) ; // Set frequency, display status if (SelectedChan & 0b10) result = DACobj[_DAC_B].Set(_Freq_,i) ; // Set frequency, display status
dma_start_channel_mask(DAC_channel_mask); // Atomic restart all 4 DMA channels... dma_start_channel_mask(DAC_channel_mask); // Atomic restart all 4 DMA channels...
printf(ResultStr) ; // Update terminal printf(ResultStr) ; // Update terminal
ResultStr[0] = '\0' ; // Reset the string variable ResultStr[0] = '\0' ; // Reset the string variable
SPI_Display_Write(i); // Update SPI display SPI_Display_Write(i); // Update SPI display
if (i==Parm[0]) { dirn = 1; if (i==Parm[0]) { dirn = 1;
sleep_ms(Parm[3]); } sleep_ms(Parm[3]); }
if (i>=Parm[1]) { dirn =-1; if (i>=Parm[1]) { dirn =-1;
sleep_ms(Parm[3]); } sleep_ms(Parm[3]); }
dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels // Disable the Ctrl channels...
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_clear_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
// wait for Busy flag to clear...
// Abort the data channels...
dma_channel_abort(DACobj[_DAC_A].data_chan);
dma_channel_abort(DACobj[_DAC_B].data_chan);
// Re-enable the Ctrl channels (doesn't restart data transfer)...
hw_set_bits(&dma_hw->ch[DACobj[_DAC_A].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
hw_set_bits(&dma_hw->ch[DACobj[_DAC_B].ctrl_chan].al1_ctrl, DMA_CH0_CTRL_TRIG_EN_BITS);
dma_start_channel_mask(DAC_channel_mask); // Atomic restart both DAC channels
i = i + dirn; i = i + dirn;
c = getchar_timeout_us (0); // Non-blocking char input c = getchar_timeout_us (0); // Non-blocking char input
if ((c>=32) & (c<=126)) { if ((c>=32) & (c<=126)) {
strcpy(ResultStr," Exit sweep mode\n") ; // Prevents error message strcpy(ResultStr," Exit sweep mode\n") ; // Prevents error message
break; } // exit on keypress break; } // exit on keypress
sleep_ms(Parm[2]); // Speed of scan sleep_ms(Parm[2]); // Speed of scan
} }
} }
if (strlen(ResultStr) == 0) { // No result can only mean unrecognised command if (strlen(ResultStr) == 0) { // No result can only mean unrecognised command
strcpy(MarginVW,MarginFW) ; // Reset Variable Width margin strcpy(MarginVW,MarginFW) ; // Reset Variable Width margin
tmp = strlen(inStr) ; tmp = strlen(inStr) ;
if (tmp != 0) tmp ++ ; // Bump to allow for cursor character if (tmp != 0) tmp ++ ; // Bump to allow for cursor character
MarginVW[MWidth - tmp] = '\0' ; // Calculate padding for input and cursor MarginVW[MWidth - tmp] = '\0' ; // Calculate padding for input and cursor

Plik binarny nie jest wyświetlany.

Wyświetl plik

@ -1,35 +0,0 @@
.program pio_blink
; Turn on LED for 1002 cycles and off for 1002 cycles.
; Large delays are required to allow the State Machine to toggle at frequencies as low as 1Hz.
; Note: Oscilloscope shows this runs about 2% fast indicating an issue with the cycle count.
.wrap_target
set pins, 1 ; Turn LED on
set x,25
; 2 cycles to this point
label01:
nop [19] ; 20 cycles
nop [18] ; 19 cycles
jmp x--, label01 ; 1 cycles
; ; 2 + 25*(20+19+1) = 1002 cycles to this point
; (restart cycle count)
set pins, 0 ; Turn LED off
set x,25
; 2 cycles to this point
label02:
nop [19] ; 20 cycles
nop [18] ; 19 cycles
jmp x--, label02 ; 1 cycles
; ; 2 + 25*(20+19+1) = 1002 cycles to this point
.wrap ; Blink forever!
% c-sdk {
// this is a raw helper function for use by the user which sets up the GPIO output, and configures the SM to output on a particular pin
void blink_program_init(PIO pio, uint sm, uint offset, uint pin) {
pio_gpio_init(pio, pin);
pio_sm_set_consecutive_pindirs(pio, sm, pin, 1, true);
pio_sm_config c = pio_blink_program_get_default_config(offset);
sm_config_set_set_pins(&c, pin, 1);
pio_sm_init(pio, sm, offset, &c);
}
%}