test program for Silicon Laboratories Inc. Si5351A-B-GT I2C-PROGRAMMABLE ANY-FREQUENCY CMOS CLOCK GENERATOR

Dependencies:   Si5351A

si5351a_check.cpp

Committer:
kenjiArai
Date:
2017-08-23
Revision:
5:e32ef4b85317
Parent:
4:5981cf106502

File content as of revision 5:e32ef4b85317:

/*
 * mbed Application program / Si5351A sample program
 *  tested on:
 *      ST Nucleo-F411RE & F401RE
 *		LPC1114FN28
 *
 *  Copyright (c) 2016,'17 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:  December 28th, 2016
 *      Revised:  January   7th, 2017
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
 * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
 * DAMAGES OR OTHER  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR
 * THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */

//  Include --------------------------------------------------------------------
#include "mbed.h"
#include "si5351a.h"
#include "si5351a_check.h"

//  Definition -----------------------------------------------------------------

//  Object ---------------------------------------------------------------------
Serial		pc(USBTX, USBRX);
//I2C			i2c(dp5, dp27);	// communication with Si5351A
I2C			i2c(I2C_SDA, I2C_SCL);	// communication with Si5351A
SI5351A		clk(i2c, 25000000UL);	// base clock = 25.0MHz

//  RAM ------------------------------------------------------------------------
bool one_char = false;

//  ROM / Constant data --------------------------------------------------------
#if defined(RANGE_EXTENDED)
static const uint32_t freq_tbl[] =
{
 1628, 1800, 1900, 2000, 2500, 2604, 2605, 2700, 3000, // 1.627KHz-3KHz
 // Above includes out of range freq.
                 4000,      5000,     8000, // 4KHz-8KHz
     10000,     20000,     50000,    80000, // 10KHz-80KHz
    100000,    200000,    500000,   800000, // 100KHz-800KHz
   1000000,   2000000,   5000000,  8000000, // 1MHz-8MHz
  10000000,  20000000,  50000000, 80000000, // 10MHz-80MHz
 100000000, 150000000, 200000000,           // 100MHz-200MHz
 // Belows are out of Si5351A specification !!!!
 220000000, 250000000, 280000000, 300000000,// 200MHz-300MHz
 0  // Terminate data!!
};
#else
static const uint32_t freq_tbl[] =
{
      2605,      4000,      5000,     8000, // 2.6KHz-8KHz
     10000,     20000,     50000,    80000, // 10KHz-80KHz
    100000,    200000,    500000,   800000, // 100KHz-800KHz
   1000000,   2000000,   5000000,  8000000, // 1MHz-8MHz
  10000000,  20000000,  50000000, 80000000, // 10MHz-80MHz
 100000000, 150000000, 200000000,           // 100MHz-200MHz
 0  // Terminate data!!
};
#endif

//------------------------------------------------------------------------------
//  Control Program
//------------------------------------------------------------------------------
int main()
{
    while (true){ test_si5351();}
}

//  Help Massage
void msg_hlp (void)
{
    PRINTF(opening_msg);
    put_rn();
#if defined(RANGE_EXTENDED)
    PRINTF("0 - Check CLK0 output between 1.627KHz to 300MHz");
    put_rn();
    PRINTF("-> You are using RANGE_EXTENDED (defined in si5351a.h)");
    put_rn();
    PRINTF("-> In RANGE_EXTENDED mode, PLL sets 250MHz to 1.3GHz");
    put_rn();
    PRINTF("-> This causes high possibility to make a PARMANENT DAMAGE");
    PRINTF(" for the chip!");
    put_rn();
    PRINTF("-> Don't use this mode!!!");
#else
    PRINTF("0 - Check CLK0 output between 2.605KHz to 200MHz");
#endif
    put_rn();
    PRINTF("1 - Check CLK1 (same as #1)");
    put_rn();
    PRINTF("2 - Check CLK2 (same as #1)");
    put_rn();
    PRINTF("3 - Example CLK0:120.00MHz, CLK1:12.00MHz, CLK2:13.56MHz");
    PRINTF("-> No wat to apply a frequency compensation");
    put_rn();
    PRINTF("4 - Set desired freq. into CLK0");
    put_rn();
    PRINTF("5 - Set desired freq. into CLK0 & CLK1");
    put_rn();
    PRINTF("6 - Set desired freq. into CLK0, CLK1 & CLK2");
    put_rn();
    PRINTF("7 - CLK0: set desired center freq. then shift +/- range");
    put_rn();
    PRINTF("a - All clear registers");
    put_rn();
    PRINTF("c - Show current configration");
    put_rn();
    PRINTF("p - Compensation");
    put_rn();
    PRINTF("r - Show current resisters");
    put_rn();
    PRINTF("x - Go to special command");
    put_rn();
    PRINTF("Hit any key then return to prompt screen");
    put_rn();
    PRINTF("Reset mbed board -> please hit key <Alt>+<B>");
    put_rn();
}

