kopia lustrzana https://github.com/oddwires/RP2040-code
2nd State Machine for low frequencies
rodzic
5b06ab9b8e
commit
316c1e1acc
|
@ -1,27 +0,0 @@
|
|||
.program pio_blink
|
||||
.wrap_target
|
||||
set y,0b00001
|
||||
mov pins, y
|
||||
set x, 31
|
||||
label01:
|
||||
jmp x--, label01 [31]
|
||||
;
|
||||
set y,0b00000
|
||||
mov pins, y
|
||||
set x, 31
|
||||
label02:
|
||||
jmp x--, label02 [31]
|
||||
.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, uint div) {
|
||||
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_clkdiv(&c, div); // Set the clock divider for the state machine
|
||||
sm_config_set_out_pins(&c, pin, 1);
|
||||
pio_sm_init(pio, sm, offset, &c);
|
||||
}
|
||||
%}
|
|
@ -10,14 +10,27 @@
|
|||
#include "FastDAC.pio.h"
|
||||
#include "SlowDAC.pio.h"
|
||||
|
||||
#define sine_table_size 256 // Number of samples per period in sine table
|
||||
|
||||
// Ref. Commands to use when my useless laptop crashes causing VSCode to trash the environment...
|
||||
// cd ./build
|
||||
// cmake -G "NMake Makefiles" ..
|
||||
// nmake
|
||||
|
||||
// Global variables...
|
||||
int ScanCtr, FlashCtr;
|
||||
int DAC[5] = { 2, 3, 4, 5, 6 }; // DAC ports - DAC0=>2 DAC4=>6
|
||||
int NixieCathodes[4] = { 18, 19, 20, 21 }; // GPIO ports connecting to Nixie Cathodes - Data0=>18 Data3=>21
|
||||
int NixieAnodes[3] = { 22, 26, 27 }; // GPIO ports connecting to Nixie Anodes - Anode0=>22 Anode2=>27
|
||||
int EncoderPorts[2] = { 16, 17 }; // GPIO ports connecting to Rotary Encoder - 16=>Clock 17=>Data
|
||||
int NixieBuffer[3] = { 6, 7, 8 }; // Values to be displayed on Nixie tubes - Tube0=>1's
|
||||
// - Tube1=>10's
|
||||
// - Tube2=>100's
|
||||
int raw_sin[sine_table_size] ;
|
||||
unsigned short DAC_data[sine_table_size] __attribute__ ((aligned(2048))) ; // Align DAC data
|
||||
const uint32_t transfer_count = sine_table_size ; // Number of DMA transfers per event
|
||||
|
||||
void blink_pin_forever(PIO pio, uint sm, uint offset, uint pin, uint freq);
|
||||
// Number of samples per period in sine table
|
||||
#define sine_table_size 256
|
||||
|
||||
class RotaryEncoder { // class to initialise a state machine to read
|
||||
public: // the rotation of the rotary encoder
|
||||
|
@ -72,6 +85,8 @@ private:
|
|||
uint sm; // the state machine
|
||||
static int rotation; // the current location of rotation
|
||||
};
|
||||
// Global Var...
|
||||
int RotaryEncoder::rotation; // Initialize static members of class Rotary_encoder
|
||||
|
||||
class blink_forever { // Class to initialise a state macne to blink a GPIO pin
|
||||
public:
|
||||
|
@ -82,32 +97,6 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
/* class DAC_write {
|
||||
public:
|
||||
DAC_write(PIO pio, uint sm, uint offset, uint pin) {
|
||||
pio_FastDAC_program_init(pio, sm, offset, pin);
|
||||
printf("PIO:%d, SM:%d running 'FastDAC'\n", 1, sm);
|
||||
// pio->txf[sm] = clock_get_hz(clk_sys) / (2 * freq); // Write to FIFO
|
||||
}
|
||||
}; */
|
||||
|
||||
// Global variables...
|
||||
int RotaryEncoder::rotation; // Initialize static members of class Rotary_encoder
|
||||
int DAC[5] = { 2, 3, 4, 5, 6 }; // DAC ports - DAC0=>2 DAC4=>6
|
||||
int NixieCathodes[4] = { 18, 19, 20, 21 }; // GPIO ports connecting to Nixie Cathodes - Data0=>18 Data3=>21
|
||||
int NixieAnodes[3] = { 22, 26, 27 }; // GPIO ports connecting to Nixie Anodes - Anode0=>22 Anode2=>27
|
||||
int EncoderPorts[2] = { 16, 17 }; // GPIO ports connecting to Rotary Encoder - 16=>Clock 17=>Data
|
||||
int NixieBuffer[3] = { 6, 7, 8 }; // Values to be displayed on Nixie tubes - Tube0=>1's
|
||||
// - Tube1=>10's
|
||||
// - Tube2=>100's
|
||||
int raw_sin[sine_table_size] ;
|
||||
unsigned short DAC_data[sine_table_size] __attribute__ ((aligned(2048))) ; // Align DAC data
|
||||
|
||||
const uint32_t transfer_count = sine_table_size ; // Number of DMA transfers per event
|
||||
static inline void dma_channel_set_timer0(uint32_t timerval) { // Modify the TIMER0 register of the dma channel
|
||||
dma_hw->timer[0] = timerval;
|
||||
}
|
||||
|
||||
void WriteCathodes (int Data) {
|
||||
// Create bit pattern on cathode GPIO's corresponding to the Data input...
|
||||
int shifted;
|
||||
|
@ -121,11 +110,35 @@ void WriteCathodes (int Data) {
|
|||
gpio_put(NixieCathodes[3], shifted %2);
|
||||
}
|
||||
|
||||
bool Repeating_Timer_Callback(struct repeating_timer *t) {
|
||||
// Scans the Nixie Anodes, and transfers data from the Nixie Buffers to the Cathodes.
|
||||
switch (ScanCtr) {
|
||||
case 0:
|
||||
gpio_put(NixieAnodes[2], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[0]); // Set up new data on cathodes (Units)
|
||||
gpio_put(NixieAnodes[0], 1) ; // Turn on current anode
|
||||
break;
|
||||
case 1:
|
||||
gpio_put(NixieAnodes[0], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[1]); // Set up new data on cathodes (10's)
|
||||
gpio_put(NixieAnodes[1], 1) ; // Turn on current anode
|
||||
break;
|
||||
case 2:
|
||||
gpio_put(NixieAnodes[1], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[2]); // Set up new data on cathodes (100's)
|
||||
gpio_put(NixieAnodes[2], 1) ; // Turn on current anode
|
||||
break;
|
||||
}
|
||||
ScanCtr++;
|
||||
if ( ScanCtr > 2 ) { ScanCtr = 0; } // Bump and Wrap the counter
|
||||
return true;
|
||||
}
|
||||
|
||||
int main() {
|
||||
set_sys_clock_khz(280000, true); // Overclocking the core by a factor of 2 allows 1MHz from DAC
|
||||
stdio_init_all(); // needed for printf
|
||||
|
||||
int scan = 0, lastval, temp;
|
||||
int lastval, temp;
|
||||
static const float blink_freq = 16000; // Reduce SM clock to keep flash visible...
|
||||
float blink_div = (float)clock_get_hz(clk_sys) / blink_freq; // ... calculate the required blink SM clock divider
|
||||
static const float rotary_freq = 16000; // Clock speed reduced to eliminate rotary encoder jitter...
|
||||
|
@ -160,7 +173,6 @@ int main() {
|
|||
for (i=0; i<(sine_table_size); i++){
|
||||
// raw_sin[i] = (int)(2047 * sin((float)i*6.283/(float)sine_table_size) + 2047); // 12 bit
|
||||
raw_sin[i] = (int)(15 * sin((float)i*6.283/(float)sine_table_size) + 15); // 5 bit
|
||||
DAC_data[i] = (raw_sin[i] & 0x0fff) ;
|
||||
DAC_data[i] = raw_sin[i] ; // memory alligned data
|
||||
}
|
||||
|
||||
|
@ -275,27 +287,30 @@ int main() {
|
|||
false // Don't start immediately.
|
||||
);
|
||||
|
||||
// We could choose to go and do something else whilst the DMA is doing its thing.
|
||||
// In this case the processor has nothing else to do, so we just wait for the DMA to finish.
|
||||
dma_channel_wait_for_finish_blocking(fast_data_chan);
|
||||
dma_channel_wait_for_finish_blocking(slow_data_chan);
|
||||
// Create a repeating timer that calls Repeating_Timer_Callback.
|
||||
// If the delay is > 0 then this is the delay between the previous callback ending and the next starting. If the delay is negative
|
||||
// then the next call to the callback will be exactly 7ms after the start of the call to the last callback.
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_ms(-7, Repeating_Timer_Callback, NULL, &timer); // 7ms - Short enough to avoid Nixie tube flicker
|
||||
// Long enough to avoid Nixie tube bluring
|
||||
|
||||
while (true) { // Infinite loop to print the current rotation
|
||||
if (my_encoder.get_rotation() != lastval) {
|
||||
// Falls through here when the rotary encoder value changes...
|
||||
temp = my_encoder.get_rotation();
|
||||
if (temp >= 17) {
|
||||
// If DAC_div exceeds 2^16 (65,536), the registers wrap around, and the State Machine clock will be incorrect.
|
||||
// A slower version of the DAC State Machine is used for frequencies below 17Hz, allowing the DAC_div to be kept
|
||||
// within range.
|
||||
// FastDAC
|
||||
DAC_freq = temp*256; // Target frequency...
|
||||
// FastDAC ( 17Hz=>1Mhz )
|
||||
DAC_freq = temp*256000; // Target frequency...
|
||||
DAC_div = (float)clock_get_hz(clk_sys) / DAC_freq; // ...calculate the required rotary encoder SM clock divider
|
||||
pio_sm_set_clkdiv(pio1, sm_FastDAC, DAC_div );
|
||||
pio_sm_set_enabled(pio, sm_SlowDAC, false); // Stop the SlowDAC State MAchine
|
||||
pio_sm_set_enabled(pio, sm_FastDAC, true); // Start the FastDAC State Machine
|
||||
dma_start_channel_mask(1u << fast_ctrl_chan); // Start the FastDAC DMA channel
|
||||
} else {
|
||||
// SlowDAC
|
||||
// SlowDAC ( 1Hz=>16Hz )
|
||||
DAC_freq = temp*256; // Target frequency...
|
||||
DAC_div = (float)clock_get_hz(clk_sys) / DAC_freq; // ...calculate the required rotary encoder SM clock divider
|
||||
DAC_div = DAC_div / 32; // Adjust to keep DAC_div within useable range
|
||||
|
@ -304,37 +319,14 @@ int main() {
|
|||
pio_sm_set_enabled(pio, sm_SlowDAC, true); // Start the SlowDAC State MAchine
|
||||
dma_start_channel_mask(1u << slow_ctrl_chan); // Start the SlowDAC DMA channel
|
||||
}
|
||||
printf("Rotation: %03d - SM Div: %8.1f - SM Clk: %06.0gHz - Fout: %3.0fHz\n",temp, DAC_div, DAC_freq, DAC_freq/256);
|
||||
printf("Rotation: %03d - SM Div: %8.4f - SM Clk: %06.0gHz - Fout: %3.0fHz\n",temp, DAC_div, DAC_freq, DAC_freq/256);
|
||||
|
||||
lastval = temp;
|
||||
NixieBuffer[0] = temp % 10 ; // finished with temp, so ok to destroy it
|
||||
temp /= 10 ;
|
||||
NixieBuffer[1] = temp % 10 ;
|
||||
temp /= 10 ;
|
||||
NixieBuffer[2] = temp % 10 ;
|
||||
NixieBuffer[0] = temp % 10 ; // First Nixie ( 1's )
|
||||
temp /= 10 ; // finished with temp, so ok to trash it. temp=>10's
|
||||
NixieBuffer[1] = temp % 10 ; // Second Nixie ( 10's )
|
||||
temp /= 10 ; // temp=>100's
|
||||
NixieBuffer[2] = temp % 10 ; // Third Nixie ( 100's )
|
||||
}
|
||||
|
||||
switch (scan) {
|
||||
case 0:
|
||||
gpio_put(NixieAnodes[2], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[0]); // Set up new data on cathodes (Units)
|
||||
gpio_put(NixieAnodes[0], 1) ; // Turn on current anode
|
||||
break;
|
||||
case 1:
|
||||
gpio_put(NixieAnodes[0], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[1]); // Set up new data on cathodes (10's)
|
||||
gpio_put(NixieAnodes[1], 1) ; // Turn on current anode
|
||||
break;
|
||||
case 2:
|
||||
gpio_put(NixieAnodes[1], 0) ; // Turn off previous anode
|
||||
WriteCathodes(NixieBuffer[2]); // Set up new data on cathodes (100's)
|
||||
gpio_put(NixieAnodes[2], 1) ; // Turn on current anode
|
||||
break;
|
||||
}
|
||||
scan++;
|
||||
if (scan == 3) { scan = 0; }
|
||||
|
||||
sleep_ms(7); // Pause: Short enough to avoid Nixie tube flicker
|
||||
// Long enough to avoid Nixie tube bluring
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue