'''
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.

'''

__author__ = "Javier D. Garcia-Lasheras"
__copyright__ = "Copyright 2014, CERN"
__license__ = "GPLv3 or later"
__version__ = "1.0"
__maintainer__ = "Javier D. Garcia-Lasheras"
__email__ = "javier@garcialasheras.com"
__status__ = "Development"


from spec_libc import *


class SpecDemoUser(Spec):
    '''Simple demo application demonstrating the use of Spec class.
    This is part of the getting started with the SPEC project.
    By creating a SpecDemoUser object, access to the basic functions
    covered in the gateware HDL Spec Demo User is granted.
    In this way, the SPEC FPGA must be programmed with the specific bitstream.
    For this purpose, use the specLoadBitstream() method inherited from Spec.
    '''

    def __init__(self, bus=-1, dev=-1, libc='/usr/lib/libspec.so'):

        Spec.__init__(self, bus=bus, dev=dev, libc=libc)

        self.userAddressMap = {
            'control': 0x0,
            'auxiliar': 0x4,
        }

        self.userControlOffsets = {
            'PCBVersion': 0,
            'GreenLED': 4,
            'RedLED': 5,
        }

        self.userAuxiliarOffsets = {
            'Button1': 0,
            'Button2': 1,
            'AuxLEDs': 2,
        }


    def specGetPCBVersion(self):
        '''Return the SPEC PCB version as an integer value.'''
        register = self.specReadL(0x0, hexformat=False)
        register = int(register % 16)
        return register


    # Green LED Controls

    def specGetGreenLED(self):
        '''Test the status of the SPEC Front Panel Green LED.
        returns a nonzero result if the LED is ON, 0 if the LED is OFF.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['GreenLED']
        return self.specTestBit(address, offset)


    def specSetGreenLED(self):
        '''Set to ON the SPEC Front Panel Green LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['GreenLED']
        self.specSetBit(address, offset)


    def specClearGreenLED(self):
        '''Clear to OFF the SPEC Front Panel Green LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['GreenLED']
        self.specClearBit(address, offset)


    def specToggleGreenLED(self):
        '''Toggle/change the SPEC Front Panel Green LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['GreenLED']
        self.specToggleBit(address, offset)


    # Red LED Controls

    def specGetRedLED(self):
        '''Test the status of the SPEC Front Panel Red LED.
        returns a nonzero result if the LED is ON, 0 if the LED is OFF.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['RedLED']
        return self.specTestBit(address, offset)


    def specSetRedLED(self):
        '''Set to ON the SPEC Front Panel Red LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['RedLED']
        self.specSetBit(address, offset)


    def specClearRedLED(self):
        '''Clear to OFF the SPEC Front Panel Red LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['RedLED']
        self.specClearBit(address, offset)


    def specToggleRedLED(self):
        '''Toggle/change the SPEC Front Panel Red LED.'''
        address = self.userAddressMap['control'] 
        offset = self.userControlOffsets['RedLED']
        self.specToggleBit(address, offset)


    # Auxiliar pushbuttons

    def specGetButton1(self):
        '''Test the state of the internal auxiliar Button1.
        Return 0 when pressed and nonzero when released.'''
        address = self.userAddressMap['auxiliar'] 
        offset = self.userAuxiliarOffsets['Button1']
        return self.specTestBit(address, offset)


    def specGetButton2(self):
        '''Test the state of the internal auxiliar Button2.
        Return 0 when pressed and nonzero when released.'''
        address = self.userAddressMap['auxiliar'] 
        offset = self.userAuxiliarOffsets['Button2']
        return self.specTestBit(address, offset)


    # Auxiliar LEDs

    def specGetAuxLEDs(self, hexformat=True):
        '''Return the hex value corresponding to the four auxiliar LEDs.
        If hexformat=True, the returned value is a string in hex format.
        Note that the Auxiliar LEDs are active low.'''
        address = self.userAddressMap['auxiliar'] 
        offset = self.userAuxiliarOffsets['AuxLEDs']
        register = self.specReadL(address, hexformat=False)
        register = register >> offset
        mask = 0xf
        register = register & mask
        if hexformat:
            register = hex(register)
        return register


    def specSetAuxLEDs(self, value):
        '''Set the hex value corresponding to the four auxiliar LEDs.
        Note that the Auxiliar LEDs are active low.'''
        address = self.userAddressMap['auxiliar'] 
        offset = self.userAuxiliarOffsets['AuxLEDs']
        register = self.specReadL(address, hexformat=False)
        mask = ~(0xf << offset)
        register = register & mask
        mask = value << offset
        register = register | mask
        self.specWriteL(address, register)



