diff --git a/Core/Inc/stm32_si5351.h b/Core/Inc/stm32_si5351.h index ca78632..81a9a80 100644 --- a/Core/Inc/stm32_si5351.h +++ b/Core/Inc/stm32_si5351.h @@ -108,12 +108,26 @@ typedef enum { #ifndef SI5351_NUMBER_OF_OUTPUTS #define SI5351_NUMBER_OF_OUTPUTS 8 #endif + +#ifdef __arm__ +#ifdef __ARM_BIG_ENDIAN +#define for_endian(size) for (int i = 0; i < size; ++i) +#define last_loop_endian (i==size-1) +#else +#define for_endian(size) for (int i = size - 1; i >= 0; --i) +#define last_loop_endian (i==0) +#endif +#else +#error "Endianness not detected or another compiler" +#endif + /* Exported functions --------------------------------------------------------*/ si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address); int si5351_deinit(si5351_inst_t si5351_handle); int si5351_isready(si5351_inst_t inst); int si5351_program(si5351_inst_t inst); char * si5351_read_debug_msg(si5351_inst_t inst); +char * si5351_read_register_debug(si5351_inst_t inst, char *buf, size_t bufsize, uint8_t regaddr); #ifdef __cplusplus } /* extern "C" */ diff --git a/Core/Inc/stm32_si5351_reg.h b/Core/Inc/stm32_si5351_reg.h index e995efa..727694e 100644 --- a/Core/Inc/stm32_si5351_reg.h +++ b/Core/Inc/stm32_si5351_reg.h @@ -605,9 +605,6 @@ Synth1 divider. */ /* #define SI5351_MULTISYNTH1_PARAMETER_2_LO_RESET_VALUE 0xXX */ - - - /* Multisynth2 Parameter 3. This 20-bit number is an encoded representation of the denominator for the frac- tional part of the MultiSynth2 Divider. */ @@ -714,9 +711,6 @@ Synth2 divider. */ /* #define SI5351_MULTISYNTH2_PARAMETER_2_LO_RESET_VALUE 0xXX */ - - - /* Multisynth3 Parameter 3. This 20-bit number is an encoded representation of the denominator for the frac- tional part of the MultiSynth3 Divider. */ @@ -823,9 +817,6 @@ Synth3 divider. */ /* #define SI5351_MULTISYNTH3_PARAMETER_2_LO_RESET_VALUE 0xXX */ - - - /* MULTISYNTH5 Parameter 3. This 20-bit number is an encoded representation of the denominator for the frac- tional part of the MultiSynth4 Divider. */ @@ -932,13 +923,6 @@ Synth3 divider. */ /* #define SI5351_MULTISYNTH4_PARAMETER_2_LO_RESET_VALUE 0xXX */ - - - - - - - /* Multisynth5 Parameter 3. This 20-bit number is an encoded representation of the denominator for the frac- tional part of the MultiSynth5 Divider. */ @@ -1088,6 +1072,15 @@ even integers greater than or equal to 6. All other divide values are invalid. * #define R6_DIV_0 (1u<<4) /* 110b: Divide by 64, 111b: Divide by 128 */ #define R6_DIV (7u<<4) +/* PLL Reset + * Resets the PLLA, PLLB when writing an 1 to the corresponding bit + * Leave the reserved bits as default. + * Note: 0x00001100 is my reset value for Si5351A 10-MSOP device + */ +#define SI5351_PLL_RESET 177u /* R/W */ +#define SI5351_PLLB_RST (1u<<7) /*!< PLLB_Reset, writing a 1 to this bit will reset PLLB. This is a self clearing bit */ +#define SI5351_PLLA_RST (1u<<5) /*!< PLLA_Reset, writing a 1 to this bit will reset PLLA. This is a self clearing bit */ +#define SI5351_PLL_RESET_RESERVED (0x5F) /*!< leave as default, not specified */ /* Crystal Internal Load Capacitance * Two bits determine the internal load capacitance value for the crystal. See the Crystal diff --git a/Core/Src/main.c b/Core/Src/main.c index 152e5e2..1f430d4 100644 --- a/Core/Src/main.c +++ b/Core/Src/main.c @@ -142,11 +142,19 @@ int main(void) printf("Device No. %d (Instance No: 0x%x) is %s\n", i, (unsigned int) instance_si5351[i], (ready==0) ? "ready" : "N/A"); } - + puts("Registers of Device No. 1"); + char buf[33]; //using uint8_t + //char buf[42]; //using uint16_t + //char buf[60]; //using uint32_t + //for (int i=0; i <= SI5351_FANOUT_ENABLE; i++) { + for (int i=0; i <= 255; i++) { + puts(si5351_read_register_debug(instance_si5351[1], buf, sizeof(buf), i)); + } +/* status = si5351_program(instance_si5351[1]); printf("Device #1 gets status %d\n", status); printf("Debug:\n%s", si5351_read_debug_msg(instance_si5351[1])); - +*/ for (int i=2; i>=0; i--) { si5351_deinit(instance_si5351[i]); } diff --git a/Core/Src/stm32_si5351.c b/Core/Src/stm32_si5351.c index 7931fd9..5da016c 100644 --- a/Core/Src/stm32_si5351.c +++ b/Core/Src/stm32_si5351.c @@ -19,6 +19,7 @@ // @TODO try to get rid off including the HAL here, using pointer to the specified functions #if DEBUG #include +#include #endif #include "stm32l4xx_hal.h" @@ -39,6 +40,17 @@ typedef struct __SI5351_HandleTypeDef { uint8_t initialized:1; /*!< mark the driver initialized */ } si5351_HandleTypeDef; +#ifndef __GNUC__ /*__arm__*/ /* Keil ARM compiler does not support typeof */ +#define snprintb(buf, n, value) __fprintb(buf, n, (uint32_t *)&value, sizeof(uint32_t)) +#define snprintb16(buf, n, value) __fprintb(buf, n, (uint16_t *)&value, sizeof(uint16_t)) +#define snprintb8(buf, n, value) __fprintb(buf, n, (uint8_t *)&value, sizeof(uint8_t)) +#else /* for gcc, clang compilers */ +#define snprintb(buf, n, value) \ +({ \ + typeof(value) _v = value; \ + __snprintb(buf, n, (typeof(_v) *) &_v, sizeof(_v)); \ +}) +#endif /* Private define ------------------------------------------------------------*/ #define SI5351_VERSION 1 @@ -47,6 +59,7 @@ typedef struct __SI5351_HandleTypeDef { si5351_HandleTypeDef * first_handle = NULL; /* pointer to the first instancee */ int si5351_errno = 0; /* error_number for functions whith return == NULL */ /* Private function prototypes -----------------------------------------------*/ +int __fprintb(FILE *stream, void *value, size_t size); /* Private functions ---------------------------------------------------------*/ /* wrapper function for receiving bytes from I2C bus @@ -217,7 +230,7 @@ int si5351_program(si5351_inst_t inst) { break; /* power down all output drivers reg 16 -- 23 */ - data = SI5351_CLKx_PDN; // 0x80 + data = SI5351_CLK0_PDN; // 0x80 #if OPTIMIZED status = si5351_write(inst, SI5351_CLK0_CONTROL, &data, SI5351_NUMBER_OF_OUTPUTS); if (status) @@ -266,7 +279,6 @@ int si5351_program(si5351_inst_t inst) { #endif - } while(0); @@ -282,6 +294,60 @@ char * si5351_read_debug_msg(si5351_inst_t inst) { return inst->debug_msg; } +/*! + * @brief Output the value in binary representation and in groups of + * bytes + * + * @param buf string of char * to output to + * @param n amount of characters to output to + * @param value Value to output in binary representation + * @param size + * @return bytes written + */ +int __snprintb(char *buf, size_t n, void *value, size_t size) +{ + uint8_t byte; + size_t blen = sizeof(byte) * 8; + uint8_t bits[blen + 1]; + int cx = 0; + + bits[blen] = '\0'; + for_endian(size) { + byte = ((uint8_t *) value)[i]; + memset(bits, '0', blen); + for (int j = 0; byte && j < blen; ++j) { + if (byte & 0x80) + bits[j] = '1'; + byte <<= 1; + } + cx += snprintf(buf+cx, n-cx, "%s%s", bits, (last_loop_endian)? "":" "); + } + return cx; +} + +char * si5351_read_register_debug(si5351_inst_t inst, char *buf, size_t bufsize, uint8_t regaddr) { + + uint8_t data; + // uint16_t data16; + // uint32_t data32; + int status; + int cx; + + if (!inst) + return NULL; + + status = si5351_read(inst, regaddr, &data, 1); + if (status) + return NULL; + // data16 = data; + // data32 = data; + cx = snprintf(buf, bufsize, "R%03u[0x%02x]=%3u[0x%02x][0b", regaddr, regaddr, data, data); + cx += snprintb(buf + cx, bufsize - cx, data); + // cx += snprintb(buf + cx, bufsize - cx, data32); + cx += snprintf(buf + cx, bufsize - cx, "]"); + return buf; +} + #if 0 int Si5351_WriteRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address, uint8_t reg_data)