def write(can, computers, output_path=bus_path): header_name = '_CAN_LIBRARY_BUS_H' with open(output_path, 'w') as f: fw = f.write fw(ifndef(header_name)) # Create enum among buses fw('typedef enum {\n') for bus in can.bus: fw('\t' + bus.name + ',\n') fw('} CANlib_Bus_T;\n\n') raw_buses = set() for computer in computers: if not ('can' in computer.participation['name'].keys()): # This computer neither sends nor recieves can messages continue raw_buses |= set( computer.participation['name']['can'].mapping.values()) assert 'INVALID_BUS' not in raw_buses, "INVALID_BUS is a reserved bus name" fw('typedef enum {\n') for bus in raw_buses: fw('\t' + bus + ',\n') fw('\tINVALID_BUS\n} CAN_Raw_Bus_T;\n\n') # Create forms enum for each bus for bus in can.bus: fw('typedef enum {\n') # First frame needs to start at 2, the rest will follow first_frame = True for msg in bus.frame: if is_multplxd(msg): for frame in msg.frame: fw('\t' + coord(bus.name, msg.name, frame.name)) if first_frame: fw(' = 2') first_frame = False fw(',\n') else: fw('\t' + coord(bus.name, msg.name)) if first_frame: fw(' = 2') first_frame = False fw(',\n') fw('} ' + '{}_T;\n\n'.format(coord(bus.name))) fw('{}_T CANlib_Identify_{}(Frame* frame);'.format( coord(bus.name), coord(bus.name, prefix=False)) + '\n\n') fw(endif(header_name))
def msg_handler(frame, name_prepends, fw): fw('typedef struct {\n') for atom in frame.atom: if atom.type.isenum(): enum_name = coord(name_prepends, frame.name, atom.name) + '_T' fw('\t{} {};\n'.format(enum_name, atom.name)) else: fw('\t{} {};\n'.format(atom.type.ctype(), atom.name)) fw('} ' + '{}_T;\n\n'.format(coord(name_prepends, frame.name)))
def single_handler(frame, name_prepends, num_tabs, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw( '\t' * num_tabs + 'case CANlib_{}_key:'.format(tot_name) + '\n' + '\t' * (num_tabs + 1) + 'CANlib_Handle_{}(&frame);\n'.format(tot_name) + '\t' * (num_tabs + 1) + 'break;\n' )
def write_declare(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('CANlib_Transmit_Error_T CANlib_Transmit_{}'.format(tot_name) + '(CANlib_{}_T *type);\n'.format(tot_name)) fw('void CANlib_Pack_{}(CANlib_{}_T *type_in, Frame *can_out);\n'.format( tot_name, tot_name) + 'void CANlib_Unpack_{}(Frame *can_in, CANlib_{}_T *type_out);\n'.format( tot_name, tot_name))
def define_pub_frame(frame, name_prepends, busnm, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('void CANlib_Send_{}(CANlib_{}_T *inp)'.format(tot_name, tot_name) + ' {\n') if frame.period is not None: fw('\tLIMIT(CANlib_{});\n'.format(tot_name)) fw('\tFrame frame;\n' + '\tCANlib_Pack_' + tot_name + '(inp, &frame);\n' + '\tCANlib_TransmitFrame(&frame, ' + busnm + ');\n' '}\n\n')
def write_can_pack(frame, name_prepends, bus_ext, fw, parent_slice=None): is_multplxd_subframe = parent_slice is not None tot_name = coord(name_prepends, frame.name, prefix=False) fw('void CANlib_Pack_' + tot_name + '(CANlib_' + tot_name + '_T *type_in, Frame *can_out)' '{\n\t' 'uint64_t bitstring = 0;' '\n') if is_multplxd_subframe: if True: # TODO: check endianness, like atom.type.endianness == Endianness.LITTLE: # TODO: Actually grab key type fw('\t' 'bitstring = INSERT(CANlib_' + tot_name + '_key, bitstring, ' + str(parent_slice.start) + ', ' + str(parent_slice.length) + ');' '\n\n') write_atoms_pack(fw, frame.atom) length = max(atom.slice.start + atom.slice.length for atom in frame.atom) fw('\t' 'from_bitstring(&bitstring, can_out->data);' '\n') key_name = "" if not is_multplxd_subframe: key_name = coord(name_prepends, frame.name, 'key') else: key_name = coord(name_prepends, 'key') fw('\t' 'can_out->id = {};'.format(key_name) + '\n' '\t' 'can_out->dlc = ' + str(ceil(length / 8)) + ';' '\n' '\t' 'can_out->extended = ' + str(bus_ext).lower() + ';' '\n' '}' '\n\n')
def write_can_unpack(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('void CANlib_Unpack_' + tot_name + '(Frame *can_in, CANlib_' + tot_name + '_T *type_out) {\n' '\t' 'uint64_t bitstring = 0;' '\n' '\t' 'to_bitstring(can_in->data, &bitstring);\n') write_atoms_unpack(fw, frame.atom, tot_name) fw('}' '\n\n')
def msg_handler(frame, name_prepends): attr = None try: attr = getattr(frame, attrnm) except AttributeError as e: if not attrnm in optional_props: raise e if attr is None: if attrnm in optional_props: return else: raise AttributeError('{} missing required attribute {}'.format(frame.name, attrnm)) attr = transform(attr) fw(templ[form].format(coord(name_prepends, frame.name, finalnm), attr))
def multplxd_handler(frame, name_prepends, num_tabs, fw): fw('\t' * num_tabs + 'case {}_key:\n'.format(coord(name_prepends, frame.name))) key_size = ceil(frame.slice.length / 8) * 8 key_name = '_'.join([name_prepends,frame.name, 'key']) fw('\t' * (num_tabs + 1) + 'to_bitstring(frame.data, &bitstring);' '\n') fw( '\t' * (num_tabs + 1) + 'uint{}_t {} = EXTRACT(bitstring, {}, {});\n'.format(key_size, key_name, frame.slice.start, frame.slice.length) + '\t' * (num_tabs + 1) + 'switch(' + key_name + ') {' '\n' ) name_prepends += '_' + frame.name for sub_frame in frame.frame: if is_multplxd(sub_frame): multplxd_handler(sub_frame, name_prepends, num_tabs + 2, fw) else: single_handler(sub_frame, name_prepends, num_tabs + 2, fw) fw('\t' * (num_tabs + 1) + '}\n')
def handle_frame(frame, name_prepends, fw): for atom in frame.atom: tot_name = coord(name_prepends, frame.name, atom.name) if atom.type.isenum(): # Only C++11 feature # fw('typedef enum ' + (atom.type.type + ' ' if atom.type.type else '') + '{\n') fw('typedef enum {\n') for enum in atom.type.enum: assert enum.name != 'NUM_FIELDS' fw(templ['enum'].format(tot_name + '_' + enum.name, enum.value)) fw('\t' + tot_name + '_' + 'NUM_FIELDS\n') fw('} ' + '{}_T;\n\n'.format(tot_name))
def write_atoms_unpack(fw, atoms, tot_name): for atom in atoms: if atom.type.isenum(): enum_name = coord(tot_name, atom.name) + '_T' fw('\t' 'type_out->' + atom.name + ' = (' + enum_name + ')EXTRACT(bitstring, ' + str(atom.slice.start) + ', ' + str(atom.slice.length) + ');' '\n') elif atom.type.type == 'bool': fw('\t' 'type_out->' + atom.name + ' = EXTRACT(bitstring, ' + str(atom.slice.start) + ', ' + str(atom.slice.length) + ');' '\n') else: if atom.type.endianness == Endianness.LITTLE: fw('\t' 'type_out->' + atom.name + ' = ' + swap_endianness_fn(atom.type) + '(EXTRACT(bitstring, ' + str(atom.slice.start) + ', ' + str(atom.slice.length) + '));' '\n') else: if atom.type.issigned(): fw('\t' 'type_out->' + atom.name + ' = SIGN(EXTRACT(bitstring, ' + str(atom.slice.start) + ', ' + str(atom.slice.length) + '), ' + str(atom.slice.length) + ');' '\n') else: fw('\t' 'type_out->' + atom.name + ' = EXTRACT(bitstring, ' + str(atom.slice.start) + ', ' + str(atom.slice.length) + ');' '\n')
def declare_pub_frame(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('void CANlib_Send_{}(CANlib_{}_T *inp);\n'.format(tot_name, tot_name))
def declare_sub_frame(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('extern CANlib_{}_T CANlib_{}_Input;\n'.format(tot_name, tot_name) + 'void CANlib_Handle_{}(Frame *frame);\n'.format(tot_name, tot_name))
def define_struct(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name) fw('{}_T {}_Input;\n'.format(tot_name, tot_name))
def define_sub_frame(frame, name_prepends, fw): tot_name = coord(name_prepends, frame.name, prefix=False) fw('void CANlib_Handle_{}(Frame *frame)'.format(tot_name, tot_name) + ' {\n' + '\tCANlib_Unpack_{}(frame, &CANlib_{}_Input);\n'.format( tot_name, tot_name) + '}\n\n')