#*******************************************************************************
#
#     SCons main construct file
#
#     Processor: MSP430 (Texas Instruments)
#
#     Toolkit:   IAR EW430
#
#     Copyright (c) 2006-2015, Harry E. Zhurov
#
#-------------------------------------------------------------------------------
import sys
import os
import glob
import subprocess

sys.path.append(os.getcwd() + '/cfg')

import scmIC

#===============================================================================
#
#     User definable area
#
#-------------------------------------------------------------------------------
#
#     Project settings
#
ProjectName  = 'slon'

RootDir      = '../../../../../'                          
SourceDirs   = ['src', 
                RootDir + 'scmRTOS/core', 
                RootDir + 'scmRTOS/port/msp430/iar']

#--------------------------------------
#
#     Options
#
Processor    = 'F169'
Optimization = ' -Ohs '

EnableHWMultiplier = True

ExtraAFlags  = ''
ExtraCFlags  = ''
ExtraLFlags  = ''

RunTimeLibrary = 'dl430fn.r43'
                
ProcessorSymbol = '__MSP430' + Processor + '__'


#===============================================================================
#
#    !!!  Service area  !!!
#
#-------------------------------------------------------------------------------
#
#    Project structure
#
ObjDir     = 'obj'
ListDir    = 'lst'
ExeDir     = 'bin'
ConfigDir  = 'cfg'

ServiceDirs = [ ObjDir, ListDir, ExeDir, ConfigDir ]
for i in ServiceDirs:
    curdir = os.getcwd() + os.sep + i
    if not os.path.exists(curdir):
        print 'Directory ' + curdir + ' does not exists. Creating the directory...',
        os.mkdir(curdir)
        print 'done'

#-------------------------------------------------------------------------------
#
#    Platform specific stuff
#
AsmExt  = 's43'
CExt    = 'c'
CppExt  = 'cpp'
ObjExt  = 'r43'
DbgExt  = 'd43'
HexExt  = 'hex'

#-------------------------------------------------------------------------------
#
#      Toolkit
#
IAR = os.environ['IAR']
TOOLKIT_PATH = IAR + '\\ew430.640'

ASM    = TOOLKIT_PATH + '\\430\\bin\\a430.exe'
CC     = TOOLKIT_PATH + '\\430\\bin\\icc430.exe'
Linker = TOOLKIT_PATH + '\\430\\bin\\xlink.exe'

ToolkitIncPath = [TOOLKIT_PATH + '\\430\\inc',  
                  TOOLKIT_PATH + '\\430\\inc\\dlib', 
                  TOOLKIT_PATH + '\\430\\lib\\dlib'] 

ToolkitLibPath = [TOOLKIT_PATH + '\\430\\lib\\dlib']
ToolkitCfgPath = [TOOLKIT_PATH + '\\430\\config']

#-------------------------------------------------------------------------------
#
#      Tools options
#
#----------------------------------------------------
#
#      Include, library, config files and paths
#
IncludePath = ''.join(' -I' + i for i in SourceDirs + ToolkitIncPath)
LibraryPath = ''.join(' -I' + i for i in ToolkitLibPath)
ConfigPath  = ''.join(' '   + i for i in ToolkitCfgPath)

LinkerCmdFile = ConfigDir + '\\lnk430' + Processor + '.xcl'
LinkerMapFile = ListDir   + '\\' + ProjectName + '.map'

#-------------------------------------------------------------------------------
#
#    The options
#
AFLAGS  = ' -L' + ListDir + '\\' + ' -O' + ObjDir + '\\' + ' -M() -S '
AFLAGS += ' -D' + ProcessorSymbol + IncludePath + ' ' + ExtraAFlags
#-------------------------------------------------------------------------------
CFLAGS  = ' -D' + ProcessorSymbol + IncludePath + Optimization + ExtraCFlags
CFLAGS += ' -lC ' + ListDir + ' --preprocess ' + ListDir + ' -e --eec++ --silent --debug --no_wrap_diagnostics'
CFLAGS += ' --dlib_config ' + RunTimeLibrary.split('.')[0] + '.h'
#-------------------------------------------------------------------------------
LFLAGS  = ' -f ' + LinkerCmdFile + ' -l ' + LinkerMapFile + ' -xsme' + ' -s __program_start'
LFLAGS += LibraryPath + ' ' + RunTimeLibrary + ' ' + ExtraLFlags

if EnableHWMultiplier:
    LFLAGS += ' -f ' + ConfigPath + '\\linker\\multiplier.xcl'
#-------------------------------------------------------------------------------


#-------------------------------------------------------------------------------
#
#    Action functions
#
def compile_cpp(target, source, env):
    #------------------------------------------------
    #
    #   Check if the first source is compiling
    #
    if env['FIRST_ENTRY'] == False:
        env['FIRST_ENTRY'] = True
        print '*'*60

    #------------------------------------------------
    #
    #   Launch compiler
    #
    print 'Compile:  ' + str(source[0])
    cmd = env['CC'] + env['CFLAGS'] + ' -o' + str(target[0]) + ' ' + str(source[0])
    p = subprocess.Popen(cmd, universal_newlines = True,
                         stdin  = subprocess.PIPE,
                         stdout = subprocess.PIPE,
                         stderr = subprocess.PIPE )

    out, err = p.communicate()
    if out: print out
    if err: print err

    return p.returncode
