- Add REAME file
authorMilo Kim <milo.kim@ti.com>
Fri, 17 Apr 2015 19:55:35 +0000 (04:55 +0900)
committerMilo Kim <milo.kim@ti.com>
Fri, 17 Apr 2015 19:55:35 +0000 (04:55 +0900)
- Support version compatibilty between python 2.x and 3
- Error format modification
- Check program size is greater than 96 or not

README [new file with mode: 0644]
_lasm_cmd_parser.py
_lasm_utils.py
lasm.py

diff --git a/README b/README
new file mode 100644 (file)
index 0000000..4ad11cd
--- /dev/null
+++ b/README
@@ -0,0 +1,47 @@
+TI LP5523 LASM(LP5523 Assembler) for Linux
+==========================================
+
+      Copyright (C) 2015 Texas Instruments
+        Author: Milo Kim <milo.kim@ti.com>
+
+Introduction
+------------
+  LASM is used for generating program code which runs LP5523 chip
+
+  (input)             (output)
+  *.src -> lasm.py -> *.bin and *.hex
+
+  Written based on documents below
+    http://www.ti.com/lit/ds/symlink/lp5523.pdf
+    http://www.ti.com/lit/an/snva664/snva664.pdf
+
+Python version compatibility
+----------------------------
+  Tested under Python 2.7 and 3.3.
+  The module 'six' is used for support version compatibility.
+
+How to use
+----------
+  Two options are available.
+  Single file conversion and multiple files conversion under a directory.
+
+  To convert a .src into .bin and .hex,
+
+    $python lasm.py -f foo.src
+
+  To convert whole src files under a directory,
+  For example, let's assume that there are tens of *.src files under 'examples'
+  directory.
+
+    $python lasm.py -d examples/
+
+  Output files are generated under same directory as *.src exists.
+
+Limitation
+----------
+  1) *.lst file
+  LASM.exe (Windows version) creates *.lst from *.src as well.
+  However, this tool doesn't generate *.lst at this moment.
+
+  2) Option for recursive conversion
+  This tool doesn't support recursive option yet.
index 6ee46b8536e0073e957f6752b2cc4c4e611c4e45..b89ff560827effea9c726171b14635f6dcee4e39 100644 (file)
 #     - www.ti.com/lit/an/snva664/snva664.pdf
 #
 
+import six                    # support compatibility between Python 2.x and 3
 import _lasm_utils as util
 
-# Return type
-SUCCESS = 0
-FAILURE = CMD_NOT_FOUND = -1
+# Constant numbers for ramp/wait command
+PRESCALE0 = 0.015625
+PRESCALE1 = 0.5
+MASTER_FREQ = 32768
+PRESCALE0_CLK = MASTER_FREQ / 16
+PRESCALE1_CLK = MASTER_FREQ / 512
+MAXCODE = 0x1F
+PRESCALE_CODE = 0x40
 
 
 # Display error
@@ -34,7 +40,7 @@ FAILURE = CMD_NOT_FOUND = -1
 def put_error(message):
     func_name = util.get_caller_func_name()
     util.put_error(func_name, message)
-    return FAILURE
+    return False
 
 
 # Segment command is used for program engine selection (1,2,3)
@@ -42,171 +48,147 @@ def put_error(message):
 def segment(name):
     args = name.split()
     if len(args) != 1:
-        put_error('must have one directive')
-        return FAILURE
+        return put_error('must have one argument')
 
-    util.add_segment_list(args[0])
-    return SUCCESS
+    if util.add_segment_list(args[0]) is False:
+        return put_error('duplicate segment name')
+
+    return True
 
 
 def mux_map_start(label):
     args = label.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     code = util.get_address_of_label(args[0], '')
     if code == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     MUX_MAP_START = 0x9C00
-    util.put_code(MUX_MAP_START | code)
-    return SUCCESS
+    return util.put_code(MUX_MAP_START | code)
 
 
 def mux_map_next(val):
-    util.put_code(0x9D80)
-    return SUCCESS
+    return util.put_code(0x9D80)
 
 
 def mux_map_prev(val):
-    util.put_code(0x9DC0)
-    return SUCCESS
+    return util.put_code(0x9DC0)
 
 
 def mux_ld_next(val):
