# Path: IoTPy/errors.py
# class IoTPy_APIError(Exception):
#     pass
# 
# def errmsg(fmt, *args):
#     if not fmt.endswith('\n'):
#         fmt += '\n'
#     sys.stderr.write(os.path.basename(sys.argv[0]))
#     sys.stderr.write(': ')
#     if len(args):
#         sys.stderr.write(fmt % args)
#     else:
#         sys.stderr.write(fmt)
#     sys.stderr.flush()
# 
# Path: IoTPy/sfp.py
# def encode_sfp(command, args):
#     """
#     Construct binary SFP command.
# 
#     :param command: SFP command ID.
#     :type command: int
#     :param args: A list of SFP arguments, which can be either an integer or a byte collection (string).
#     :type args: list
#     :return: Binary SFP command.
#     :rtype: str
#     """
#     functions = {
#         binary_type: _encode_bytes,
#         integer_types[0]: _encode_int   # [0] - kinda hack to get class int
#     }
# 
#     sfp_command = pack('B', command) + b''.join(functions[type(arg)](arg) for arg in args)
#     sfp_command = b'\xd4' + pack('>H', len(sfp_command)) + sfp_command
#     return sfp_command
# 
# def decode_sfp(io_buffer):
#     """
#     Decode SFP command from byte buffer.
# 
#     :param io_buffer: A byte buffer which stores SFP command.
#     :type io_buffer: bytes string
#     :return: SFP function ID and arguments list.
#     """
#     if io_buffer[0:1] != b'\xd4':
#         return
#     command_length = unpack('>H', io_buffer[1:3])[0] + 3    # get SFP command length located in two bytes
#     sfp_command = unpack('B', io_buffer[3:4])[0]            # get SFP command code
#     pointer = 4
#     args = []
#     while pointer < command_length:
#         arg_type = ord(io_buffer[pointer:pointer + 1])
#         pointer += 1
#         if arg_type < 64:                    # short int
#             args.append(arg_type)
#         elif arg_type < 128:                    # short str
#             arg_len = arg_type & 0x3f
#             args.append(io_buffer[pointer:pointer + arg_len])
#             pointer += arg_len
#         else:
#             arg_len = arg_type & 0x0f
#             if arg_len < 4:            # decoding integers
#                 if arg_len == 0:
#                     args.append(ord(io_buffer[pointer:pointer + 1]))
#                 elif arg_len == 1:
#                     args.append(unpack('>H', io_buffer[pointer:pointer + 2])[0])
#                 elif arg_len == 2:
#                     args.append(unpack('>I', b'\x00' + io_buffer[pointer:pointer + 3])[0])
#                 elif arg_len == 3:
#                     args.append(unpack('>I', io_buffer[pointer:pointer + 4])[0])
#                 pointer += arg_len + 1
#             else:
#                 if arg_type == 0xc4:        # decoding strings
#                     arg_len = ord(io_buffer[pointer:pointer + 1])
#                 elif arg_type == 0xc5:
#                     arg_len = unpack('>H', io_buffer[pointer:pointer + 2])[0]
#                     pointer += 1
#                 else:
#                     raise IoTPy_APIError("UPER API: Bad parameter type in decodeSFP method.")
#                 pointer += 1
#                 args.append(io_buffer[pointer:pointer + arg_len])
#                 pointer += arg_len
#     return sfp_command, args


from IoTPy.errors import IoTPy_APIError, errmsg
from IoTPy.sfp import encode_sfp, decode_sfp

class SPI(object):
    """
    SPI communication module.

    :param board: IoBoard with SPI capability.
    :type board: :class:`IoTPy.pyuper.ioboard.IoBoard`
    :param port: SPI module number. Optional, default 0 (SPI0 module).
    :type port: int
    :param divider: SPI clock divider. SPI clock speed will be maximum clock speed (2MHz) divided by this value. Optional, default 1.
    :type divider: int
    :param mode: Standard SPI mode number (SPI.MODE_0 to SPI.MODE_3). Optional, default SPI.MODE_0.
    :type mode: int
    """

    MODE_0 = 0
    MODE_1 = 1
    MODE_2 = 2
    MODE_3 = 3

    def __init__(self, board, port=0, divider=1, mode=MODE_0):
        divider = min(max(divider, 1), 256)

        self.board = board
        self.port = port
        self.divider = divider
        self.mode = mode
        if self.port == 1:
            self.board.low_level_io(0, encode_sfp(2, [4]))
            self.board.low_level_io(0, encode_sfp(2, [5]))

