kopia lustrzana https://github.com/oddwires/RP2040-code
Initial commit
rodzic
bd55c22466
commit
ae8697f44a
|
@ -0,0 +1,22 @@
|
|||
add_executable(Clock)
|
||||
|
||||
# pull in common dependencies
|
||||
target_sources(Clock PRIVATE Clock.cpp)
|
||||
|
||||
# pull in common dependencies and additional spi hardware support
|
||||
target_link_libraries(Clock PRIVATE
|
||||
pico_stdlib
|
||||
hardware_pio
|
||||
hardware_dma
|
||||
hardware_spi
|
||||
)
|
||||
|
||||
# enable usb output, disable uart output
|
||||
pico_enable_stdio_usb(Clock 1)
|
||||
pico_enable_stdio_uart(Clock 0)
|
||||
|
||||
# create map/bin/hex file etc.
|
||||
pico_add_extra_outputs(Clock)
|
||||
|
||||
# add url via pico_set_program_url
|
||||
example_auto_set_url(Clock)
|
|
@ -0,0 +1,237 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <math.h>
|
||||
#include "pico/stdlib.h"
|
||||
#include "pico/binary_info.h"
|
||||
#include "hardware/spi.h"
|
||||
#include "hardware/clocks.h"
|
||||
#include "hardware/dma.h"
|
||||
|
||||
#include "hardware/gpio.h" // Required for manually toggling GPIO pins (clock)
|
||||
|
||||
#define eof 255 // EOF in stdio.h -is -1, but getchar returns int 255 to avoid blocking
|
||||
#define CR 13
|
||||
#define BitMapSize 256 // Match X to Y resolution
|
||||
#define MWidth 10 // Width of terminal command margin (in columns)
|
||||
#define SysClock 125 // System clock (Pico default)
|
||||
//#define SysClock 250 // System clock x 2 (Overclock)
|
||||
|
||||
// Data for clock face generated by 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,
|
||||
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} ;
|
||||
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,
|
||||
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} ;
|
||||
// (Number of pixels: 421)
|
||||
|
||||
// Store clock hands co-ordinates...
|
||||
uint8_t HandsX[192] = {} ; // Each hand requires 64 bytes - 3x64=192
|
||||
uint8_t HandsY[192] = {} ;
|
||||
int Hours=0, Mins=0, Secs=0, Angle, StartX, StartY, Radius ;
|
||||
float Radians ;
|
||||
|
||||
int tmp ; // Debug and general use
|
||||
|
||||
char MarginFW[MWidth+1], MarginVW[MWidth+1] ; // Fixed Width & Variable Width strings to create a fixed margin
|
||||
//unsigned short DAC_channel_mask = 0 ; // Binary mask to simultaneously start all DMA channels
|
||||
//const uint32_t transfer_count = BitMapSize ; // Number of DMA transfers per event
|
||||
//const float _2Pi = 6.283; // 2*Pi
|
||||
int c, i, ParmCnt = 0, Parm[4], WaveForm_Type ;
|
||||
//int SelectedChan, c, i = 0, dirn = 1, result ;
|
||||
int MarginCount = 0 ; // Manual count of characters written to terminal - required to maintain margins
|
||||
//float MaxDACfreq ;
|
||||
char inStr[15], outStr[1000], ResultStr[3000] ;
|
||||
|
||||
bool Repeating_Timer_Callback(struct repeating_timer *t) {
|
||||
int i, steps=64, MidX=128, MidY=128 ;
|
||||
// Bump the time...
|
||||
if ((++Secs)>59) Secs=0 ; // Always bump seconds
|
||||
if (Secs==0) { if ((++Mins)>59 ) Mins=0 ; } // Bump minutes when seconds = 0
|
||||
if ((Mins==0) && (Secs==0)) { if ((++Hours)>12) Hours=0 ; } // Bump hours when minutes and seconds = 0
|
||||
|
||||
// Calculate seconds hand...
|
||||
i=0, Radius=127 ;
|
||||
Angle=90-(Secs*6) ; // Angle in degrees
|
||||
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...
|
||||
Radius=95 ;
|
||||
Angle=90-(Mins*6) ; // Angle in degrees
|
||||
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...
|
||||
// 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.
|
||||
Radius=64 ;
|
||||
Angle=5*(90-((Hours*6)+(Mins/2)%5)) ; // Angle in degrees
|
||||
//Angle=5*(90-((6*(Hours))+(Mins/12))%5) ; // TBD - does this work ? is it clearer ?
|
||||
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+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;
|
||||
}
|
||||
|
||||
void VerText () {
|
||||
// Print version info aligned to current margin settings...
|
||||
tmp = strlen(inStr) ; // Get number of command line characters
|
||||
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
|
||||
sprintf(ResultStr, "%s|-------------------------|\n"
|
||||
"%s| Analog Clock Simulator |\n"
|
||||
"%s| Version 1.0.0 |\n"
|
||||
"%s| 25th August 2023 |\n"
|
||||
"%s|-------------------------|\n",
|
||||
MarginVW, MarginFW, MarginFW, MarginFW, MarginFW ) ;
|
||||
}
|
||||
|
||||
void HlpText () {
|
||||
// Print Help text aligned to current margin settings...
|
||||
// Note: Following string requires '%%%%' to print '%'
|
||||
// HelpText string is copied to outStr using sprintf - this reduces '%%%%' to '%%'
|
||||
// outStr is sent to terminal using printf - this reduces '%%' to '%'
|
||||
tmp = strlen(inStr) ; // Get number of command line characters
|
||||
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
|
||||
sprintf(ResultStr, "%sHelp...\n"
|
||||
"%s? - Help\n"
|
||||
"%sV - Version\n"
|
||||
"%s<A/B/C>scnn,nn,nn - Set time Hours,Mins,Seconds\n"
|
||||
"%swhere...\n"
|
||||
"%s<A/B/C> = DAC channel A,B or Both\n"
|
||||
"%snnn = Three digit numeric value\n",
|
||||
MarginVW, MarginFW, MarginFW, MarginFW, MarginFW, MarginFW) ;
|
||||
}
|
||||
|
||||
static inline void cs_select(int _gpio) {
|
||||
asm volatile("nop \n nop \n nop");
|
||||
gpio_put(_gpio, 0); // Active low
|
||||
asm volatile("nop \n nop \n nop");
|
||||
}
|
||||
|
||||
static inline void cs_deselect(int _gpio) {
|
||||
asm volatile("nop \n nop \n nop");
|
||||
gpio_put(_gpio, 1);
|
||||
asm volatile("nop \n nop \n nop");
|
||||
}
|
||||
|
||||
static void getLine() {
|
||||
char *pPos = (char *)inStr ; // Pointer to start of Global input string
|
||||
int count = 0 ;
|
||||
while(1) {
|
||||
c = getchar();
|
||||
if (c == eof || c == '\n' || c == '\r') break ; // Non blocking exit
|
||||
putchar(c); // FullDuplex echo
|
||||
*pPos++ = c ; // Bump pointer, store character
|
||||
count ++ ;
|
||||
}
|
||||
*pPos = '\0' ;
|
||||
MarginCount += count ; // Track number of characters on current line
|
||||
return ;
|
||||
}
|
||||
|
||||
int main() {
|
||||
set_sys_clock_khz(SysClock*1000, true) ; // Set Pico clock speed
|
||||
stdio_init_all() ;
|
||||
|
||||
// Initialise GPIO ports for use with R-2R resistor network...
|
||||
// (Setting Max slew rate and gpio drive strength keeps output linear at high frequencies)
|
||||
for (int gpio = 0; gpio < 16; gpio++) {
|
||||
gpio_init(gpio);
|
||||
gpio_set_dir(gpio, GPIO_OUT);
|
||||
gpio_set_slew_rate(gpio, GPIO_SLEW_RATE_FAST);
|
||||
gpio_set_drive_strength(gpio, GPIO_DRIVE_STRENGTH_12MA);
|
||||
}
|
||||
|
||||
struct repeating_timer timer;
|
||||
add_repeating_timer_ms(-1000, Repeating_Timer_Callback, NULL, &timer) ;
|
||||
|
||||
memset(MarginFW,' ',MWidth) ; // Initialise Fixed Width margin...
|
||||
MarginFW[MWidth] = '\0' ; // ... and terminate
|
||||
memset(MarginVW,' ',MWidth) ; // Initialise Variable Width margin...
|
||||
MarginVW[MWidth] = '\0' ; // ... and terminate
|
||||
ResultStr[0] = '\0' ; // Reset string
|
||||
|
||||
while (!stdio_usb_connected()) { sleep_ms(100); } // Wait for USB connection...
|
||||
|
||||
// Send (optional) start-up messages to terminal...
|
||||
VerText() ; // Version text
|
||||
printf(ResultStr) ; // Update terminal
|
||||
|
||||
while(1) {
|
||||
memset(MarginVW,' ',MWidth) ; // Re-initialise Variable Width margin...
|
||||
MarginVW[MWidth] = '\0' ; // ... and terminate
|
||||
ResultStr[0] = '\0' ; // Reset string
|
||||
printf(">") ; // Command prompt
|
||||
MarginCount = 1 ; // Reset count and bump for command prompt
|
||||
|
||||
// Clock display code...
|
||||
gpio_clr_mask(0xff) ; // clear first 16 GPIO outputs
|
||||
ResultStr[0] = '\0' ; // String also used as a flag, so needs to be cleared
|
||||
while (ResultStr[0] == '\0') { // exit on keypress
|
||||
// Draw the clock face...
|
||||
for (int i=0; i<sizeof(FaceX); i++) {
|
||||
gpio_put_masked(0x00ff,FaceX[i]) ; // Write data byte to DAC A
|
||||
gpio_put_masked(0xff00,FaceY[i]<<8) ; // Write data byte to DAC B
|
||||
sleep_us(2) ; // Pause for on-screen persistance
|
||||
}
|
||||
// Draw the clock hands...
|
||||
for (i=0; i<192; i++) { // 3 hands @ 64 pixels each = 192
|
||||
gpio_put_masked(0x00ff,HandsX[i]) ; // Write data byte to DAC A
|
||||
gpio_put_masked(0xff00,HandsY[i]<<8) ; // Write data byte to DAC B
|
||||
sleep_us(2) ; // Pause for on-screen persistance
|
||||
}
|
||||
// Check for console input...
|
||||
c = getchar_timeout_us (0); // Non-blocking char input
|
||||
if ((c=='S') or (c=='s')) { // Set time
|
||||
MarginCount = 1 ; // Reset count and bump for command prompt
|
||||
MarginVW[MWidth - MarginCount] = '\0' ; // Calculate padding required for command characters and cursor
|
||||
printf("%sSet time (format HH:MM:SS)\n%s",MarginVW, MarginFW ) ;
|
||||
getLine() ; // Get the console input
|
||||
Parm[0]=0, Parm[1]=0, Parm[2]=0, Parm[3]=0 ; // Reset all command line parameters
|
||||
i=0, ParmCnt=0 ; // Reset all command line counters
|
||||
while (i<strlen(inStr) ) {
|
||||
if (inStr[i]==':') { ParmCnt++ ; } // Next parameter
|
||||
else if (isdigit(inStr[i])) {
|
||||
Parm[ParmCnt] *= 10; // Next digit. Bump the existing decimal digits
|
||||
Parm[ParmCnt] += inStr[i] - '0'; } // Convert character to integer and add
|
||||
i++ ; // Next character
|
||||
}
|
||||
Hours=Parm[0]%24 ; Mins=Parm[1]%60 ; Secs=Parm[2]%60 ; // Set the time from parameters
|
||||
|
||||
printf("\n%sClock set to %02d:%02d:%02d\n>",MarginFW,Hours,Mins,Secs) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (strlen(ResultStr) == 0) { // No result can only mean unrecognised command
|
||||
strcpy(MarginVW,MarginFW) ; // Reset Variable Width margin
|
||||
tmp = strlen(inStr) ;
|
||||
if (tmp != 0) tmp ++ ; // Bump to allow for cursor character
|
||||
MarginVW[MWidth - tmp] = '\0' ; // Calculate padding for input and cursor
|
||||
sprintf(outStr,"%sUnknown command!\n", MarginVW) ; // Empty response buffer indicates command has not been recognised
|
||||
}
|
||||
else strcpy(outStr,ResultStr) ;
|
||||
printf(outStr) ; // Update terminal
|
||||
outStr[0] = '\0' ; // Clear (reset) the string variable
|
||||
// strcpy(LastCmd, inStr) ; // Preserve last command
|
||||
}
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"folders": [
|
||||
{
|
||||
"name": "sandpit",
|
||||
"path": ".."
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"files.associations": {
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"compare": "cpp",
|
||||
"concepts": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"deque": "cpp",
|
||||
"string": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"random": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"limits": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeinfo": "cpp"
|
||||
}
|
||||
}
|
||||
}
|
Ładowanie…
Reference in New Issue