-    util.put_code(0x9D81)
-    return SUCCESS
+    return util.put_code(0x9D81)
 
 
 def mux_ld_prev(val):
-    util.put_code(0x9DC1)
-    return SUCCESS
+    return util.put_code(0x9DC1)
 
 
 def mux_ld_addr(label):
     args = label.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     code = util.get_address_of_label(args[0], '')
     if code == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     MUX_LD_ADDR = 0x9F00
-    util.put_code(MUX_LD_ADDR | code)
-    return SUCCESS
+    return util.put_code(MUX_LD_ADDR | code)
 
 
 def mux_map_addr(label):
     args = label.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     code = util.get_address_of_label(args[0], '')
     if code == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     MUX_MAP_ADDR = 0x9F80
-    util.put_code(MUX_MAP_ADDR | code)
-    return SUCCESS
+    return util.put_code(MUX_MAP_ADDR | code)
 
 
 def mux_sel(val):
     args = val.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     MAX_LEDS = 9
     GPO = 16
     led = int(args[0])
     if (led < 0 or (led > MAX_LEDS and led is not GPO)):
-        put_error('invalid argument')
-        return FAILURE
+        return put_error('%d is invalid argument' % led)
 
     MUX_SEL = 0x9D00
-    util.put_code(MUX_SEL | led)
-    return SUCCESS
+    return util.put_code(MUX_SEL | led)
 
 
 def mux_clr(val):
-    util.put_code(0x9D00)
-    return SUCCESS
+    return util.put_code(0x9D00)
 
 
 def mux_ld_start(label):
     args = label.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     code = util.get_address_of_label(args[0], '')
     if code == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     MUX_LD_START = 0x9E00
-    util.put_code(MUX_LD_START | code)
-    return SUCCESS
+    return util.put_code(MUX_LD_START | code)
 
 
 def mux_ld_end(label):
     args = label.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     code = util.get_address_of_label(args[0], '')
     if code == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     MUX_LD_END = 0x9C80
-    util.put_code(MUX_LD_END | code)
-    return SUCCESS
+    return util.put_code(MUX_LD_END | code)
 
 
 def set_pwm(val):
     args = val.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
-    # Format: set_pwm <number>
-    #         set_pwm 'ra' or 'rb' or 'rc' or 'rd'
+    arg = args[0]
+    # Format: set_pwm 'ra' or 'rb' or 'rc' or 'rd'
+    #         set_pwm <number>
     variables = {'ra': 0, 'rb': 1, 'rc': 2, 'rd': 3}
-    index_var = variables.get(args[0])
+    index_var = variables.get(arg)
     if index_var is None:
+        if arg.isdigit() is False:
+            t = util.number_type(arg)
+            types = {'b', 'B', 'h', 'H'}
+            if t not in types:
+                return put_error('%s is invalid argument' % arg)
+
         SET_PWM = 0x4000
-        code = util.format_number(args[0])
-        util.put_code(SET_PWM | code)
-        return SUCCESS
+        code = util.format_number(arg)
+        return util.put_code(SET_PWM | code)
 
     SET_PWM = 0x8460
-    util.put_code(SET_PWM | index_var)
-    return SUCCESS
+    return util.put_code(SET_PWM | index_var)
 
 
 def wait(val):
     args = val.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
-
-    PRESCALE0 = 0.015625
-    PRESCALE1 = 0.5
-    MASTER_FREQ = 32768
-    PRESCALE0_CLK = MASTER_FREQ / 16
-    PRESCALE1_CLK = MASTER_FREQ / 512
-    MAXCODE = 0x1F
-    PRESCALE_CODE = 0x40
+        return put_error('must have one argument')
 
     time = float(args[0])
-
     if time < 0:
-        put_error('time should be positive value')
-        return FAILURE
+        return put_error('time should be positive value')
 
     if time < PRESCALE0:
         code = min(int(round(time * PRESCALE0_CLK, 0)), MAXCODE)
@@ -215,11 +197,9 @@ def wait(val):
         code = min(int(round(time * PRESCALE1_CLK, 0)), MAXCODE)
         code = PRESCALE_CODE | (code << 1)
     else:
