initial commit
This commit is contained in:
@@ -0,0 +1,225 @@
|
||||
How to Regenerate Existing BSPs
|
||||
===============================
|
||||
After making changes to the BSP source files (```am_bsp.h```, ```am_bsp.c```, and ```bsp_pins.src```) you will still need to ensure that the ```libam_bsp.a``` archive is updated to reflect this (if this file exists then the build process simply uses it instead of compiling BSP sources). The simplest way is to navigate to the root of this repo and run ```./common/tools_sfe/scripts/regen_bsps.sh```
|
||||
|
||||
**all these automated methods rely on this repo being placed in the root directory of the AmbiqSuite SDK (alternately you may employ an environment variable {$AMSDK} pointing at the root) and having the prerequisite tools available**
|
||||
|
||||
How to Generate New BSP Files
|
||||
=============================
|
||||
|
||||
A Board Support Package is designed to provide a uniform interface to the hardware capabilities across boards, thus enabling users to easily identify what hardware is being used and increasing the compatibility of example applications.
|
||||
|
||||
To do so the BSP provides a listing of pin names and corresponding pin configurations, as well as several uniform API calls.
|
||||
|
||||
|
||||
am_bsp_pins.h + am_bsp_pins.c
|
||||
=============================
|
||||
|
||||
These files are used to create named configurations (and pins numbers) that represent what's on the board. The files are automatically generated by the ```pinconfig.py``` script. This uses pin definitions that the user sets up in the ```bsp_pins.src``` file which helps reduce maintenance effort. An example usage is (from the root directory of this repo):
|
||||
|
||||
```bash
|
||||
python common/bsp_pinconfig/pinconfig.py ${board}/bsp/bsp_pins.src ${selector} > ${board}/bsp/am_bsp_pins.${selector}
|
||||
```
|
||||
Where ```${board}``` is the directory for the board whose BSP is being generated and ```${selector}``` is one of ```c``` or ```h``` (which tells the script which file to generate)
|
||||
|
||||
|
||||
am_bsp.h + am_bsp.c
|
||||
===================
|
||||
|
||||
This compilation unit uses the pin definitions (above) to describe the common interface. It has a standard structure and contents, but it is also possible to add additional board-specific macros.
|
||||
|
||||
**The Header**
|
||||
The header is standardized and changes to it should be minimal
|
||||
Includes:
|
||||
- License + Copyright
|
||||
- Include guards (opening)
|
||||
- Includes
|
||||
- stdint
|
||||
- stdbool
|
||||
- am_mcu_apollo
|
||||
- am_bsp_pins
|
||||
- am_devices_led
|
||||
- am_devices_button
|
||||
- C++ guards (opening)
|
||||
|
||||
``` c
|
||||
//*****************************************************************************
|
||||
//
|
||||
// am_bsp.h
|
||||
//! @file
|
||||
//!
|
||||
//! @brief Functions to aid with configuring the GPIOs.
|
||||
//!
|
||||
//! @addtogroup BSP Board Support Package (BSP)
|
||||
//! @addtogroup apollo3_fpga_bsp BSP for the Apollo3 Hotshot FPGA
|
||||
//! @ingroup BSP
|
||||
//! @{
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2019, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision v2.0.0 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef AM_BSP_H
|
||||
#define AM_BSP_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "am_mcu_apollo.h"
|
||||
#include "am_bsp_pins.h"
|
||||
|
||||
//
|
||||
// Make individual includes to not require full port before usage.
|
||||
//#include "am_devices.h"
|
||||
//
|
||||
#include "am_devices_led.h"
|
||||
#include "am_devices_button.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Begin User Modifiable Area
|
||||
//
|
||||
//*****************************************************************************
|
||||
```
|
||||
|
||||
**The User Modifiable Area**
|
||||
Contents of this section are free reign. Nothing is required. Possible elements include:
|
||||
- Aliases for pin names
|
||||
- Definitions for HW not captured by the bsp_pins.src file
|
||||
|
||||
**Print Interface Area**
|
||||
Todo: explain what this area is about
|
||||
```c
|
||||
//*****************************************************************************
|
||||
//
|
||||
// End User Modifiable Area
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Print interface type
|
||||
//
|
||||
//*****************************************************************************
|
||||
#define AM_BSP_PRINT_INFC_NONE 0
|
||||
#define AM_BSP_PRINT_INFC_SWO 1
|
||||
#define AM_BSP_PRINT_INFC_UART0 2
|
||||
#define AM_BSP_PRINT_INFC_BUFFERED_UART0 3
|
||||
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
//! Structure containing UART configuration information while it is powered down.
|
||||
//
|
||||
//*****************************************************************************
|
||||
typedef struct
|
||||
{
|
||||
bool bSaved;
|
||||
uint32_t ui32TxPinNum;
|
||||
uint32_t ui32TxPinCfg;
|
||||
}
|
||||
am_bsp_uart_pwrsave_t;
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External data definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern am_bsp_uart_pwrsave_t am_bsp_uart_pwrsave[AM_REG_UART_NUM_MODULES];
|
||||
|
||||
```
|
||||
|
||||
**The API Area**
|
||||
This area declares standard bsp functions that are used across AmbiqSuite examples. It is best to attempt to implement these functions in ```am_bsp.c```.
|
||||
```c
|
||||
//*****************************************************************************
|
||||
//
|
||||
// External function definitions.
|
||||
//
|
||||
//*****************************************************************************
|
||||
extern void am_bsp_low_power_init(void);
|
||||
extern void am_bsp_iom_pins_enable(uint32_t ui32Module, am_hal_iom_mode_e eIOMMode);
|
||||
extern void am_bsp_iom_pins_disable(uint32_t ui32Module, am_hal_iom_mode_e eIOMMode);
|
||||
extern void am_bsp_mspi_pins_enable(am_hal_mspi_device_e eMSPIDevice);
|
||||
extern void am_bsp_mspi_pins_disable(am_hal_mspi_device_e eMSPIDevice);
|
||||
|
||||
extern void am_bsp_ios_pins_enable(uint32_t ui32Module, uint32_t ui32IOSMode); // SparkFun Edge does not expose IO Slave Clock signal, so hiding these functions
|
||||
extern void am_bsp_ios_pins_disable(uint32_t ui32Module, uint32_t ui32IOSMode);
|
||||
|
||||
extern void am_bsp_debug_printf_enable(void);
|
||||
extern void am_bsp_debug_printf_disable(void);
|
||||
|
||||
#ifdef AM_BSP_GPIO_ITM_SWO
|
||||
extern void am_bsp_itm_printf_enable(void);
|
||||
#else
|
||||
extern void am_bsp_itm_printf_enable(uint32_t ui32Pin, am_hal_gpio_pincfg_t sPincfg);
|
||||
#endif
|
||||
extern void am_bsp_itm_string_print(char *pcString);
|
||||
extern void am_bsp_itm_printf_disable(void);
|
||||
|
||||
extern void am_bsp_uart_string_print(char *pcString);
|
||||
extern void am_bsp_uart_printf_enable(void);
|
||||
extern void am_bsp_uart_printf_enable_custom(const am_hal_uart_config_t* p_config);
|
||||
extern void am_bsp_uart_printf_disable(void);
|
||||
|
||||
extern void am_bsp_buffered_uart_printf_enable(void);
|
||||
extern void am_bsp_buffered_uart_service(void);
|
||||
|
||||
extern uint32_t am_bsp_com_uart_transfer(const am_hal_uart_transfer_t *psTransfer);
|
||||
```
|
||||
|
||||
**The Footer**
|
||||
The footer just wraps it all up
|
||||
```c
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // AM_BSP_H
|
||||
//*****************************************************************************
|
||||
//
|
||||
// End Doxygen group.
|
||||
//! @}
|
||||
//
|
||||
//*****************************************************************************
|
||||
```
|
||||
+653
@@ -0,0 +1,653 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# *****************************************************************************
|
||||
#
|
||||
# pinconfig.py
|
||||
#
|
||||
# @brief Script for generating a BSP pin file.
|
||||
|
||||
# *****************************************************************************
|
||||
|
||||
# *****************************************************************************
|
||||
#
|
||||
# Copyright (c) 2019, Ambiq Micro
|
||||
# All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright notice,
|
||||
# this list of conditions and the following disclaimer.
|
||||
#
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in the
|
||||
# documentation and/or other materials provided with the distribution.
|
||||
#
|
||||
# 3. Neither the name of the copyright holder nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from this
|
||||
# software without specific prior written permission.
|
||||
#
|
||||
# Third party software included in this distribution is subject to the
|
||||
# additional license terms as defined in the /docs/licenses directory.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
# AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
# ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
# LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
# CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
# SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
# INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
# CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
# ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
# This is part of revision 2.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
|
||||
#
|
||||
# *****************************************************************************
|
||||
|
||||
# *****************************************************************************
|
||||
# Imported modules
|
||||
# *****************************************************************************
|
||||
import argparse
|
||||
import textwrap
|
||||
import os.path
|
||||
import rsonlite
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
# Templates
|
||||
# *****************************************************************************
|
||||
filetemplateC = '''
|
||||
//*****************************************************************************
|
||||
//
|
||||
// {filename}
|
||||
//! @file
|
||||
//!
|
||||
//! @brief BSP pin configuration definitions.
|
||||
//!
|
||||
//! @addtogroup BSP Board Support Package (BSP)
|
||||
//! @addtogroup apollo3_evb_bsp BSP for the Apollo3 Engineering Board
|
||||
//! @ingroup BSP
|
||||
//! @{{
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2019, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#include "am_bsp.h"
|
||||
{pin_defs}
|
||||
//*****************************************************************************
|
||||
//
|
||||
// End Doxygen group.
|
||||
//! @}}
|
||||
//
|
||||
//*****************************************************************************
|
||||
'''.strip()
|
||||
|
||||
|
||||
filetemplateH = '''
|
||||
//*****************************************************************************
|
||||
//
|
||||
// {filename}
|
||||
//! @file
|
||||
//!
|
||||
//! @brief BSP pin configuration definitions.
|
||||
//!
|
||||
//! @addtogroup BSP Board Support Package (BSP)
|
||||
//! @addtogroup apollo3_bsp BSP for the Apollo3 EVB.
|
||||
//! @ingroup BSP
|
||||
//! @{{
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// Copyright (c) 2019, Ambiq Micro
|
||||
// All rights reserved.
|
||||
//
|
||||
// Redistribution and use in source and binary forms, with or without
|
||||
// modification, are permitted provided that the following conditions are met:
|
||||
//
|
||||
// 1. Redistributions of source code must retain the above copyright notice,
|
||||
// this list of conditions and the following disclaimer.
|
||||
//
|
||||
// 2. Redistributions in binary form must reproduce the above copyright
|
||||
// notice, this list of conditions and the following disclaimer in the
|
||||
// documentation and/or other materials provided with the distribution.
|
||||
//
|
||||
// 3. Neither the name of the copyright holder nor the names of its
|
||||
// contributors may be used to endorse or promote products derived from this
|
||||
// software without specific prior written permission.
|
||||
//
|
||||
// Third party software included in this distribution is subject to the
|
||||
// additional license terms as defined in the /docs/licenses directory.
|
||||
//
|
||||
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
// POSSIBILITY OF SUCH DAMAGE.
|
||||
//
|
||||
// This is part of revision 2.2.0-hotfix-2.2.1 of the AmbiqSuite Development Package.
|
||||
//
|
||||
//*****************************************************************************
|
||||
|
||||
#ifndef {headerdef}
|
||||
#define {headerdef}
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "am_mcu_apollo.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{{
|
||||
#endif
|
||||
{pin_defs}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}}
|
||||
#endif
|
||||
|
||||
#endif // {headerdef}
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// End Doxygen group.
|
||||
//! @}}
|
||||
//
|
||||
//*****************************************************************************
|
||||
'''.strip()
|
||||
|
||||
|
||||
sectiontemplate = '''
|
||||
|
||||
//*****************************************************************************
|
||||
//
|
||||
// {pin_descr}
|
||||
//
|
||||
//*****************************************************************************
|
||||
'''.strip()
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
#
|
||||
# Globals
|
||||
#
|
||||
# *****************************************************************************
|
||||
|
||||
# *****************************************************************************
|
||||
#
|
||||
# Command line support.
|
||||
#
|
||||
# *****************************************************************************
|
||||
def read_arguments():
|
||||
parser = argparse.ArgumentParser()
|
||||
|
||||
parser.add_argument('input', help='input src file name')
|
||||
parser.add_argument('CorH', help='C to create C file, H to create H file',
|
||||
choices=['C','H','c','h'])
|
||||
parser.add_argument('-g', '--guard', dest='headerdef', required=False, default='AM_BSP_PINS_H', help='optional string to use for header include guards - defaults to AM_BSP_PINS_H')
|
||||
parser.add_argument('-p', '--prefix', dest='prefix', required=False, default='AM_BSP_GPIO', help='optional string with which to prefix names - defaults to AM_BSP')
|
||||
parser.add_argument('-b', '--bgaguard', dest='bgaguard', required=False, default=None, help='if provided this script will place preprocessor guards around pins that only exist on the BGA package using the provided string as the check value')
|
||||
|
||||
return parser.parse_args()
|
||||
|
||||
# *****************************************************************************
|
||||
# parse_input()
|
||||
# *****************************************************************************
|
||||
def parse_input(filename):
|
||||
'''
|
||||
Simple wrapper to pull an rsonlite list from given file.
|
||||
'''
|
||||
with open(filename) as f:
|
||||
data = f.read()
|
||||
return rsonlite.loads(data)
|
||||
|
||||
# *****************************************************************************
|
||||
# list_to_dict()
|
||||
# *****************************************************************************
|
||||
def list_to_dict(L):
|
||||
'''
|
||||
rsonlite loads data from the rson files as a very-nested list. This
|
||||
function converts that list to a set of nested dictionaries. At each level,
|
||||
the dictionary keys correspond to the "headings", and the dictionary values
|
||||
are a list of the items under that "heading". Values assigned by
|
||||
equals-sign statements are (unfortunately) also converted to (key, list)
|
||||
pairs, the same way that subheadings are.
|
||||
'''
|
||||
if len(L) == 1:
|
||||
return L[0]
|
||||
else:
|
||||
D = dict()
|
||||
for x in L:
|
||||
if x[0] in D:
|
||||
D[x[0]] = D[x[0]] + [list_to_dict(x[1])]
|
||||
else:
|
||||
D[x[0]] = [list_to_dict(x[1])]
|
||||
return D
|
||||
|
||||
# *****************************************************************************
|
||||
# get_val()
|
||||
# *****************************************************************************
|
||||
def get_val(name, D):
|
||||
'''
|
||||
get_val is just a helper to make it more obvious when you are trying to get
|
||||
at an equals-sign-assigned value from the rson file dictionary.
|
||||
'''
|
||||
if name not in D:
|
||||
return "ERROR: {} VALUE MISSING".format(name)
|
||||
else:
|
||||
return D[name][0]
|
||||
|
||||
# *****************************************************************************
|
||||
# get_pinobj()
|
||||
# *****************************************************************************
|
||||
def get_pinobj(filename):
|
||||
'''
|
||||
Given the filename of an 'src' file, this function will return a 'pin'
|
||||
object corresponding to the fields described in the src file.
|
||||
'''
|
||||
|
||||
# Set the location for the supplementary files (infoblock, base addresses, etc.)
|
||||
srcdir = os.path.dirname(filename)
|
||||
|
||||
# Read in the contents of the src file, and use the rsonlite library to
|
||||
# parse them into a list.
|
||||
rson_data = parse_input(filename)
|
||||
|
||||
# Convert the list to a dictionary.
|
||||
rson_dict = list_to_dict(rson_data)
|
||||
|
||||
# Convert the dictionary to a block object, which will create field
|
||||
# objects as necessary. Return this object to the caller.
|
||||
return pinobj(rson_dict)
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
# pinfields
|
||||
# *****************************************************************************
|
||||
class pinfields:
|
||||
def __init__(self, pindict):
|
||||
|
||||
self.name = ''
|
||||
self.desc = ''
|
||||
self.pinnum = 0
|
||||
self.powersw = ''
|
||||
self.pullup = ''
|
||||
self.func_sel = ''
|
||||
self.drvstrength = 0
|
||||
self.intdir = 0
|
||||
self.GPOutcfg = ''
|
||||
self.GPinput = ''
|
||||
self.GPRdZero = ''
|
||||
self.IOMnum = ''
|
||||
self.CEnum = ''
|
||||
self.CEpol = ''
|
||||
self.bIomMSPIn = ''
|
||||
|
||||
intnotgiven = 65535
|
||||
strnotgiven = 'none_given'
|
||||
|
||||
if 'name' in pindict:
|
||||
self.name = get_val('name', pindict)
|
||||
else:
|
||||
self.name = strnotgiven
|
||||
|
||||
if 'desc' in pindict:
|
||||
self.desc = get_val('desc', pindict)
|
||||
else:
|
||||
self.desc = strnotgiven
|
||||
|
||||
if 'pinnum' in pindict:
|
||||
self.pinnum = int(get_val('pinnum', pindict))
|
||||
else:
|
||||
self.pinnum = intnotgiven
|
||||
|
||||
if 'powersw' in pindict:
|
||||
self.powersw = get_val('powersw', pindict)
|
||||
else:
|
||||
self.powersw = strnotgiven
|
||||
|
||||
if 'pullup' in pindict:
|
||||
self.pullup = get_val('pullup', pindict)
|
||||
else:
|
||||
self.pullup = strnotgiven
|
||||
|
||||
if 'func_sel' in pindict:
|
||||
self.func_sel = get_val('func_sel', pindict)
|
||||
else:
|
||||
self.func_sel = strnotgiven
|
||||
|
||||
if 'drvstrength' in pindict:
|
||||
self.drvstrength = int(get_val('drvstrength', pindict))
|
||||
else:
|
||||
self.drvstrength = intnotgiven
|
||||
|
||||
if 'intdir' in pindict:
|
||||
self.intdir = get_val('intdir', pindict)
|
||||
else:
|
||||
self.intdir = strnotgiven
|
||||
|
||||
if 'GPOutcfg' in pindict:
|
||||
self.GPOutcfg = get_val('GPOutcfg', pindict)
|
||||
else:
|
||||
self.GPOutcfg = strnotgiven
|
||||
|
||||
if 'GPinput' in pindict:
|
||||
self.GPinput = get_val('GPinput', pindict)
|
||||
else:
|
||||
self.GPinput = strnotgiven
|
||||
|
||||
if 'GPRdZero' in pindict:
|
||||
self.GPRdZero = get_val('GPRdZero', pindict)
|
||||
else:
|
||||
self.GPRdZero = strnotgiven
|
||||
|
||||
if 'IOMnum' in pindict:
|
||||
self.IOMnum = get_val('IOMnum', pindict)
|
||||
else:
|
||||
self.IOMnum = strnotgiven
|
||||
|
||||
if 'CEnum' in pindict:
|
||||
self.CEnum = get_val('CEnum', pindict)
|
||||
else:
|
||||
self.CEnum = strnotgiven
|
||||
|
||||
if 'CEpol' in pindict:
|
||||
self.CEpol = get_val('CEpol', pindict)
|
||||
else:
|
||||
self.CEpol = strnotgiven
|
||||
|
||||
if 'bIomMSPIn' in pindict:
|
||||
self.bIomMSPIn = get_val('bIomMSPIn', pindict)
|
||||
else:
|
||||
self.bIomMSPIn = strnotgiven
|
||||
|
||||
#
|
||||
# Check for an invalid field in the src file. If so, report it.
|
||||
#
|
||||
for fld in pindict:
|
||||
if fld != 'name' and \
|
||||
fld != 'desc' and \
|
||||
fld != 'pinnum' and \
|
||||
fld != 'powersw' and \
|
||||
fld != 'pullup' and \
|
||||
fld != 'func_sel' and \
|
||||
fld != 'drvstrength' and \
|
||||
fld != 'intdir' and \
|
||||
fld != 'GPOutcfg' and \
|
||||
fld != 'GPinput' and \
|
||||
fld != 'GPRdZero' and \
|
||||
fld != 'IOMnum' and \
|
||||
fld != 'CEnum' and \
|
||||
fld != 'CEpol' and \
|
||||
fld != 'bIomMSPIn':
|
||||
print("Invalid field: '%s.%s'" % (self.name, fld))
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
# pinobj
|
||||
# *****************************************************************************
|
||||
class pinobj:
|
||||
def __init__(self, pindict):
|
||||
self.name = 'name'
|
||||
self.srcver=0x0000
|
||||
self.pins = []
|
||||
|
||||
if 'pinsrc_ver' in pindict:
|
||||
# Convert rson list object to int
|
||||
ssrcver = pindict["pinsrc_ver"][0]
|
||||
if ssrcver[0:2].lower() == "0x":
|
||||
self.srcver = int(ssrcver,16)
|
||||
else:
|
||||
self.srcver = int(ssrcver,10)
|
||||
else:
|
||||
# If no src file version given, assume version for Apollo3
|
||||
self.srcver = 0x0003
|
||||
|
||||
# Run through all the pins given in the src file
|
||||
if 'pin' in pindict:
|
||||
#
|
||||
# Run through the 'pin' list.
|
||||
#
|
||||
for pin in pindict['pin']:
|
||||
self.pins.append(pinfields(pin))
|
||||
|
||||
# *****************************************************************************
|
||||
# write_Cfiles()
|
||||
# *****************************************************************************
|
||||
|
||||
def write_Cfiles(pinobj, bCreateC):
|
||||
#
|
||||
# Initializations
|
||||
#
|
||||
intnotgiven = 65535
|
||||
strnotgiven = 'none_given'
|
||||
strCfile = ''
|
||||
strHfile = ''
|
||||
|
||||
for pin in pinobj.pins:
|
||||
sectiondesc = pin.name.strip() + ' pin'
|
||||
if pin.desc == strnotgiven:
|
||||
sectiondesc += '.'
|
||||
else:
|
||||
sectiondesc += ': ' + pin.desc.strip()
|
||||
if sectiondesc[-1] != '.':
|
||||
sectiondesc += '.'
|
||||
strCfile += '\n'
|
||||
strCfile += sectiontemplate.format(pin_descr=sectiondesc)
|
||||
strCfile += '\n'
|
||||
strHfile += '\n'
|
||||
strHfile += sectiontemplate.format(pin_descr=sectiondesc)
|
||||
strHfile += '\n'
|
||||
|
||||
bga = False
|
||||
if ( 30 <= pin.pinnum <=38 ) or ( 42 <= pin.pinnum <= 43 ) or ( 45 <= pin.pinnum <= 46 ):
|
||||
bga = True
|
||||
|
||||
if pin.pinnum != intnotgiven:
|
||||
if bga and args.bgaguard:
|
||||
strHfile += '#if defined (' + args.bgaguard + ')\n'
|
||||
|
||||
strHfile += '#define ' + args.prefix + '_%-20s\t' % pin.name + '%d\n' % pin.pinnum
|
||||
strHfile += 'extern const am_hal_gpio_pincfg_t g_' + args.prefix + '_%s;\n' % pin.name
|
||||
|
||||
if bga and args.bgaguard:
|
||||
strHfile += '#endif // ' + args.bgaguard + '\n'
|
||||
#strHfile += '\n'
|
||||
|
||||
if bga and args.bgaguard:
|
||||
strCfile += '#if defined (' + args.bgaguard + ')\n'
|
||||
|
||||
strCfile += 'const am_hal_gpio_pincfg_t g_' + args.prefix + '_%s =\n' % pin.name
|
||||
strCfile += '{\n'
|
||||
strCfile += '%-25s' % ' .uFuncSel' + '= %s,\n' % pin.func_sel
|
||||
|
||||
if pin.powersw != strnotgiven:
|
||||
if (pin.powersw.lower() == "vdd") or \
|
||||
(pin.powersw.lower() == "vss") or \
|
||||
(pin.powersw.lower() == "none"):
|
||||
strCfile += '%-25s' % ' .ePowerSw' + '= AM_HAL_GPIO_PIN_POWERSW_%s,\n' % pin.powersw.upper()
|
||||
else:
|
||||
strCfile += '%-25s' % ' .ePowerSw' + '= %s,\n' % pin.powersw
|
||||
|
||||
if pin.pullup != strnotgiven:
|
||||
if (pin.pullup.lower() == "none") or \
|
||||
(pin.pullup.lower() == "weak") or \
|
||||
(pin.pullup.lower() == "pulldown") or \
|
||||
(pin.pullup.lower() == "1_5k") or \
|
||||
(pin.pullup.lower() == "6k") or \
|
||||
(pin.pullup.lower() == "12k") or \
|
||||
(pin.pullup.lower() == "24k"):
|
||||
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%s,\n' % pin.pullup.upper()
|
||||
elif (pin.pullup == "1_5") or \
|
||||
(pin.pullup == "6") or \
|
||||
(pin.pullup == "12") or \
|
||||
(pin.pullup == "24"):
|
||||
strCfile += '%-25s' % ' .ePullup' + '= AM_HAL_GPIO_PIN_PULLUP_%sK,\n' % pin.pullup
|
||||
else:
|
||||
strCfile += '%-25s' % ' .ePullup' + '= %s,\n' % pin.pullup
|
||||
|
||||
if pin.drvstrength != intnotgiven:
|
||||
if (pin.drvstrength != 2) and (pin.drvstrength != 4) and \
|
||||
(pin.drvstrength != 8) and (pin.drvstrength != 12):
|
||||
pin.drvstrength = 2
|
||||
strCfile += '%-25s' % ' .eDriveStrength' + '= AM_HAL_GPIO_PIN_DRIVESTRENGTH_%dMA,\n' % pin.drvstrength
|
||||
|
||||
if pin.GPOutcfg != strnotgiven:
|
||||
if (pin.GPOutcfg.lower() == "disable") or \
|
||||
(pin.GPOutcfg.lower() == "pushpull") or \
|
||||
(pin.GPOutcfg.lower() == "opendrain") or \
|
||||
(pin.GPOutcfg.lower() == "tristate"):
|
||||
strCfile += '%-25s' % ' .eGPOutcfg' + '= AM_HAL_GPIO_PIN_OUTCFG_%s,\n' % pin.GPOutcfg.upper()
|
||||
else:
|
||||
strCfile += '%-25s' % ' .eGPOutcfg' + '= %s,\n' % pin.GPOutcfg
|
||||
|
||||
if pin.GPinput != strnotgiven:
|
||||
if (pin.GPinput.lower() == "true"):
|
||||
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_ENABLE,\n'
|
||||
elif (pin.GPinput.lower() == "false"):
|
||||
strCfile += '%-25s' % ' .eGPInput' + '= AM_HAL_GPIO_PIN_INPUT_NONE,\n'
|
||||
else:
|
||||
strCfile += '%-25s' % ' .eGPInput' + '= %s,\n' % pin.GPinput
|
||||
|
||||
if pin.GPRdZero != strnotgiven:
|
||||
if (pin.GPRdZero.lower() == "true") or \
|
||||
(pin.GPRdZero.lower() == "zero"):
|
||||
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_ZERO,\n'
|
||||
elif (pin.GPRdZero.lower() == "false") or \
|
||||
(pin.GPRdZero.lower() == "readpin"):
|
||||
strCfile += '%-25s' % ' .eGPRdZero' + '= AM_HAL_GPIO_PIN_RDZERO_READPIN,\n'
|
||||
else:
|
||||
strCfile += '%-25s' % ' .eGPRdZero' + '= %s,\n' % pin.GPRdZero
|
||||
|
||||
if pin.intdir != strnotgiven:
|
||||
if (pin.intdir.lower() == "none") or \
|
||||
(pin.intdir.lower() == "lo2hi") or \
|
||||
(pin.intdir.lower() == "hi2lo") or \
|
||||
(pin.intdir.lower() == "either"):
|
||||
strCfile += '%-25s' % ' .eIntDir' + '= AM_HAL_GPIO_PIN_INTDIR_%s,\n' % pin.intdir.upper()
|
||||
else:
|
||||
strCfile += '%-25s' % ' .eIntDir' + '= %s,\n' % pin.intdir
|
||||
|
||||
if (pin.bIomMSPIn != strnotgiven):
|
||||
if pinobj.srcver >= 0x0003:
|
||||
if ((pin.bIomMSPIn[0:1].lower() != "m") and (pin.bIomMSPIn != "0")):
|
||||
bIom = 1
|
||||
else:
|
||||
bIom = 0
|
||||
strCfile += '%-25s' % ' .bIomMSPIn' + '= %d,\n' % bIom
|
||||
|
||||
if pin.IOMnum != strnotgiven:
|
||||
strCfile += '%-25s' % ' .uIOMnum' + '= %s,\n' % str(pin.IOMnum)
|
||||
|
||||
if pin.CEnum != strnotgiven:
|
||||
strCfile += '%-25s' % ' .uNCE' + '= %s,\n' % str(pin.CEnum)
|
||||
|
||||
# Create the define
|
||||
strtmp = '#define ' + args.prefix + '_%s_CHNL' % (pin.name)
|
||||
strHfile += '%-40s' % strtmp + '%s\n' % str((pin.CEnum))
|
||||
|
||||
if pin.CEpol != strnotgiven:
|
||||
if (pin.CEpol.lower() == "low") or \
|
||||
(pin.CEpol.lower() == "high"):
|
||||
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_ACTIVE%s,\n' % pin.CEpol.upper()
|
||||
elif (pin.CEpol.lower() == "activelow") or \
|
||||
(pin.CEpol.lower() == "activehigh"):
|
||||
strCfile += '%-25s' % ' .eCEpol' + '= AM_HAL_GPIO_PIN_CEPOL_%s,\n' % pin.CEpol.upper()
|
||||
else:
|
||||
strCfile += '%-25s' % ' .eCEpol' + '= %s,\n' % pin.CEpol
|
||||
|
||||
# Eliminate the last comma from the last structure member
|
||||
strCfile = strCfile[:-2]
|
||||
|
||||
# Terminate the structure
|
||||
strCfile += '\n};\n'
|
||||
|
||||
if bga and args.bgaguard:
|
||||
strCfile += '#endif // ' + args.bgaguard + '\n'
|
||||
|
||||
if bCreateC:
|
||||
#
|
||||
# Develop and print the C file
|
||||
#
|
||||
S = filetemplateC.format(filename='am_bsp_pins.c', pin_defs=strCfile);
|
||||
print(S)
|
||||
else:
|
||||
#
|
||||
# Develop and print the H file
|
||||
#
|
||||
S = filetemplateH.format(filename='am_bsp_pins.h',
|
||||
pin_defs=strHfile,
|
||||
headerdef=args.headerdef)
|
||||
print(S)
|
||||
|
||||
|
||||
# *****************************************************************************
|
||||
#
|
||||
# main
|
||||
#
|
||||
# *****************************************************************************
|
||||
if __name__ == '__main__':
|
||||
|
||||
#
|
||||
# Get arguments.
|
||||
# First arg is a string for the input .src file.
|
||||
# Second arg must be a C or H.
|
||||
#
|
||||
args = read_arguments()
|
||||
if args.CorH.upper() == 'C':
|
||||
bCreateC = True
|
||||
else:
|
||||
bCreateC = False
|
||||
|
||||
pinobj = get_pinobj(args.input)
|
||||
|
||||
#
|
||||
# pinobj.pins is a list of the pins
|
||||
#
|
||||
write_Cfiles(pinobj, bCreateC)
|
||||
@@ -0,0 +1,294 @@
|
||||
'''
|
||||
rsonlite -- an extremely lightweight version of rson.
|
||||
|
||||
Copyright (c) 2012, Patrick Maupin
|
||||
|
||||
License :: MIT
|
||||
|
||||
http://pypi.python.org/pypi/rsonlite
|
||||
http://code.google.com/p/rson/
|
||||
|
||||
rsonlite makes it easy to build a file parser for
|
||||
declarative hierarchical data structures using indentation.
|
||||
(Spaces only, tabs not considered indentation.)
|
||||
|
||||
The only special characters are '#', '=', and indentation:
|
||||
|
||||
- Indentation denotes a key/value relationship. The
|
||||
value is indented from the key.
|
||||
|
||||
- = Denotes the start of a free-format string. These
|
||||
strings can contain '=' and '#' characters, and
|
||||
even be multi-line, but every line in the string
|
||||
must be indented past the initial equal sign.
|
||||
|
||||
Note that, for multi-line strings, indentation is
|
||||
preserved but normalized such that at least one
|
||||
line starts in the left column. This allows for
|
||||
restructuredText or Python code to exist inside
|
||||
multi-line strings.
|
||||
|
||||
- # Denotes the start of a line comment, when not
|
||||
inside a free-format string.
|
||||
|
||||
The only Python objects resulting from parsing a file
|
||||
with rsonlite are:
|
||||
|
||||
- strings:
|
||||
free-format strings (described above) can
|
||||
contain any character, but the whitespace
|
||||
before/after the string may be stripped.
|
||||
|
||||
Regular strings must fit on a single line and
|
||||
cannot contain '=' or '#' characters.
|
||||
|
||||
Regular strings may be used as keys in key/value
|
||||
pairs, but free-format strings may not.
|
||||
|
||||
- tuple:
|
||||
A key/value pair is a two-element tuple. The key is always
|
||||
a string. The value is always a list.
|
||||
|
||||
- list:
|
||||
The top level is a list, and the value element of every
|
||||
key/value pair tuple is also a list. Lists can contain
|
||||
strings and key/value pair tuples.
|
||||
'''
|
||||
|
||||
import re
|
||||
|
||||
version = __version__ = '0.1.0'
|
||||
|
||||
# Our attempt at rationalizing differences between Python 2 and Python 3.
|
||||
|
||||
try:
|
||||
basestring
|
||||
except NameError:
|
||||
basestring = str
|
||||
class unicode: pass
|
||||
|
||||
# Use OrderedDict if it's available
|
||||
|
||||
try:
|
||||
from collections import OrderedDict as stddict
|
||||
except ImportError:
|
||||
stddict = dict
|
||||
|
||||
# Splits the entire file into probable tokens.
|
||||
|
||||
splitter = re.compile('(\n *|=[^\n]*|#[^\n]*|[^\n#=]+)').findall
|
||||
|
||||
class RsonToken(str):
|
||||
''' A string that may be annotated with location information
|
||||
'''
|
||||
def __new__(cls, s, line, col):
|
||||
self = str.__new__(cls, s)
|
||||
self.line = line
|
||||
self.col = col
|
||||
return self
|
||||
def __add__(self, other):
|
||||
return RsonToken(str(self) + other, self.line, self.col)
|
||||
|
||||
|
||||
def gettoks(source):
|
||||
''' Convert string into (probable) tokens
|
||||
(some tokens may be recombined later, e.g. if they
|
||||
contain # or = but were already inside a string)
|
||||
'''
|
||||
|
||||
# Use "regular" strings, whatever that means for the given Python
|
||||
if isinstance(source, unicode):
|
||||
source = source.encode('utf-8', 'replace')
|
||||
elif not isinstance(source, basestring):
|
||||
source = source.decode('utf-8', 'replace')
|
||||
|
||||
# Convert MS-DOS or Mac line endings to the one true way, and
|
||||
# prefix the source with a linefeed to simplify the tokenization.
|
||||
source = '\n' + source.replace('\r\n', '\n').replace('\r', '\n')
|
||||
|
||||
line = 0
|
||||
for tok in splitter(source):
|
||||
if tok.startswith('\n'):
|
||||
line += 1
|
||||
col = len(tok)
|
||||
else:
|
||||
yield RsonToken(tok, line, col)
|
||||
col += len(tok)
|
||||
|
||||
def multiline(lineinfo, dedent):
|
||||
''' Returns one string for each line,
|
||||
properly dedented.
|
||||
'''
|
||||
linenum = lineinfo[0].line
|
||||
for tok in lineinfo:
|
||||
while linenum < tok.line:
|
||||
yield ''
|
||||
linenum += 1
|
||||
yield (tok.col - dedent) * ' ' + tok.rstrip()
|
||||
linenum += 1
|
||||
|
||||
def getfreeformat(toklist, firsttok, firstcol):
|
||||
''' Returns a free-formatted string.
|
||||
'''
|
||||
curline = firsttok.line
|
||||
firstpart = firsttok[1:].strip() # Get past = sign
|
||||
lineinfo = []
|
||||
while toklist and toklist[-1].col > firstcol:
|
||||
tok = toklist.pop()
|
||||
if tok.line == curline:
|
||||
lineinfo[-1] += tok
|
||||
else:
|
||||
lineinfo.append(tok)
|
||||
curline = tok.line
|
||||
if lineinfo:
|
||||
dedent = min(tok.col for tok in lineinfo)
|
||||
if firstpart:
|
||||
lineinfo.insert(0, RsonToken(firstpart, firsttok.line, dedent))
|
||||
firstpart = '\n'.join(multiline(lineinfo, dedent))
|
||||
return RsonToken(firstpart, firsttok.line, firsttok.col)
|
||||
|
||||
def loads(source):
|
||||
''' load a string into an rsonlite datastructure.
|
||||
If the source is not a string instance, then
|
||||
loads will attempt to convert it into a string
|
||||
instance, by encoding to UTF-8 on Python 2,
|
||||
or decoding from UTF-8 on Python 3.
|
||||
'''
|
||||
toklist = list(gettoks(source))
|
||||
toklist.reverse()
|
||||
result = [None]
|
||||
stack = []
|
||||
curcol = -1
|
||||
curlist = result
|
||||
while toklist:
|
||||
tok = toklist.pop()
|
||||
if tok.startswith('#'):
|
||||
continue
|
||||
col = tok.col
|
||||
if col > curcol:
|
||||
stack.append((curcol, curlist))
|
||||
oldlist = curlist
|
||||
curcol, curlist = col, []
|
||||
oldlist[-1] = oldlist[-1], curlist
|
||||
while col < curcol:
|
||||
curcol, curlist = stack.pop()
|
||||
if col != curcol:
|
||||
err = IndentationError('unindent does not match any outer indentation level')
|
||||
err.filename = '<rsonlite>'
|
||||
err.lineno = tok.line
|
||||
raise err
|
||||
if tok.startswith('='):
|
||||
curlist.append(getfreeformat(toklist, tok, col))
|
||||
else:
|
||||
curlist.append(RsonToken(tok.rstrip(), tok.line, tok.col))
|
||||
if toklist and toklist[-1].line == tok.line:
|
||||
tok = toklist.pop()
|
||||
if tok.startswith('='):
|
||||
curlist[-1] = curlist[-1], [getfreeformat(toklist, tok, col)]
|
||||
else:
|
||||
assert tok.startswith('#') # else problem in regex...
|
||||
result, = result
|
||||
return [] if result is None else result[1]
|
||||
|
||||
def dumps(data, indent=' ', initial_indent=''):
|
||||
''' Dump a string loaded with loads back out.
|
||||
'''
|
||||
def getstring(data, indent2):
|
||||
if '\n' in data:
|
||||
data = ('\n'+indent2).join([''] + data.split('\n'))
|
||||
return data
|
||||
|
||||
def recurse(data, indent2):
|
||||
assert isinstance(data, list), repr(data)
|
||||
for data in data:
|
||||
if isinstance(data, tuple):
|
||||
key, value = data
|
||||
if len(value) == 1 and isinstance(value[0], basestring):
|
||||
append('%s%s = %s' % (indent2, key, getstring(value[0], indent2+indent)))
|
||||
else:
|
||||
append('%s%s' % (indent2, key))
|
||||
recurse(value, indent2 + indent)
|
||||
else:
|
||||
assert isinstance(data, basestring)
|
||||
if '\n' in data or '=' in data or '#' in data:
|
||||
append(indent2 + '=')
|
||||
append(getstring(data, indent2 + ' '))
|
||||
else:
|
||||
append('%s%s' % (indent2, data))
|
||||
result = []
|
||||
append = result.append
|
||||
recurse(data, initial_indent)
|
||||
append('')
|
||||
return '\n'.join(result)
|
||||
|
||||
def pretty(data, indent=' '):
|
||||
''' Pretty-print a string loaded by loads into
|
||||
something that makes it easy to see the actual
|
||||
structure of the data. The return value of
|
||||
this should be parseable by eval()
|
||||
'''
|
||||
def recurse(data, indent2):
|
||||
assert isinstance(data, list)
|
||||
for data in data:
|
||||
assert isinstance(data, (tuple, basestring))
|
||||
if isinstance(data, tuple) and (
|
||||
len(data[1]) != 1 or not isinstance(data[1][0], basestring)):
|
||||
append('%s(%s, [' % (indent2, repr(data[0])))
|
||||
recurse(data[1], indent2 + indent)
|
||||
append('%s])' % (indent2))
|
||||
else:
|
||||
append('%s%s,' % (indent2, repr(data)))
|
||||
result = []
|
||||
append = result.append
|
||||
append('[')
|
||||
recurse(data, indent)
|
||||
append(']')
|
||||
append('')
|
||||
return '\n'.join(result)
|
||||
|
||||
##########################################################################
|
||||
# These higher-level functions might suffice for simple data, and also
|
||||
# provide a template for designing similar functions.
|
||||
|
||||
def stringparse(s, special=dict(true=True, false=False, null=None)):
|
||||
''' This gives an example of handling the JSON special identifiers
|
||||
true, false and null, and also of handling simple arrays.
|
||||
'''
|
||||
if s in special:
|
||||
return special[s]
|
||||
if s.startswith('[') and s.endswith(']'):
|
||||
t = s[1:-1]
|
||||
for ch in '"\'[]{}\n':
|
||||
if ch in t:
|
||||
return s
|
||||
return [x.strip() for x in t.split(',')]
|
||||
return s
|
||||
|
||||
def simpleparse(source, stringparse=stringparse, stddict=stddict):
|
||||
''' Return the simplest structure that uses dicts instead
|
||||
of tuples, and doesn't lose any source information.
|
||||
Use ordered dicts if they are available.
|
||||
'''
|
||||
def recurse(mylist):
|
||||
if len(mylist) == 1 and isinstance(mylist[0], basestring):
|
||||
return stringparse(mylist[0])
|
||||
keys = [x[0] for x in mylist if isinstance(x, tuple)]
|
||||
if not keys:
|
||||
return mylist # simple list
|
||||
if len(set(keys)) == len(mylist):
|
||||
return stddict((x, recurse(y)) for (x, y) in mylist)
|
||||
# Complicated. Make a list that might have multiple dicts
|
||||
result = []
|
||||
curdict = None
|
||||
for item in mylist:
|
||||
if not isinstance(item, tuple):
|
||||
result.append(stringparse(item))
|
||||
curdict = None
|
||||
continue
|
||||
key, value = item
|
||||
if curdict is None or key in curdict:
|
||||
curdict = stddict()
|
||||
result.append(curdict)
|
||||
curdict[key] = recurse(value)
|
||||
return result
|
||||
return recurse(source if isinstance(source, list) else loads(source))
|
||||
Reference in New Issue
Block a user