ADD si5351_read_register_debug for reading the value of a bulk of register

This commit is contained in:
Tom Kuschel 2022-05-17 12:59:33 +02:00
parent f4a61ee06f
commit 83c3043d2c
4 changed files with 101 additions and 20 deletions

View File

@ -108,12 +108,26 @@ typedef enum {
#ifndef SI5351_NUMBER_OF_OUTPUTS #ifndef SI5351_NUMBER_OF_OUTPUTS
#define SI5351_NUMBER_OF_OUTPUTS 8 #define SI5351_NUMBER_OF_OUTPUTS 8
#endif #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 --------------------------------------------------------*/ /* Exported functions --------------------------------------------------------*/
si5351_inst_t si5351_init(void * i2c_handle, uint32_t xtal_frequency, uint8_t i2c_address); 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_deinit(si5351_inst_t si5351_handle);
int si5351_isready(si5351_inst_t inst); int si5351_isready(si5351_inst_t inst);
int si5351_program(si5351_inst_t inst); int si5351_program(si5351_inst_t inst);
char * si5351_read_debug_msg(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 #ifdef __cplusplus
} /* extern "C" */ } /* extern "C" */

View File

@ -605,9 +605,6 @@ Synth1 divider. */
/* #define SI5351_MULTISYNTH1_PARAMETER_2_LO_RESET_VALUE 0xXX */ /* #define SI5351_MULTISYNTH1_PARAMETER_2_LO_RESET_VALUE 0xXX */
/* Multisynth2 Parameter 3. /* Multisynth2 Parameter 3.
This 20-bit number is an encoded representation of the denominator for the frac- This 20-bit number is an encoded representation of the denominator for the frac-
tional part of the MultiSynth2 Divider. */ tional part of the MultiSynth2 Divider. */
@ -714,9 +711,6 @@ Synth2 divider. */
/* #define SI5351_MULTISYNTH2_PARAMETER_2_LO_RESET_VALUE 0xXX */ /* #define SI5351_MULTISYNTH2_PARAMETER_2_LO_RESET_VALUE 0xXX */
/* Multisynth3 Parameter 3. /* Multisynth3 Parameter 3.
This 20-bit number is an encoded representation of the denominator for the frac- This 20-bit number is an encoded representation of the denominator for the frac-
tional part of the MultiSynth3 Divider. */ tional part of the MultiSynth3 Divider. */
@ -823,9 +817,6 @@ Synth3 divider. */
/* #define SI5351_MULTISYNTH3_PARAMETER_2_LO_RESET_VALUE 0xXX */ /* #define SI5351_MULTISYNTH3_PARAMETER_2_LO_RESET_VALUE 0xXX */
/* MULTISYNTH5 Parameter 3. /* MULTISYNTH5 Parameter 3.
This 20-bit number is an encoded representation of the denominator for the frac- This 20-bit number is an encoded representation of the denominator for the frac-
tional part of the MultiSynth4 Divider. */ tional part of the MultiSynth4 Divider. */
@ -932,13 +923,6 @@ Synth3 divider. */
/* #define SI5351_MULTISYNTH4_PARAMETER_2_LO_RESET_VALUE 0xXX */ /* #define SI5351_MULTISYNTH4_PARAMETER_2_LO_RESET_VALUE 0xXX */
/* Multisynth5 Parameter 3. /* Multisynth5 Parameter 3.
This 20-bit number is an encoded representation of the denominator for the frac- This 20-bit number is an encoded representation of the denominator for the frac-
tional part of the MultiSynth5 Divider. */ 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_0 (1u<<4) /* 110b: Divide by 64, 111b: Divide by 128 */
#define R6_DIV (7u<<4) #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 /* Crystal Internal Load Capacitance
* Two bits determine the internal load capacitance value for the crystal. See the Crystal * Two bits determine the internal load capacitance value for the crystal. See the Crystal

View File

@ -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"); 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]); status = si5351_program(instance_si5351[1]);
printf("Device #1 gets status %d\n", status); printf("Device #1 gets status %d\n", status);
printf("Debug:\n%s", si5351_read_debug_msg(instance_si5351[1])); printf("Debug:\n%s", si5351_read_debug_msg(instance_si5351[1]));
*/
for (int i=2; i>=0; i--) { for (int i=2; i>=0; i--) {
si5351_deinit(instance_si5351[i]); si5351_deinit(instance_si5351[i]);
} }

View File

@ -19,6 +19,7 @@
// @TODO try to get rid off including the HAL here, using pointer to the specified functions // @TODO try to get rid off including the HAL here, using pointer to the specified functions
#if DEBUG #if DEBUG
#include <stdio.h> #include <stdio.h>
#include <string.h>
#endif #endif
#include "stm32l4xx_hal.h" #include "stm32l4xx_hal.h"
@ -39,6 +40,17 @@ typedef struct __SI5351_HandleTypeDef {
uint8_t initialized:1; /*!< mark the driver initialized */ uint8_t initialized:1; /*!< mark the driver initialized */
} si5351_HandleTypeDef; } 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 ------------------------------------------------------------*/ /* Private define ------------------------------------------------------------*/
#define SI5351_VERSION 1 #define SI5351_VERSION 1
@ -47,6 +59,7 @@ typedef struct __SI5351_HandleTypeDef {
si5351_HandleTypeDef * first_handle = NULL; /* pointer to the first instancee */ si5351_HandleTypeDef * first_handle = NULL; /* pointer to the first instancee */
int si5351_errno = 0; /* error_number for functions whith return == NULL */ int si5351_errno = 0; /* error_number for functions whith return == NULL */
/* Private function prototypes -----------------------------------------------*/ /* Private function prototypes -----------------------------------------------*/
int __fprintb(FILE *stream, void *value, size_t size);
/* Private functions ---------------------------------------------------------*/ /* Private functions ---------------------------------------------------------*/
/* wrapper function for receiving bytes from I2C bus /* wrapper function for receiving bytes from I2C bus
@ -217,7 +230,7 @@ int si5351_program(si5351_inst_t inst) {
break; break;
/* power down all output drivers reg 16 -- 23 */ /* power down all output drivers reg 16 -- 23 */
data = SI5351_CLKx_PDN; // 0x80 data = SI5351_CLK0_PDN; // 0x80
#if OPTIMIZED #if OPTIMIZED
status = si5351_write(inst, SI5351_CLK0_CONTROL, &data, SI5351_NUMBER_OF_OUTPUTS); status = si5351_write(inst, SI5351_CLK0_CONTROL, &data, SI5351_NUMBER_OF_OUTPUTS);
if (status) if (status)
@ -266,7 +279,6 @@ int si5351_program(si5351_inst_t inst) {
#endif #endif
} while(0); } while(0);
@ -282,6 +294,60 @@ char * si5351_read_debug_msg(si5351_inst_t inst) {
return inst->debug_msg; 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 #if 0
int Si5351_WriteRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address, uint8_t reg_data) int Si5351_WriteRegister(Si5351_ConfigTypeDef *Si5351_ConfigStruct, uint8_t reg_address, uint8_t reg_data)