-        put_error('time should be less than 0.48')
-        return FAILURE
+        return put_error('time should be less than 0.48')
 
-    util.put_code(code << 8)
-    return SUCCESS
+    return util.put_code(code << 8)
 
 
 # Format: ramp <time>, <pwm>
@@ -232,29 +212,21 @@ def ramp(val):
     args = val.split(',')
     if len(args) == 2:        # format : ramp <time>, <pwm>
         # Remove space and check whether it is digit or not
-        if util.is_float(args[0].split()[0]):
-            time = float(args[0].split()[0])
-            pwm = int(args[1].split()[0])
+        stime = args[0].split()[0]
+        spwm = args[1].split()[0]
+        if util.is_float(stime):
+            time = float(stime)
+            pwm = int(spwm)
 
             if time < 0:
-                put_error('time should be positive value')
-                return FAILURE
+                return put_error('time should be positive value')
 
             if (pwm < -255 or pwm > 255):
-                put_error('should be -255 <= pwm <= 255')
-                return FAILURE
+                return put_error('%d is out of range. -255 <= value <= 255'
+                                  % pwm)
 
             if pwm == 0:
-                put_error('should not zero')
-                return FAILURE
-
-            PRESCALE0 = 0.015625
-            PRESCALE1 = 0.5
-            MASTER_FREQ = 32768
-            PRESCALE0_CLK = MASTER_FREQ / 16
-            PRESCALE1_CLK = MASTER_FREQ / 512
-            MAXCODE = 0x1F
-            PRESCALE_CODE = 0x40
+                return put_error('%d is invalid. should not zero' % pwm)
 
             time = time / abs(pwm)
             if time < PRESCALE0:
@@ -264,26 +236,22 @@ def ramp(val):
                 code = min(int(round(time * PRESCALE1_CLK, 0)), MAXCODE)
                 code = PRESCALE_CODE | (code << 1)
             else:
-                put_error('time should be less than 0.48')
-                return FAILURE
+                return put_error('too long time')
 
             NEGATIVE = 0x01
             if pwm < 0:
                 code = code | NEGATIVE
 
-            util.put_code((code << 8) | abs(pwm))
-            return SUCCESS
+            return util.put_code((code << 8) | abs(pwm))
         else:
-            put_error('invalid value')
-            return FAILURE
+            return put_error('invalid value')
     elif len(args) == 3:        # format : ramp <var1>, <prescale>, <var2>
         # Step time
         var1 = args[0].split()[0]
         variables = {'ra': 0x0, 'rb': 0x04, 'rc': 0x08, 'rd': 0x0C}
         step_time = variables.get(var1)
         if step_time is None:
-            put_error('%s is invalid argument' % var1)
-            return FAILURE
+            return put_error('%s is invalid argument' % var1)
 
         # Prescale
         if args[1].split()[0] == 'pre=0':
@@ -291,8 +259,7 @@ def ramp(val):
         elif args[1].split()[0] == 'pre=1':
             prescale = 1 << 4
         else:
-            put_error('%s is invalid argument' % prescale)
-            return FAILURE
+            return put_error('%s is invalid argument' % args[1].split()[0])
 
         # Sign bit and number of increments
         var2 = args[2].split()[0]
@@ -300,15 +267,12 @@ def ramp(val):
                      '-ra': 0x10, '-rb': 0x11, '-rc': 0x12, '-rd': 0x13}
         sign_and_inc = variables.get(var2)
         if sign_and_inc is None:
-            put_error('%s is invalid argument' % var2)
-            return FAILURE
+            return put_error('%s is invalid argument' % var2)
 
         RAMP = 0x8400
-        util.put_code(RAMP | prescale | sign_and_inc | step_time)
-        return SUCCESS
+        return util.put_code(RAMP | prescale | sign_and_inc | step_time)
 
-    put_error('invalid arguments')
-    return FAILURE
+    return put_error('invalid arguments')
 
 
 # Convert ds argument to offset
@@ -322,22 +286,20 @@ def get_offset_size(val):
 def ds(val):
     size = get_offset_size(val)
     if size < 0:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
 
     for i in range(0, size):
         util.put_code(0x0000)
