From ae8697f44a02327217624c04ddd1f1a73c6f9023 Mon Sep 17 00:00:00 2001 From: Tony Date: Fri, 25 Aug 2023 13:42:33 +0100 Subject: [PATCH] Initial commit --- Clock/CMakeLists.txt | 22 +++ Clock/Clock.cpp | 237 +++++++++++++++++++++++++++++ Clock/pico-examples.code-workspace | 55 +++++++ 3 files changed, 314 insertions(+) create mode 100644 Clock/CMakeLists.txt create mode 100644 Clock/Clock.cpp create mode 100644 Clock/pico-examples.code-workspace diff --git a/Clock/CMakeLists.txt b/Clock/CMakeLists.txt new file mode 100644 index 0000000..2c7e758 --- /dev/null +++ b/Clock/CMakeLists.txt @@ -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) diff --git a/Clock/Clock.cpp b/Clock/Clock.cpp new file mode 100644 index 0000000..fb3edf1 --- /dev/null +++ b/Clock/Clock.cpp @@ -0,0 +1,237 @@ +#include +#include +#include +#include +#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(iscnn,nn,nn - Set time Hours,Mins,Seconds\n" + "%swhere...\n" + "%s = 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",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; +} diff --git a/Clock/pico-examples.code-workspace b/Clock/pico-examples.code-workspace new file mode 100644 index 0000000..7829fd4 --- /dev/null +++ b/Clock/pico-examples.code-workspace @@ -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" + } + } +} \ No newline at end of file