Skip to content

Latest commit

 

History

31 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

registers

Typed read/write abstraction for all FANUC robot controller register types, with a bidirectional Karel ↔ TP variable bridge and a GPP template for mapping Karel structs to registers.


Overview

Karel has no native way to read or write FANUC registers without calling raw built-ins (GET_REG, SET_INT_REG, GET_PORT_VAL, etc.) and manually dispatching on register type. This module wraps all of that behind a consistent registers__* API with error checking, comment (label) management, and type-safe getters and setters.

Reach for this module whenever you need to:

  • Read or write R[], SR[], PR[], F[], DI/DO, AI/AO, or other I/O ports from Karel
  • Label registers with string comments visible on the teach pendant
  • Bridge a Karel struct field to/from a TP register (e.g. for operator input via TP)
  • Define a full struct ↔ register mapping declaratively (via regmap)

Note: For position register operations (PR[]) use kl-pose (pose__set_posreg_xyz, pose__get_posreg_xyz, etc.). The registerstp bridge calls those routines internally.


Files

File Purpose
src/registers.kl Core implementation — get/set/comment for all register types
src/registerstp.kl Karel ↔ TP bridge using GET_VAR / SET_VAR
include/registers.klh Public header — import to use registers__* routines
include/register_types.klt Type code constants (DATA_REG, io_din, etc.) — include separately
include/registers.klt Module variable ok : BOOLEAN — included in program block
include/registerstp.klh Public header for registerstp__* routines
lib/regmap.klc GPP class template for struct ↔ register mapping
lib/regmap.klh regmap class interface
lib/regmap.klt map_select_getter / map_select_setter macro definitions
test/test_regist.kl KUnit tests for core register API
test/test_regmap.kl KUnit test for regmap roundtrip
test/test_set_var.tpp TP-Plus test for registerstp bridge
test/test_set_struct.tpp TP-Plus test for regmap from TP side
test/config/testregmap.klt Example regmap config

API Reference

Register Type Constants (include/register_types.klt)

Always %include register_types.klt before using type constants. Do not hardcode integer values.

%include register_types.klt

DATA_REG      -- R[n] numeric registers
DATA_POSREG   -- PR[n] position registers
DATA_STRING   -- SR[n] string registers
INVALIDTYPE   -- sentinel value (17043)

-- I/O type codes (from FANUC kliotyps.kl):
io_din / io_dout     -- DI[n] / DO[n]
io_anin / io_anout   -- AI[n] / AO[n]
io_flag              -- F[n]
io_rdi / io_rdo      -- RI[n] / RO[n]
io_gpin / io_gpout   -- GI[n] / GO[n]
io_uopin / io_uopout -- UI[n] / UO[n]
io_sopin / io_sopout -- SI[n] / SO[n]

Type Enum Conversion

When you have a string code (e.g., from parsing a config file) and need the integer constant:

typ = registers__get_type_enum('DI')   -- returns io_din
str = registers__get_type_name(io_din) -- returns 'DI'

Supported strings: 'R', 'PR', 'SR', 'F', 'DI', 'DO', 'AI', 'AO', 'RI', 'RO', 'GI', 'GO', 'UI', 'UO'

Getters

-- Numeric register R[n]
val_i = registers__get_int(10)       -- R[10] as INTEGER
val_r = registers__get_real(10)      -- R[10] as REAL
is_r  = registers__is_real(10)       -- TRUE if R[10] currently holds REAL
is_i  = registers__is_int(10)        -- TRUE if R[10] currently holds INTEGER

-- String register SR[n]
s = registers__get_string(1)

-- Flag F[n]
b = registers__get_boolean(27)       -- F[27] as BOOLEAN

-- Any I/O port (returns raw integer: 0/1 for digital, scaled for analog)
v = registers__get_io(io_din, 14)    -- DI[14]
v = registers__get_io(io_anin, 2)    -- AI[2]

Setters