-    return SUCCESS
+    return True
 
 
 def dw(val):
     args = val.split()
     if len(args) != 1:
-        put_error('must have one argument')
-        return FAILURE
+        return put_error('must have one argument')
+
     code = util.format_number(args[0])
-    util.put_code(code)
-    return SUCCESS
+    return util.put_code(code)
 
 
 # Format: branch <number>, label
@@ -345,20 +307,19 @@ def dw(val):
 def branch(val):
     args = val.split(',')
     if len(args) != 2:
-        put_error('must have two arguments')
-        return FAILURE
+        return put_error('must have two arguments')
 
     # Remove space and check whether it is digit or not
     if args[0].split()[0].isdigit():
         loop_count = int(args[0].split()[0])
         if (loop_count < 0 or loop_count > 64):
-            put_error('0 <= loop count <= 63')
-            return FAILURE
+            return put_error('%d is out of range. 0 <= loop count <= 63'
+                              % loop_count)
 
         label = args[1].split()[0]
         step_no = util.get_offset_address_of_label(label)
         if step_no == util.INVALID_ADDR:
-            return FAILURE
+            return False
 
         BRANCH = 0xA000
         word = (BRANCH | (loop_count << 7) | (step_no & 0x7F))
@@ -366,56 +327,47 @@ def branch(val):
         variables = {'ra': 0, 'rb': 1, 'rc': 2, 'rd': 3}
         index_var = variables.get(args[0].split()[0])
         if index_var is None:
-            put_error('%s is invalid argument' % args[0].split()[0])
-            return FAILURE
+            return put_error('%s is invalid argument' % args[0].split()[0])
 
         label = args[1].split()[0]
         step_no = util.get_offset_address_of_label(label)
         if step_no == util.INVALID_ADDR:
-            return FAILURE
+            return False
 
         BRANCH = 0x8600
         word = (BRANCH | (step_no << 2) | index_var)
 
-    util.put_code(word)
-    return SUCCESS
+    return util.put_code(word)
 
 
 def reset(val):
-    util.put_code(0x0000)
-    return SUCCESS
+    return util.put_code(0x0000)
 
 
 def interrupt(val):
-    util.put_code(0xC400)
-    return SUCCESS
+    return util.put_code(0xC400)
 
 
 def end(val):
     args = val.split()
     if len(args) == 0:    # format: 'end'
-        util.put_code(0xC000)
-        return SUCCESS
+        return util.put_code(0xC000)
 
     args = args[0].split(',')
     num_args = len(args)
     if num_args == 1:        # format: 'end i' or 'end r'
         arg = args[0]
         if arg == 'i':
-            util.put_code(0xD000)
-            return SUCCESS
+            return util.put_code(0xD000)
         elif arg == 'r':
-            util.put_code(0xC800)
-            return SUCCESS
+            return util.put_code(0xC800)
     elif num_args == 2:        # format: 'end i,r' or 'end r,i'
         arg1 = args[0]
         arg2 = args[1]
         if (arg1 == 'i' and arg2 == 'r') or (arg1 == 'r' and arg2 == 'i'):
-            util.put_code(0xD800)
-            return SUCCESS
+            return util.put_code(0xD800)
 
-    put_error('invalid argument')
-    return FAILURE
+    return put_error('invalid argument')
 
 
 # Generate trigger code
@@ -454,12 +406,10 @@ def trigger(val):
         s_code = get_trigger_code(val[idx_start:])
 
     if idx_wait < 0 and idx_start < 0:
-        put_error('invalid argument')
-        return FAILURE
+        return put_error('invalid argument')
 
     TRIGGER = 0xE000
-    util.put_code(TRIGGER | (w_code << 7) | (s_code << 1))
-    return SUCCESS
+    return util.put_code(TRIGGER | (w_code << 7) | (s_code << 1))
 
 
 # Common function for jne, jl, jge and je
@@ -467,8 +417,7 @@ def trigger(val):
 def jump(val, action):
     args = val.split(',')
     if len(args) != 3:
-        put_error('must have three arguments')
-        return FAILURE
+        return put_error('must have three arguments')
 
     # Check the 1st and 2nd argument are variable or not
     var1 = args[0].split()[0]