# Path: IoTPy/errors.py
# class IoTPy_APIError(Exception):
#     pass
# 
# def errmsg(fmt, *args):
#     if not fmt.endswith('\n'):
#         fmt += '\n'
#     sys.stderr.write(os.path.basename(sys.argv[0]))
#     sys.stderr.write(': ')
#     if len(args):
#         sys.stderr.write(fmt % args)
#     else:
#         sys.stderr.write(fmt)
#     sys.stderr.flush()
# 
# Path: IoTPy/sfp.py
# def encode_sfp(command, args):
#     """
#     Construct binary SFP command.
# 
#     :param command: SFP command ID.
#     :type command: int
#     :param args: A list of SFP arguments, which can be either an integer or a byte collection (string).
#     :type args: list
#     :return: Binary SFP command.
#     :rtype: str
#     """
#     functions = {
#         binary_type: _encode_bytes,
#         integer_types[0]: _encode_int   # [0] - kinda hack to get class int
#     }
# 
#     sfp_command = pack('B', command) + b''.join(functions[type(arg)](arg) for arg in args)
#     sfp_command = b'\xd4' + pack('>H', len(sfp_command)) + sfp_command
#     return sfp_command
# 
# def decode_sfp(io_buffer):
#     """
#     Decode SFP command from byte buffer.
# 
#     :param io_buffer: A byte buffer which stores SFP command.
#     :type io_buffer: bytes string
#     :return: SFP function ID and arguments list.
#     """
#     if io_buffer[0:1] != b'\xd4':
#         return
#     command_length = unpack('>H', io_buffer[1:3])[0] + 3    # get SFP command length located in two bytes
#     sfp_command = unpack('B', io_buffer[3:4])[0]            # get SFP command code
#     pointer = 4
#     args = []
#     while pointer < command_length:
#         arg_type = ord(io_buffer[pointer:pointer + 1])
#         pointer += 1
#         if arg_type < 64:                    # short int
#             args.append(arg_type)
#         elif arg_type < 128:                    # short str
#             arg_len = arg_type & 0x3f
#             args.append(io_buffer[pointer:pointer + arg_len])
#             pointer += arg_len
#         else:
#             arg_len = arg_type & 0x0f
#             if arg_len < 4:            # decoding integers
#                 if arg_len == 0:
#                     args.append(ord(io_buffer[pointer:pointer + 1]))
#                 elif arg_len == 1:
#                     args.append(unpack('>H', io_buffer[pointer:pointer + 2])[0])
#                 elif arg_len == 2:
#                     args.append(unpack('>I', b'\x00' + io_buffer[pointer:pointer + 3])[0])
#                 elif arg_len == 3:
#                     args.append(unpack('>I', io_buffer[pointer:pointer + 4])[0])
#                 pointer += arg_len + 1
#             else:
#                 if arg_type == 0xc4:        # decoding strings
#                     arg_len = ord(io_buffer[pointer:pointer + 1])
#                 elif arg_type == 0xc5:
#                     arg_len = unpack('>H', io_buffer[pointer:pointer + 2])[0]
#                     pointer += 1
#                 else:
#                     raise IoTPy_APIError("UPER API: Bad parameter type in decodeSFP method.")
#                 pointer += 1
#                 args.append(io_buffer[pointer:pointer + arg_len])
#                 pointer += arg_len
#     return sfp_command, args


# Path: IoTPy/interfaces/spi.py
from IoTPy.errors import IoTPy_APIError, errmsg
from IoTPy.sfp import encode_sfp, decode_sfp


class SPI(object):
    """
    SPI communication module.

    :param board: IoBoard with SPI capability.
    :type board: :class:`IoTPy.pyuper.ioboard.IoBoard`
    :param port: SPI module number. Optional, default 0 (SPI0 module).
    :type port: int
    :param divider: SPI clock divider. SPI clock speed will be maximum clock speed (2MHz) divided by this value. Optional, default 1.
    :type divider: int
    :param mode: Standard SPI mode number (SPI.MODE_0 to SPI.MODE_3). Optional, default SPI.MODE_0.
    :type mode: int
    """

    MODE_0 = 0
    MODE_1 = 1
    MODE_2 = 2
    MODE_3 = 3

    def __init__(self, board, port=0, divider=1, mode=MODE_0):
        divider = min(max(divider, 1), 256)

        self.board = board
        self.port = port
        self.divider = divider
        self.mode = mode
        if self.port == 1:
            self.board.low_level_io(0, encode_sfp(2, [4]))
            self.board.low_level_io(0, encode_sfp(2, [5]))

            self.board.low_level_io(0, encode_sfp(2, [11]))