<commit_before># Copyright (c) 2016, Nordic Semiconductor
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * 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.
#
# * Neither the name of Nordic Semiconductor ASA nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# 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.

import os
import nrfjprog_version
import numpy as np
from pynrfjprog import API, Hex

class NRF5x:
    """
    Class that handles the api instance, some arguments that commands share, and logging.

    """
    def __init__(self, args, do_not_initialize_api = False):
        """
        Initialize api (the connection to the target device) and the class's properties.

        :param Object  args:                  The arguments the command was called with.
        :param boolean do_not_initialize_api: If api should be intialized (the connection to the target device should be set up).
        """
        self.quiet = args.quiet # All commands are to have the quiet argument.

        if do_not_initialize_api:
            return
        else:
            self.clockspeed = args.clockspeed # Any commands that connect to the emulator (debugger) are to have the clock speed/serial number arguments.
            self.snr = args.snr
            self.api = self._setup()

        np.set_printoptions(formatter={'int':hex}) # Output values displayed as hex instead of dec.

    def _setup(self):
        """
        Discovers the family (either NRF51 or NRF52) of the target device (through trial and error) and connects to it.

        :return API api: Instance of an API object that is initialized and connected to an nRF5x device.
        """
        device_family = API.DeviceFamily.NRF51
        api = API.API(device_family)
        api.open()
        self._connect_to_emu(api)
        
        try:
            device_version = api.read_device_version()
        except API.APIError as e:
            if e.err_code == API.NrfjprogdllErr.WRONG_FAMILY_FOR_DEVICE:
                device_family = API.DeviceFamily.NRF52
                api.close()
                api = API.API(device_family)
                api.open()
                self._connect_to_emu(api)
            else:
                raise e

        api.connect_to_device()
        return api

    def _connect_to_emu(self, api):
        if self.snr and self.clockspeed:
            api.connect_to_emu_with_snr(self.snr, self.clockspeed)
        elif self.snr:
            api.connect_to_emu_with_snr(self.snr)
        elif self.clockspeed:
            api.connect_to_emu_without_snr(self.clockspeed)
        else:
            api.connect_to_emu_without_snr()

    def log(self, msg):
        if self.quiet:
            pass
        else:
            print(msg)

    def cleanup(self):
        self.api.disconnect_from_emu()
        self.api.close()

"""
The callback functions that are called from __main__.py (argparse) based on the command-line input.

All functions follow the same structure: initialize NRF5x, log (exactly what the help menu prints for the command, but in different tense), perform functionality, cleanup.
"""

def erase(args):
    nrf = NRF5x(args)
    nrf.log('Erasing the device.')

    if args.erasepage:
        nrf.api.erase_page(args.erasepage)
    elif args.eraseuicr:
        nrf.api.erase_uicr()
    else:
        nrf.api.erase_all()

    nrf.cleanup()

def halt(args):
    nrf = NRF5x(args)
    nrf.log("Halting the device's CPU.")

    nrf.api.halt()

    nrf.cleanup()

def ids(args):
    nrf = NRF5x(args, do_not_initialize_api = True)
    nrf.log('Displaying the serial numbers of all debuggers connected to the PC.')

    api = API.API(API.DeviceFamily.NRF51) # Family doesn't matter since we are not connecting to a device so use NRF51 by default.
    api.open()

    ids = api.enum_emu_snr()
    print(sorted(ids))

    api.close()

def memrd(args):
    nrf = NRF5x(args)
    nrf.log("Reading the device's memory.")

    if args.length:
        length = args.length
    else:
        length = 4

    read_data = nrf.api.read(args.addr, length)
    print(np.array(read_data))

    nrf.cleanup()

def memwr(args):
    nrf = NRF5x(args)
    nrf.log("Writing the device's memory.")

    if args.flash:
        nrf.api.write_u32(args.addr, args.val, True)
    else:
        nrf.api.write_u32(args.addr, args.val, False)

    nrf.cleanup()

def pinresetenable(args):
    nrf = NRF5x(args)
    nrf.log("Enabling the pin reset on nRF52 devices. Invalid command on nRF51 devices.")
  
    UICR_PSELRESET0_ADDR = 0x10001200
    UICR_PSELRESET1_ADDR = 0x10001204
    UICR_PSELRESET_21_CONNECT = 0x8FFFFF15 # Writes the connect bit field and 21 pin bit field (reset is connected and GPIO pin 21 is selected as the reset).

    nrf.api.write_u32(UICR_PSELRESET0_ADDR, UICR_PSELRESET_21_CONNECT, True)
    nrf.api.write_u32(UICR_PSELRESET1_ADDR, UICR_PSELRESET_21_CONNECT, True)
    nrf.api.sys_reset()

    nrf.cleanup()

def program(args):
    nrf = NRF5x(args)
    nrf.log('Programming the device.')

    if args.eraseall:
        nrf.api.erase_all()
    elif args.sectorserase:
        assert (False), "Not implemented in nrf5x.py yet."
    elif args.sectorsanduicrerase:<commit_msg>use default values, dont check twice.<commit_after># Copyright (c) 2016, Nordic Semiconductor
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are met:
#
# * Redistributions of source code must retain the above copyright notice, this
#   list of conditions and the following disclaimer.
#
# * 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.
#
# * Neither the name of Nordic Semiconductor ASA nor the names of its
#   contributors may be used to endorse or promote products derived from
#   this software without specific prior written permission.
#
# 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.