@@ -476,30 +425,26 @@ def jump(val, action):
     variables = {'ra': 0, 'rb': 1, 'rc': 2, 'rd': 3}
     index_var1 = variables.get(var1)
     if index_var1 is None:
-        put_error('%s is invalid argument' % var1)
-        return FAILURE
+        return put_error('%s is invalid argument' % var1)
 
     index_var2 = variables.get(var2)
     if index_var2 is None:
-        put_error('%s is invalid argument' % var2)
-        return FAILURE
+        return put_error('%s is invalid argument' % var2)
 
     # Check the 3rd is label or not
     var3 = args[2].split()[0]
     addr = util.get_address_of_label(var3, "")
     if addr == util.INVALID_ADDR:
-        return FAILURE
+        return False
 
     cmds = {'jne': 0x8800, 'jl': 0x8A00, 'jge': 0x8C00, 'je': 0x8E00}
     code = cmds.get(action)
     if code is None:
-        put_error('%s is invalid argument' % code)
-        return FAILURE
+        return put_error('%s is invalid argument' % action)
 
     offset = abs(addr - util.get_sram_address()) - 1
     word = (code | (offset << 4) | (index_var1 << 2) | index_var2)
-    util.put_code(word)
-    return SUCCESS
+    return util.put_code(word)
 
 
 def jne(val):
@@ -521,27 +466,23 @@ def je(val):
 def ld(val):
     args = val.split(',')
     if len(args) != 2:
-        put_error('must have two arguments')
-        return FAILURE
+        return put_error('must have two arguments')
 
     # Check the 1st argument is variable or not
     var = args[0].split()[0]
     target = {'ra': 0, 'rb': 1, 'rc': 2}
     index = target.get(var)
     if index is None:
-        put_error('%s is invalid argument' % var)
-        return FAILURE
+        return put_error('%s is invalid argument' % var)
 
     # Check the 2nd argument is valid or not
     val = util.format_number(args[1].split()[0])
     if val < 0 or val > 255:
-        put_error('0 <= value <=255')
-        return FAILURE
+        return put_error('%d is out of range. 0 <= value <=255' % val)
 
     LD = 0x9000
     word = (LD | (index << 10) | val)
-    util.put_code(word)
-    return SUCCESS
+    return util.put_code(word)
 
 
 # Common function for 'add' and 'sub'
@@ -556,20 +497,17 @@ def add_or_sub(val, action):
         target = {'ra': 0, 'rb': 1, 'rc': 2}
         index = target.get(var)
         if index is None:
-            put_error('%s is invalid argument' % var)
-            return FAILURE
+            return put_error('%s is invalid argument' % var)
 
         # Check the 2nd argument is valid or not
         val = util.format_number(args[1].split()[0])
         if (val < 0 or val > 255):
-            put_error('0 <= value <=255')
-            return FAILURE
+            return put_error('%d is out of range. 0 <= value <=255' % val)
 
         cmds = {'add': 0x9100, 'sub': 0x9200}
         code = cmds.get(action)
         if code is None:
-            put_error('%s is invalid argument' % code)
-            return FAILURE
+            return put_error('%s is invalid argument' % action)
 
         word = (code | (index << 10) | val)
         util.put_code(word)
@@ -579,8 +517,7 @@ def add_or_sub(val, action):
         target = {'ra': 0, 'rb': 1, 'rc': 2}
         index_var1 = target.get(var1)
         if index_var1 is None:
-            put_error('%s is invalid argument' % var1)
-            return FAILURE
+            return put_error('%s is invalid argument' % var1)
 
         # Check the others are variable or not
         var2 = args[1].split()[0]
@@ -588,26 +525,21 @@ def add_or_sub(val, action):
         others = {'ra': 0, 'rb': 1, 'rc': 2, 'rd': 3}
         index_var2 = others.get(var2)
         if index_var2 is None:
-            put_error('%s is invalid argument' % var2)
-            return FAILURE
+            return put_error('%s is invalid argument' % var2)
+
         index_var3 = others.get(var3)
         if index_var3 is None:
-            put_error('%s is invalid argument' % var3)
-            return FAILURE
+            return put_error('%s is invalid argument' % var3)
 
         cmds = {'add': 0x9300, 'sub': 0x9310}
         code = cmds.get(action)
         if code is None:
-            put_error('%s is invalid argument' % code)
-            return FAILURE
+            return put_error('%s is invalid argument' % action)
 
         word = (code | (index_var1 << 10) | (index_var2 << 2) | index_var3)
-        util.put_code(word)
+        return util.put_code(word)
     else:
-        put_error('invalid arguments')
-        return FAILURE
-
-    return SUCCESS
+        return put_error('invalid arguments')
 
 
 def add(val):
@@ -662,9 +594,9 @@ commands = {
 def lookup_command(cmd, action):
     # Skip checking if the command is space character
     if len(cmd.split()) == 0:
-        return SUCCESS
+        return True
 
-    for key, func in commands.iteritems():
+    for key, func in six.iteritems(commands):
         if cmd.split()[0] == key:
             # Two actions are allowed when the command is matched
             # - create_label: just increase SRAM address for next use
@@ -672,41 +604,45 @@ def lookup_command(cmd, action):
             if action == 'create_label':
                 # .segment command does not require SRAM address increment
                 if key == '.segment':
-                    return SUCCESS
+                    return True
 
                 # ds command needs to update SRAM size offset
                 if key == 'ds':
-                    size = get_offset_size(cmd.split(key)[1])
+                    arg = cmd.split(key)[1]
+                    size = get_offset_size(arg)
                     if size < 0:
-                        put_error("wrong size information")
-                        return FAILURE
+                        return put_error("wrong size information")
+
                     for x in range(0, size):
-                        util.inc_sram_address()
-                    return SUCCESS
+                        if util.inc_sram_address() is False:
+                            return put_error("code size should be less than %d"
+                                              % util.MAX_SRAM_SIZE)
+
+                    return True
 
                 # Other commands, just increase SRAM address
-                util.inc_sram_address()
-                return SUCCESS
+                if util.inc_sram_address() is False:
+                    return put_error("code size should be less than %d"
+                                      % util.MAX_SRAM_SIZE)
+
+                return True
             elif action == 'generate_code':
                 arg = cmd.split(key)[1]
-                return func(arg)
+                return func(arg)        # call a function
 
-    put_error("%s command is not found" % cmd)
-    return CMD_NOT_FOUND
+    return put_error("%s command is not found" % cmd)
 
 
 # Line format
 #
-# COMMAND COMMAND ARGUMENTS(S)
-# LABEL:    COMMAND ARGUMENT(S)
+# COMMAND ARGUMENTS(S)              'COMMAND format'
+# LABEL:    COMMAND ARGUMENT(S)     'LABEL format'
 def parse_line(string, action):
     LABEL = ":"
     index = string.find(LABEL)
     if index > 0:    # LABEL format
         if action == 'create_label':
             util.add_label_list(string[:index])
-        ret = lookup_command(string[index + 1:], action)
+        return lookup_command(string[index + 1:], action)
     else:              # COMMAND format
-        ret = lookup_command(string, action)
-
-    return ret
+        return lookup_command(string, action)
index 7f3e54c79d8abcc7008a48108c5fb0761ea4cb01..cbe2594e1d7ac66d26786aa06edeaee0e3dd3be8 100644 (file)
 #
 
 import inspect
+import six           # support compatibility between Python 2.x and 3
 
-segment_addr = 0
-sram_addr = 0
+segment_addr = 0     # mapping segment to SRAM address
+sram_addr = 0        # LP5523 SRAM offset from 0 to 95
 MAX_SRAM_SIZE = 96
+INVALID_ADDR = 0xFF
 
 segments = {}        # { "segment":address}
 labels = {}          # { "key":address }
 errors = {}          # { command: error }
 codes = []           # output program code
-INVALID_ADDR = 0xFF
 
 LF = '\n'
-CRLF = '\r\n'
+CRLF = '\r\n'        # .hex should be Windows format due to LP5523.exe
 
 
 #
@@ -46,12 +47,14 @@ def put_error(command, message):
 
 # Print out errors
 def report_error(ln, line):
-    for cmd, msg in errors.iteritems():
-        print """
+    for cmd, msg in six.iteritems(errors):
+        six.print_(
+        """
         Error! Line number: %d
         %s
-        %s %s
+        [%s] %s
         """ % (ln, line, cmd, msg)
+        )
 
 
 #
@@ -68,9 +71,14 @@ def init_segment():
 # Add segment structure
 # Format: { segment name:address }
 def add_segment_list(name):
+    for x in segments:
+        if segments.get(name) is not None:
+            return False
+
     global segment_addr
     segment_addr = get_sram_address()
     segments.update({name: segment_addr})
+    return True
 
 
 # Return the address of the latest segment
@@ -90,10 +98,16 @@ def init_sram_address():
 
 
 # Increase SRAM address
+# Return false if address is out of range
 def inc_sram_address():
     global sram_addr
     sram_addr += 1
 
+    if sram_addr > MAX_SRAM_SIZE:
+        return False
+    else:
+        return True
+
 
 # Get SRAM address
 def get_sram_address():
@@ -112,10 +126,11 @@ def init_code():
 
 
 # Put word bytes
+# Return true/false
 def put_code(word):
     codes.append((word & 0xFF00) >> 8)
     codes.append(word & 0x00FF)
-    inc_sram_address()
+    return inc_sram_address()
 
 
 #
@@ -130,7 +145,8 @@ def init_label_list():
 
 # Add label information
 # Format: { label name:address }
-def add_label_list(key):
+def add_label_list(name):
+    key = name.split()[0]
     addr = get_sram_address()
     labels.update({key: addr})
 
@@ -145,7 +161,7 @@ def get_address_of_label(label, func_name):
     if not func_name:
         func_name = get_caller_func_name()
 
-    put_error(func_name, 'can not find %s' % label)
+    put_error(func_name, 'can not find \'%s\'' % label)
     return INVALID_ADDR
 
 
@@ -190,9 +206,9 @@ def generate_bin(src):
     fname = src[:-3] + 'bin'
     f = open(fname, 'w')
 
-    # Update segment code
-    for item in segments:
-        bits = bin_format(segments.get(item), 8)
+    # Update segment address
+    for addr in sorted(segments.values()):
+        bits = bin_format(addr, 8)
         f.write(bits)
         f.write(LF)
 
@@ -252,10 +268,11 @@ def generate_hex(src):
             if count % 16 == 0:
                 f.write(CRLF)
 
-    # Update segment code
-    for item in segments:
-        code = hex_format(segments.get(item))
-        form = "@ %s %s" % (code, item)
+    # Update segment name and address
+    for addr in sorted(segments.values()):
+        segname = [key for key, value in six.iteritems(segments)
+                if value == addr][0]
+        form = "@ %s %s" % (hex_format(addr), segname)
         f.write(form)
         f.write(CRLF)
 
diff --git a/lasm.py b/lasm.py
index 94adfb3e1e18a2588f206178df46cfbb2a0f1246..01575c9721456700d67be96c1825dc4776c074c7 100644 (file)
--- a/lasm.py
+++ b/lasm.py
@@ -23,6 +23,7 @@
 #
 
 import os
+import six                    # support compatibility between Python 2.x and 3
 import sys
 import _lasm_cmd_parser as cp
 import _lasm_utils as util
@@ -48,12 +49,15 @@ def readline_without_comment(line):
     return line
 
 
+# Error format
 def error(argv):
-    print """
+    six.print_(
+    """
     Argument error: %s
     Usage: python lasm.py -f <src file name>
            python lasm.py -d <directory name>
     """ % str(argv)
+    )
 
 
 # Initialize data structures
@@ -77,12 +81,12 @@ def process_from_file(src):
             if is_comment(line):
                 continue
             line = readline_without_comment(line)
-            err = cp.parse_line(line, action)
-            if err < 0:
+            ret = cp.parse_line(line, action)
+            if ret is False:
                 util.report_error(ln, line)
                 break
 
-        if err < 0:
+        if ret is False:
             return False
 
     # Generate output files
@@ -96,8 +100,7 @@ def process_from_directory(dir):
     for f in os.listdir(dir):
         fullpath = dir + f
         if os.path.isfile(fullpath) and f[-3:] == 'src':
-            err = process_from_file(fullpath)
-            if err < 0:
+            if process_from_file(fullpath) is False:
                 return False
 
     return True