// ---------- Program starts here! ---------------------------------------------
void test_si5351(void)
{
    char *ptr;
	int32_t f;

    BAUD(BAUD_RATE);
    put_rn();
    put_rn();
    PRINTF("%s [Help:'?' key]", opening_msg);
    put_rn();
#if defined(RANGE_EXTENDED)
    PRINTF("-> You are using RANGE_EXTENDED (defined in si5351a.h)");
    put_rn();
    PRINTF("-> In RANGE_EXTENDED mode, PLL sets 375MHz to 1.3GHz");
    put_rn();
    PRINTF("-> This causes high possibility to make a PARMANENT DAMAGE");
    PRINTF(" for the chip!");
    put_rn();
#endif
    clk.all_reset();
    for (;;) {
        put_r();
        PUTC('>');
        ptr = linebuf;
        get_line(ptr, sizeof(linebuf));
        put_r();
        switch (*ptr++) {
                //--------------------------------------------------------------
                //  test0
                //--------------------------------------------------------------
            case '0' :
            	clk.all_reset();
            	test(0);
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  test1
                //--------------------------------------------------------------
            case '1' :
            	clk.all_reset();
            	test(1);
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  test2
                //--------------------------------------------------------------
            case '2' :
            	clk.all_reset();
            	test(2);
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  test3
                //--------------------------------------------------------------
            case '3' :
			    clk.debug_example_clock();
			    //clk.debug_reg_print();
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  test4
                //--------------------------------------------------------------
            case '4' :
            	clk.all_reset();
                PRINTF("CLK0 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK0:%u [Hz]", clk.set_frequency(0, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                break;
                //--------------------------------------------------------------
                //  test5
                //--------------------------------------------------------------
            case '5' :
            	clk.all_reset();
                PRINTF("CLK0 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK0:%u [Hz]", clk.set_frequency(0, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                PRINTF("CLK1 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK1:%u [Hz]", clk.set_frequency(1, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                break;
                //--------------------------------------------------------------
                //  test6
                //--------------------------------------------------------------
            case '6' :
            	clk.all_reset();
                PRINTF("CLK0 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK0:%u [Hz]", clk.set_frequency(0, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                PRINTF("CLK1 %s", msg0);
                put_rn();
                PRINTF(
                "If you set CLK1 over 100MHz, you cannt set CLK2 anymore");
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK1:%u [Hz]", clk.set_frequency(1, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                PRINTF("CLK2 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK2:%u [Hz]", clk.set_frequency(2, f));
                } else {
                	PUTC('?');
                }
                put_rn();
                break;
                //--------------------------------------------------------------
                //  test7 CLK0: set desired center freq. then shift +/- range
                //--------------------------------------------------------------
            case '7' :
            	one_char = true;
            	clk.all_reset();
                PRINTF("CLK0 %s", msg0);
                put_rn();
                ptr = linebuf;
                get_line(ptr, buf_size);
                put_r();
                if (xatoi(&ptr,&f)){
                	if (f < 0){ break;}
                	PRINTF("CLK0:%u [Hz]", clk.set_frequency(0, f));
                } else {
                	PUTC('?');
                	put_r();
                }
                put_rn();
                PRINTF("Please enter sift command [Help: ?]");
                put_rn();
				while (true){
                    PRINTF("[S]>");
                    ptr = linebuf;
                    get_line(ptr, buf_size);
                    put_r();
                    switch(*ptr) {
                        case 'P' :
							PRINTF("Shift to %u [Hz]", clk.shift_freq(0, 100));
							put_rn();
                            break;
                        case 'p' :
							PRINTF("Shift to %u [Hz]", clk.shift_freq(0, 10));
							put_rn();
                            break;
                        case 'M' :
							PRINTF("Shift to %u [Hz]", clk.shift_freq(0, -100));
							put_rn();
                            break;
                        case 'm' :
							PRINTF("Shift to %u [Hz]", clk.shift_freq(0, -10));
							put_rn();
                            break;
                        case 's' :
                        	ptr++;
                        	xatoi(&ptr,&f);
                        	PRINTF("offset=%d\r\n", f);
                        	PRINTF("Shift to %u [Hz]", clk.shift_freq(0, f));
							put_rn();
                            break;
                        case '?' :
                            PRINTF("p -> +10Hz, P -> +100Hz");
                            put_rn();
                            PRINTF("m -> -10Hz, M -> -100Hz");
                            put_rn();
                            PRINTF("s -> Shift +/-x Hz (example -100)");
                            put_rn();
                            PRINTF("? -> You know this");
                            put_rn();
                            PRINTF("e -> Exit");
                            put_rn();
                            break;
                        case 'e' :
                            break;
                        default:
                            PUTC('?');
                            put_rn();
                    }
                    if (*ptr == 'e'){
                    	break;
                    }
                }
                one_char = false;
                break;
                //--------------------------------------------------------------
                //  All clear alll registers
                //--------------------------------------------------------------
            case 'a' :
            	clk.all_reset();
            	PRINTF("Cleared all of registers!\r\n");
            	break;
                //--------------------------------------------------------------
                //  Show configration
                //--------------------------------------------------------------
            case 'c' :
			    clk.debug_current_config();
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  Compensation
                //--------------------------------------------------------------
            case 'p' :
            	clk.set_frequency(0, 25000000);		// Set CLK0=10MHz
            	PRINTF(
            		"Please measure Clock0 output frequency (aound 25MHz)\r\n");
            	PRINTF("Enter your mesured data = ");
                ptr = linebuf;
                get_line(ptr, buf_size);
                if (xatoi(&ptr,&f)){
                	if (f < 0){
                		PUTC('?');
                		break;
                	}
                	PRINTF("\r%u [Hz]\r\n", f);
                	clk.f_compensation(25000000, f);
                	clk.debug_current_config();
                } else {
                	PUTC('?');
                }
            	break;
                //--------------------------------------------------------------
                //  Show resisters
                //--------------------------------------------------------------
            case 'r' :
			    clk.debug_reg_print();
                //put_rn();
                break;
                //--------------------------------------------------------------
                //  Go to special command
                //--------------------------------------------------------------
            case 'x' :
                special_command();
                break;
                //--------------------------------------------------------------
                //  help
                //--------------------------------------------------------------
            case '?' :
                msg_hlp();
                break;
                //--------------------------------------------------------------
                //    no support
                //--------------------------------------------------------------
            default:
                PUTC('?');
                put_rn();
                break;
        }
    }
}

#if defined(INCREMENT)
void test(uint8_t channel)
{
    uint32_t f_set = 4000;    // 4KHz
    double f = 0;
    uint32_t flg = 0;
    char *ptr;
    int32_t seconds = 1;

    clk.all_reset();
    f = clk.set_frequency(channel, f_set);
    clk.debug_reg_print();
    PRINTF("CLK%u = %10.6f MHz\r\n", channel, f / 1000000.0f);
    PRINTF("Please enter interval time[sec] -> ");
    ptr = linebuf;
    get_line(ptr, buf_size);
    put_r();
    xatoi(&ptr,&seconds);
    if (seconds <= 0){ seconds = 1;}
    if (seconds > 1000){ seconds = 1000;}
    PRINTF("%u[sec]\r\n", seconds);
    while(true){
        f = clk.set_frequency(channel, f_set);
        PRINTF("CLK%u = %10.6f MHz\r\n", channel, f / 1000000.0f);
        if (flg){
            f_set = f * 0.95f;
            if (f_set < 5000){
                flg = 0;
            }
        } else {
            f_set = f * 1.05f;
            if (f_set > 190000000){
                flg = 1;
            }
        }
        if (READABLE()) {
            GETC();
            return;
        }
        delay(seconds);
    }
}
#endif

#if defined(TABLE_LOOK)
void test(uint8_t channel)
{
    uint32_t f_set = 0;
    uint32_t i,j;
    double f = 0;
    char *ptr;
    int32_t seconds = 1;

    clk.all_reset();
    PRINTF("Please enter interval time[sec] -> ");
    ptr = linebuf;
    get_line(ptr, buf_size);
    put_r();
    xatoi(&ptr,&seconds);
    if (seconds <= 0){ seconds = 1;}
    if (seconds > 1000){ seconds = 1000;}
    PRINTF("%u[sec]\r\n", seconds);
    while(true){
        for (i = 0; ; i++){
        	f_set = freq_tbl[i];
        	if (f_set == 0){
        		break;
        	}
	        f = clk.set_frequency(channel, f_set);
	        PRINTF("CLK%u = %10.6f MHz\r\n", channel, f / 1000000.0f);
	        if (READABLE()) {
	            GETC();
	            return;
	        }
        	delay(seconds);
	    }
        for (j = i - 2; j > 0 ; j--){
        	f_set = freq_tbl[j];
	        f = clk.set_frequency(channel, f_set);
	        PRINTF("CLK%u = %10.6f MHz\r\n", channel, f / 1000000.0f);
	        if (READABLE()) {
	            GETC();
	            return;
	        }
            delay(seconds);
	    }
    }
}
#endif

void special_command(void)
{
	PRINTF("Not impliment yet");
	put_rn();
}

void delay(int32_t time)
{
#if MBED_MAJOR_VERSION == 2
	wait((float)time);
#elif  MBED_MAJOR_VERSION == 5
	Thread::wait(time * 1000);
#else
#error "Running on Unknown OS"
#endif
}

//  Put \r\n
void put_rn ( void )
{
    PUTC('\r');
    PUTC('\n');
}

//  Put \r
void put_r ( void )
{
    PUTC('\r');
}

//  Change string -> integer
int xatoi (char **str, int32_t *res)
{
    uint32_t val;
    int8_t c, radix, s = 0;

    while ((c = **str) == ' ') (*str)++;
    if (c == '-') {
        s = 1;
        c = *(++(*str));
    }
    if (c == '+') {
    	c = *(++(*str));
	}
    if (c == '0') {
        c = *(++(*str));
        if (c <= ' ') {
            *res = 0;
            return 1;
        }
        if (c == 'x') {
            radix = 16;
            c = *(++(*str));
        } else {
            if (c == 'b') {
                radix = 2;
                c = *(++(*str));
            } else {
                if ((c >= '0')&&(c <= '9')) {
                    radix = 8;
                } else {
                    return 0;
                }
            }
        }
    } else {
        if ((c < '1')||(c > '9')) {
            return 0;
        }
        radix = 10;
    }
    val = 0;
    while (c > ' ') {
        if (c >= 'a') c -= 0x20;
        c -= '0';
        if (c >= 17) {
            c -= 7;
            if (c <= 9) return 0;
        }
        if (c >= radix) return 0;
        val = val * radix + c;
        c = *(++(*str));
    }
    if (s) val = -val;
    *res = val;
    return 1;
}

//  Get key input data
void get_line (char *buff, int len)
{
    char c;
    int idx = 0;

    for (;;) {
        c = GETC();
        if (c == '\r') {
            buff[idx++] = c;
            break;
        }
        if ((c == '\b') && idx) {
            idx--;
            PUTC(c);
            PUTC(' ');
            PUTC(c);
        }
        if (((uint8_t)c >= ' ') && (idx < len - 1)) {
            buff[idx++] = c;
            PUTC(c);
            // Special control
            if (one_char == true){
            	if ((c == 'p') || (c == 'm') || (c == 'P') || (c == 'M')){
            		break;
            	}
            }
        }
    }
    buff[idx] = 0;
    PUTC('\n');
}