/*
 * Mbed Application program for TYBLE-16
 *
 * Copyright (c) 2018 Kenji Arai / JH1PJL
 *  http://www.page.sannet.ne.jp/kenjia/index.html
 *  http://mbed.org/users/kenjiArai/
 *      Created:    Feburary  16th, 2018
 *      Revised:    April     10th, 2018
 */

#include "mbed.h"

static uint32_t mem_range[][2] = {     // Memory access range
    { 0x00000000, 0x0003ffff }, // On-chip non-volatile memory //128 or 256KB
    { 0x20000000, 0x20007fff }, // On-chip SRAM                //16 or 32KB
    { 0x10000000, 0x1000007f }, // FICR
    { 0x10001000, 0x100010ff }, // UICR
    { 0x40000000, 0x400245ff }, // Peripheral
    { 0x50000500, 0x500007ff }  // GPIO
};

static void mem_cnfg_init( uint8_t print )
{
    uint32_t a, b, c;

    a = NRF_FICR->CODEPAGESIZE;
    b = NRF_FICR->CODESIZE;
    c = a * b;
    mem_range[0][1] = mem_range[0][0] + c -1;
    if (print) {
        printf("CODEPAGESIZE:%d, CODESIZE:%d\r\nFLASH:0x%08x-0x%08x\r\n",
                  a, b, mem_range[0][0], mem_range[0][1]);
    }
    a = NRF_FICR->NUMRAMBLOCK;
    b = NRF_FICR->SIZERAMBLOCKS;
    c = a * b;
    mem_range[1][1] = mem_range[1][0] + c -1;
    if (print) {
        printf("NUMRAMBLOCK:%d, SIZERAMBLOCKS:%d\r\nRAM:  0x%08x-0x%08x\r\n",
                  a, b, mem_range[1][0], mem_range[1][1]);
    }
}

void cpu_sys(void)
{
    uint32_t m1 = 0, m2 = 0;

    //printf("line:%d\r\n", __LINE__);
    wait(0.1f);
    m1 = SCB->CPUID;
    m2 = ( m1 >> 24 );
    if ( m2 == 0x41 ) {
        printf( "CPU = ARM " );
        wait(0.1f);
    } else {
        printf( "CPU = NOT ARM " );
    }
    m2 = ( m1 >> 4 ) & 0xfff;
    if ( m2 == 0xc20 ) {
        printf( "Cortex-M0" );
        wait(0.1f);
    } else {
        printf( "NOT Cortex-M0" );
    }
    m2 = ( m1 >> 20 ) & 0x0f;
    printf( "  Variant:%x  ", m2 );
    m2 = m1 & 0x7;
    printf( "Revision:%x\r\n", m2 );
    printf( "CPU ID: 0x%08x\r\n", m1 );
    // nRF Chip revision
    m1 = (((*((uint32_t volatile *)0xF0000FE8)) & 0x000000F0) >> 4);
    switch (m1) {
        case 1:     // revision 1
            m2 = 1;
            break;
        case 4:     // revision 2
            m2 = 2;
            break;
        case 7:
        case 8:
        case 9:     // revision 3
            m2 = 3;
            break;
        default:
            m2 = 0;
            break;
    }
    if (m2) {
        printf( "nRF Revision: %d\r\n", m2 );
    } else {
        printf( "nRF Revision: Unknown\r\n" );
    }
    // Firmware
    m1 = NRF_UICR->FWID & 0xffff;
    printf( "Firmware ID: 0x%04x\r\n", m1 );
    // System Clock
    m1 = NRF_UICR->XTALFREQ & 0xff;
    printf( "System clock by " );
    if (m1) {
        printf( "XTAL:16MHz\r\n" );
    } else {
        printf( "XTAL:32MHz\r\n" );
    }
    m1 = NRF_CLOCK->LFCLKSRCCOPY & 0x3;
    printf( "LFCLK Source=32.768 kHz " );
    switch (m1) {
        case 0:     // revision 1
            printf( "RC oscillator" );
            break;
        case 1:     // revision 1
            printf( "crystal oscillator" );
            break;
        case 2:      // revision 1
            printf( "synthesized from HFCLK" );
            break;
        default:
            printf( "unknown" );
            break;
    }
    printf("\r\n");
    // FLASH & RAM
    mem_cnfg_init(1);
}

bool compile_condition(void)
{
    uint32_t m1 = 0, m2 = 0;

    // ARM
    m1 = SCB->CPUID;
    m2 = ( m1 >> 24 );
    if ( m2 != 0x41 ) {
        return false;
    }
    // M0
    m2 = ( m1 >> 4 ) & 0xfff;
    if ( m2 != 0xc20 ) {
        return false;
    }
    // FLASH
    m1 = NRF_FICR->CODEPAGESIZE;
    if (m1 != 1024) {
        return false;
    }
    m1 = NRF_FICR->CODESIZE;
    if (m1 != 256) {
        return false;
    }
    // RAM
    m1 = NRF_FICR->NUMRAMBLOCK;
    if (m1 != 4) {
        return false;
    }
    m1 = NRF_FICR->SIZERAMBLOCKS;
    if (m1 != 8192) {
        return false;
    }
    // 32MHz Xtal
    m1 = NRF_UICR->XTALFREQ & 0xff;
    if (m1) {
        return false;   // Not 32MHz XTAL
    }
    // LF = internal RC
    m1 = NRF_CLOCK->LFCLKSRCCOPY & 0x3;
    if (m1 != 0) {
        printf("Looks TY51822r3 board\r\n");
        return false;   // Not RC
    }
    printf("Looks TYBLE16 board\r\n");
    return true;
}