#-------------------------------------------------------------------------------
def assembly_src(target, source, env):
    #------------------------------------------------
    #
    #   Check if the first source is compiling
    #
    if env['FIRST_ENTRY'] == False:
        env['FIRST_ENTRY'] = True
        print '*'*60

    #------------------------------------------------
    #
    #   Launch assembler
    #
    print 'Assembly: ' + str(source[0])
    cmd = env['ASM'] + env['AFLAGS'] + ' ' + str(source[0])
    p = subprocess.Popen( cmd,
                          stdin  = subprocess.PIPE,
                          stdout = subprocess.PIPE,
                          stderr = subprocess.PIPE)

    out, err = p.communicate()
    if out: print out
    if err: print err

    return p.returncode
#-------------------------------------------------------------------------------
def BuildTarget(target, source, env):
    if env['FIRST_ENTRY'] == False:
        print '*'*60
        print 'Sources are up to date'

    check_scmRTOS_cfg(target, source, env)
    print '*'*60
    print 'Link: ' + str(target[0])

    src_list = ''
    for i in xrange(len(source)):
        src_list += ' ' + str(source[i])

    cmd = env['LINKER'] + env['LFLAGS'] + ' -r' + ' -o ' + str(target[0]) + src_list 
    #print cmd
    p = subprocess.Popen( cmd )
    rcode = p.wait()

    print '*'*60
    return rcode

#-------------------------------------------------------------------------------
#
#   Builders
#
cpp2obj = Builder(action         = compile_cpp,
                  suffix         = ObjExt,
                  src_suffix     = CppExt,
                  source_scanner = CScanner)
#-------------------------------------------------------------------------------
asm2obj = Builder(action         = assembly_src,
                  suffix         = ObjExt,
                  src_suffix     = AsmExt,
                  source_scanner = CScanner)
#-------------------------------------------------------------------------------
build_exe = Builder(action       = BuildTarget,
                    suffix       = DbgExt,
                    src_suffix   = ObjExt)

#-------------------------------------------------------------------------------
#
#    State variables
#
FirstEntry = False

#-------------------------------------------------------------------------------
#
#    Environment
#

env = Environment(TOOLS = {})

env['BUILDERS'] = { 'asmObj' : asm2obj, 'cppObj' : cpp2obj, 'Exe' : build_exe }
env['ASM'        ] = ASM
env['CC'         ] = CC
env['LINKER'     ] = Linker
env['AFLAGS'     ] = AFLAGS
env['CFLAGS'     ] = CFLAGS
env['LFLAGS'     ] = LFLAGS
env['SRC_PATH'   ] = SourceDirs[0]
env['CPPPATH'    ] = SourceDirs + ToolkitIncPath
env['FIRST_ENTRY'] = FirstEntry

#-------------------------------------------------------------------------------
#
#    Cpp source file list
#
cpp_files = []
for i in SourceDirs:
    cpp_files += glob.glob(i + '/*.' + CppExt)

cpp_targets = {}

for i in cpp_files:
    name_ext = os.path.split(i)[1]
    name     = os.path.splitext(name_ext)[0] + '.' + ObjExt
    cpp_targets[i] = ObjDir + '/' + name
    Depends(cpp_targets[i],  'SConstruct')      
#-------------------------------------------------------------------------------
#
#    Asm source file list
#
asm_files = []
for i in SourceDirs:
    asm_files += glob.glob(i + '/*.' + AsmExt)

asm_targets = {}

for i in asm_files:
    name_ext = os.path.split(i)[1]
    name     = os.path.splitext(name_ext)[0] + '.' + ObjExt
    asm_targets[i] = ObjDir + '/' + name
    Depends(asm_targets[i],  'SConstruct')      
    
#-------------------------------------------------------------------------------
#
#    Objects builing
#
cpp_obj_list = []
for i in cpp_files:
    cpp_obj_list.append( env.cppObj(cpp_targets[i], i) )


asm_obj_list = []
for i in asm_files:
    asm_obj_list.append( env.asmObj(asm_targets[i], i) )

obj_list = cpp_obj_list + asm_obj_list


#env.Clean(obj_list)
#-------------------------------------------------------------------------------
#
#    Main target building
#
env.Exe(source = obj_list, target = ExeDir +'\\' + ProjectName)

#-------------------------------------------------------------------------------
#
#    Clean and Rebuid
#
def remove_files(dir_, mask):
    file_list = glob.glob(dir_ + '\\*.' + mask)
    for i in file_list:
        os.remove(i)
    
#-------------------------------------------------------------------------------
def clean(target, source, env):
    os.remove('.sconsign.dblite')
    remove_files(ObjDir,  ObjExt)
    remove_files(ExeDir,  DbgExt)
    remove_files(ListDir, 'i')
    remove_files(ListDir, 'lst')
    remove_files(ListDir, 'map')

#-------------------------------------------------------------------------------
def check_scmRTOS_cfg(target, source, env):
    print '*'*60
    print 'Run integrity checker...',
    rcode = scmIC.checker([env['SRC_PATH']])
    if rcode != 0:
        print '\n scmRTOS configuration is invalid.'

    print '*'*60

#-------------------------------------------------------------------------------
build_main = env.Alias(ProjectName, ExeDir +'\\' + ProjectName + '.' + DbgExt)
clean_all  = env.Alias('cln', action = clean)

env.AlwaysBuild('cln')
env.Alias('rebuild', [clean_all, build_main])

#-------------------------------------------------------------------------------
#print env.Dump()
 
#-------------------------------------------------------------------------------