registers__set_int(10, 42)
registers__set_real(133, 3.14)
registers__set_string(1, 'job_001')
registers__set_boolean(27, TRUE)            -- F[27]
registers__set_io(io_dout, 3, TRUE)         -- DO[3] = ON

Register Comments (Labels)

Comments appear next to the register number on the teach pendant. Set once at startup; they persist on the controller.

%include register_types.klt

-- Write labels
registers__set_comment(DATA_REG,    10, 'part_count')
registers__set_comment(DATA_POSREG,  4, 'home_pose')
registers__set_comment(DATA_STRING,  1, 'job_name')
registers__set_comment(io_dout,      3, 'laser_enable')

-- Read back
cmt = registers__get_comment(DATA_REG, 10)   -- 'part_count'

-- Clear all R[] labels (values preserved)
registers__clear_comments(DATA_REG, FALSE)

-- Clear labels AND reset R[] values to 0
registers__clear_comments(DATA_REG, TRUE)

TP Interfaces (include/registerstp.klh)

registerstp bridges Karel program variables to FANUC registers so TP programs can read and write them. Uses GET_VAR / SET_VAR built-ins. String limit: 32 characters.

progname = Karel program name. varname = variable name, dot-notation for struct fields (e.g., 'config.step_count').

TP+ call syntax

The package.json exposes these as named TP interfaces:

# Getters — read Karel variable, write to register
intvar = get_kint('<program_name>', '<variable>')
realvar = get_krel('<program_name>', '<variable>')
boolvar = get_kio('<program_name>', '<variable>', 'F')
strvar = get_kstr('<program_name>', '<variable>')
posvar = get_kpos('<program_name>', '<variable>')           # group 1
posvar.group(1) = get_kposgrp('<program_name>', '<variable>')
jntvar = get_kjnt('<program_name>', '<variable>')           # group 1
jntvar.group(1) = get_kjntgrp('<program_name>', '<variable>')

# Setters — read register, write to Karel variable
set_kint(intvar, '<program_name>', '<variable>')
set_krel(realvar, '<program_name>', '<variable>')
set_kbool(boolvar, '<program_name>', '<variable>')
set_kstr(strvar, '<program_name>', '<variable>')
set_kxyz(&posvar, '<program_name>', '<variable>')
set_kjnt(&jntvar, '<program_name>', '<variable>')

Direct Karel use

-- Read Karel variable → register
registerstp__get_karel_int('myapp', 'config.step_count', 5)
registerstp__get_karel_real('myapp', 'speed', 6)
registerstp__get_karel_string('myapp', 'job_name', 1)
registerstp__get_karel_xyz('myapp', 'target_pose', 4, 1)   -- reg 4, group 1
registerstp__get_karel_joint('myapp', 'home_joint', 5, 1)
registerstp__get_karel_io('myapp', 'ready', 'F', 2)

-- Register → Karel variable
registerstp__set_karel_int(registers__get_int(5), 'myapp', 'config.step_count')
registerstp__set_karel_real(registers__get_real(6), 'myapp', 'speed')
registerstp__set_karel_string(registers__get_string(1), 'myapp', 'job_name')
registerstp__set_karel_xyz(pose__get_posreg_xyz(4, 1), 'myapp', 'target_pose')
registerstp__set_karel_joint(pose__get_posreg_joint(5, 1), 'myapp', 'home_joint')
-- Note: set_karel_bool takes INTEGER (0/1), not BOOLEAN
registerstp__set_karel_bool(registers__get_io(io_flag, 2), 'myapp', 'ready')

regmap — Struct ↔ Register Mapping

regmap.klc is a GPP template that maps every field of a Karel struct to a specific register, letting you push or pull the whole struct in one call. It's the right pattern when a TP program needs bidirectional access to a multi-field Karel struct.

Step 1 — Create a config .klt

-- myconfig.klt

%define REGMAP_TYPE t_MY_PARAMS