import os
import nrfjprog_version
import numpy as np
from pynrfjprog import API, Hex

class NRF5x:
    """
    Class that handles the api instance, some arguments that commands share, and logging.

    """
    def __init__(self, args, do_not_initialize_api = False):
        """
        Initialize api (the connection to the target device) and the class's properties.

        :param Object  args:                  The arguments the command was called with.
        :param boolean do_not_initialize_api: If api should be intialized (the connection to the target device should be set up).
        """
        self.quiet = args.quiet # All commands are to have the quiet argument.

        if do_not_initialize_api:
            return
        else:
            self.clockspeed = args.clockspeed # Any commands that connect to the emulator (debugger) are to have the clock speed/serial number arguments.
            self.snr = args.snr
            self.api = self._setup()

        np.set_printoptions(formatter={'int':hex}) # Output values displayed as hex instead of dec.

    def _setup(self):
        """
        Discovers the family (either NRF51 or NRF52) of the target device (through trial and error) and connects to it.

        :return API api: Instance of an API object that is initialized and connected to an nRF5x device.
        """
        device_family = API.DeviceFamily.NRF51
        api = API.API(device_family)
        api.open()
        self._connect_to_emu(api)
        
        try:
            device_version = api.read_device_version()
        except API.APIError as e:
            if e.err_code == API.NrfjprogdllErr.WRONG_FAMILY_FOR_DEVICE:
                device_family = API.DeviceFamily.NRF52
                api.close()
                api = API.API(device_family)
                api.open()
                self._connect_to_emu(api)
            else:
                raise e

        api.connect_to_device()
        return api

    def _connect_to_emu(self, api):
        if self.snr and self.clockspeed:
            api.connect_to_emu_with_snr(self.snr, self.clockspeed)
        elif self.snr:
            api.connect_to_emu_with_snr(self.snr)
        elif self.clockspeed:
            api.connect_to_emu_without_snr(self.clockspeed)
        else:
            api.connect_to_emu_without_snr()

    def log(self, msg):
        if self.quiet:
            pass
        else:
            print(msg)

    def cleanup(self):
        self.api.disconnect_from_emu()
        self.api.close()

"""
The callback functions that are called from __main__.py (argparse) based on the command-line input.

All functions follow the same structure: initialize NRF5x, log (exactly what the help menu prints for the command, but in different tense), perform functionality, cleanup.
"""

def erase(args):
    nrf = NRF5x(args)
    nrf.log('Erasing the device.')

    if args.erasepage:
        nrf.api.erase_page(args.erasepage)
    elif args.eraseuicr:
        nrf.api.erase_uicr()
    else:
        nrf.api.erase_all()

    nrf.cleanup()

def halt(args):
    nrf = NRF5x(args)
    nrf.log("Halting the device's CPU.")

    nrf.api.halt()

    nrf.cleanup()

def ids(args):
    nrf = NRF5x(args, do_not_initialize_api = True)
    nrf.log('Displaying the serial numbers of all debuggers connected to the PC.')

    api = API.API(API.DeviceFamily.NRF51) # Family doesn't matter since we are not connecting to a device so use NRF51 by default.
    api.open()

    ids = api.enum_emu_snr()
    print(sorted(ids))

    api.close()

def memrd(args):
    nrf = NRF5x(args)
    nrf.log("Reading the device's memory.")

    read_data = nrf.api.read(args.addr, args.length)
    print(np.array(read_data))

    nrf.cleanup()

def memwr(args):
    nrf = NRF5x(args)
    nrf.log("Writing the device's memory.")

    nrf.api.write_u32(args.addr, args.val, args.flash)

    nrf.cleanup()

def pinresetenable(args):
    nrf = NRF5x(args)
    nrf.log("Enabling the pin reset on nRF52 devices. Invalid command on nRF51 devices.")
  
    UICR_PSELRESET0_ADDR = 0x10001200
    UICR_PSELRESET1_ADDR = 0x10001204
    UICR_PSELRESET_21_CONNECT = 0x8FFFFF15 # Writes the connect bit field and 21 pin bit field (reset is connected and GPIO pin 21 is selected as the reset).

    nrf.api.write_u32(UICR_PSELRESET0_ADDR, UICR_PSELRESET_21_CONNECT, True)
    nrf.api.write_u32(UICR_PSELRESET1_ADDR, UICR_PSELRESET_21_CONNECT, True)
    nrf.api.sys_reset()

    nrf.cleanup()

def program(args):
    nrf = NRF5x(args)
    nrf.log('Programming the device.')

    if args.eraseall:
        nrf.api.erase_all()
    elif args.sectorserase:
        assert (False), "Not implemented in nrf5x.py yet."
    elif args.sectorsanduicrerase:
{'fraction_non_alphanumeric': 0.07722461779694237, 'fraction_numerical': 0.011681693453547628, 'mean_word_length': 2.8468033775633295, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3361326', 'n_tokens_mistral': 4034, 'n_tokens_neox': 3816, 'n_words': 1295}