-- Use REGMAP_STRUCT to define the struct inside the class,
-- or REGMAP_STRUCT_IMPORT to reference an externally defined type.
%define REGMAP_STRUCT `TYPE
  t_MY_PARAMS FROM class_name = STRUCTURE
    laser_power : REAL
    step_count  : INTEGER
    job_name    : STRING[16]
    home_pose   : XYZWPR
    enabled     : BOOLEAN
  ENDSTRUCTURE`

-- REGMAPPGET: struct field → register (args: progname, varname, regtype, reg_id, field, type, group)
%define REGMAPPGET `
  map_select_getter(progname, varname, 'R',  1, 'laser_power', 'REAL',    1)
  map_select_getter(progname, varname, 'R',  2, 'step_count',  'INTEGER', 1)
  map_select_getter(progname, varname, 'SR', 3, 'job_name',    'STRING',  1)
  map_select_getter(progname, varname, 'PR', 4, 'home_pose',   'XYZWPR',  1)
  map_select_getter(progname, varname, 'F',  5, 'enabled',     'BOOLEAN', 1)
`

-- REGMAPPSET: register → struct field (inverse)
%define REGMAPPSET `
  map_select_setter(progname, varname, 'R',  1, 'laser_power', 'REAL',    1)
  map_select_setter(progname, varname, 'R',  2, 'step_count',  'INTEGER', 1)
  map_select_setter(progname, varname, 'SR', 3, 'job_name',    'STRING',  1)
  map_select_setter(progname, varname, 'PR', 4, 'home_pose',   'XYZWPR',  1)
  map_select_setter(progname, varname, 'F',  5, 'enabled',     'BOOLEAN', 1)
`

map_select_getter / map_select_setter argument order: (progname, varname, regtype, register_id, field_name, type_string, group_no)

regtype values: 'R' (numeric), 'SR' (string), 'PR' (position), 'F'/'DI'/'DO'/etc. (I/O)

Step 2 — Instantiate

%class mymap(regmap.klc, regmap.klh, myconfig.klt)

Step 3 — Push / pull

-- All struct fields → their mapped registers
mymap__set_registers('myapp', 'params')

-- All mapped registers → struct fields
mymap__get_registers('myapp', 'out_params')

See test/config/testregmap.klt and test/test_regmap.kl for a complete working example.


Tests

rossum .. -w -o -t
ninja
kpush
kunit
  • test/test_regist.kl — KUnit tests for core register API (R[], F[], comments, type checks)
  • test/test_regmap.kl — KUnit test for regmap struct roundtrip
  • test/test_set_var.tpp — TP-Plus example for registerstp getters/setters
  • test/test_set_struct.tpp — TP-Plus example calling a regmap object

Common Mistakes

Mistake Symptom Fix
registers__get_real on an INTEGER register Wrong value or type abort Use registers__is_real(n) first; always match getter type to setter type
Hardcoding type integer values instead of constants Wrong register type accessed silently %include register_types.klt and use named constants (DATA_REG, io_din, etc.)
Passing a string ('DI') to get_io/set_io INVALIDTYPE with no visible error Use registers__get_type_enum('DI') to convert string → integer
Missing grp_no in map_select_getter for PR fields Wrong motion group on multi-arm controller Supply explicit group number (1-based) as 7th argument
Calling registerstp__set_karel_bool with a BOOLEAN Compiler type error Parameter is INTEGER (0 or 1) — pass registers__get_io(io_flag, n) directly
String values > 32 chars with get_karel_string Silent truncation MAX_STRING = 32 in registerstp — keep SR[] values within that limit
registers__clear_comments(..., TRUE) mid-run Other programs lose R[] values Only use reset_reg=TRUE during initialization, never during operation

Build Flow

registers is a Layer 5 module. It depends on errors, pose, systemlib, TPElib, and ktransw-macros. Modules that depend on it include hash-registers, display, csv, paths/lam, and paths/pathlayer.

regmap.klc is not compiled standalone — it is expanded via %class inside the consumer module's build.

For full build instructions see the Ka-Boost readme.

About

registers library for Fanuc Karel

Resources

Stars

2 stars

Watchers

1 watching

Forks

Releases

Packages

Used by

Contributors

Languages