TASCII

A native balanced-ternary character set

v0.3 working draft

TASCII is a character set designed for balanced ternary, not transcoded from ASCII. Its integer values are native and deliberately not the ASCII code points, so reinterpreting ASCII bits produces garbage and only a semantic remap works. It is the text layer of a ferrite-core ternary computer, a physical project separate from the T-CNN work on this site.

The Unit

trit · 1
-0+
-1, 0 or +1: a sign, not a truth value
treble · 3
---
3 trits, 27 values
dtreble · 6
0++|---
2 trebles, 729 values
tword · 9 = 1 character
000|0++|---
planeblockoffset
3 trebles, 39 = 19,683 code points

Every unit is a whole number of trebles, built up here from the letter A. One character fills exactly one tword, the machine's word size. Every character defined so far lives in plane 000, so its value equals its block|offset dtreble value. The other 26 planes (18,954 code points) are reserved or private use; see the plane registry below.

Block Map

BlockTritsCategoryRule for the offset
-13---ControlDevice signals (overflow into --0)
-12--0Control(continuation)
-30-0DelimitersPaired: negate offset = open ↔ close
-20-+SpillSymbols with no family seat
-100-SymbolsFamily = leading trit of the offset
0000NeutralsNothing → blank → whitespace ramp
100+DigitsOffset = the digit's value (char → int is free)
20+-LowercaseUppercase with the 3rd block trit negated
30+0vacantHeadroom (the v0.2 fold letters were dropped in v0.3)
40++UppercaseOffset = signed A to Z

Value bands, fully disjoint

control -363..-332<delim -85..-77<spill -56..-52<symbol -40..-14<neutral 0..4<digit 27..36<lower 41..66<vacant 68..94<upper 95..120

NUL sits at the origin (0). Everything printable is above it and all machinery is below. The taxonomy is monotonic, and one trit is enough to route a character to its category.

Sort order differs from ASCII: lowercase (41..66) sorts before uppercase (95..120). This is deliberate: lowercase is the case-fold target, and canonical forms sort first. Ported strcmp logic should expect it.

The Full Table · 128 Characters

Select any character to see its plane, block and offset. Dashed slots in the control block are vacant on purpose: the old NUL, HT, LF and CR positions are left as holes, not repacked.

Neutrals

0005 chars

Nothing, then blank, then whitespace: the amount-of-emptiness ramp.

Control

---/--029 chars

Device signals. NUL, HT, LF and CR moved out to the neutrals, and their old slots stay vacant.

block ---
invalid000|---|----364
old HT000|---|0---355
old LF000|---|0-0-354
old CR000|---|000-351
block --0 (continuation)

Symbols

00-19 chars

Operators, quotes and marks. The family is the leading trit of the offset.

family - · ops
family 0 · quotes
family + · marks

Spill

0-+5 chars

Symbols with no family seat.

Delimiters

0-08 chars

Paired. Negating the offset flips open and close.

Digits

00+10 chars

The offset is the digit's value, so char to int needs no table.

Uppercase

0++26 chars

The offset is the signed position, A to Z.

Lowercase

0+-26 chars

Uppercase with the third block trit negated.

Two Negations, One Principle

There is no single global "negate the whole tword." Negating a full tword also flips the block and sends the character to a different category. Instead, negation acts on whichever field carries that block's signed meaning.

Delimiters: negate the offset

Pairs sit at signed offsets ±n. Flipping every offset trit mirrors open into close.

(
000|0-0|00-
offset 00- = -1 · value -82

Letters: the case trit

Case is the third block trit, as a signed quantity. Negate it to flip case; clamp it to - to fold to lowercase for comparison. A t3 of 0 is vacant headroom.

A
000|0++|---
upper, t3 = + · value 95

Full-tword NEG is a type error, and it fails loudly

Negating a whole tword of text is a mistake, and preventing it is software's job, as on any binary machine (nothing stops ~'b' in C either). What TASCII adds is that the mistake is visible.

107
land in vacant space
1
NUL, its own negation
20
swap in 10 pairs

108 of 128 characters cannot be silently corrupted by a stray NEG. Because the map is deterministic (v → -v) and those landing slots are empty, a decoder may even recover: if a tword is invalid but its negation is a valid character, flag a stray negation and restore it. That is a debugging aid for the hand-assembly era, not a guarantee.

The 10 pairs where NEG yields another valid character
$ ↔ p\ ↔ o_ ↔ n| ↔ m~ ↔ l= ↔ 9% ↔ 8^ ↔ 7" ↔ 1' ↔ 0

Eliminating them was considered and rejected: the symbol block holds 19 characters but only 17 slots outside the digits' reflection, so any fix would break family-by-leading-trit or digit offset = value.

Design Notes

Erased memory reads as NUL
000|000|000

A ferrite core rests at 0. NUL is all zeros, so blank cores are already a null-filled buffer, and NUL-terminated strings fall straight out of the hardware.

Digits need no table
7000|00+|+-+

The offset is the value: +-+ = 9 - 3 + 1 = 7. Converting a digit character to an integer is just reading its low treble.

One trit routes a symbol
+000|00-|---
'000|00-|000
!000|00-|+00

Symbol offsets are 9 × family + slot. Since 9 is the leading trit's weight, the family (ops, quotes, marks) is a single-trit read with no range check.

Lossless both ways
128

Exactly ASCII's count, and every character has an ASCII source, so TASCII to ASCII and back loses nothing. The values differ, the repertoire does not: conversion is a table, never a bit trick.

The Plane Registry

PlaneTritsStatusCode points
0000TASCII core · locked; this spec729
±1 to ±600+..+-000-..-+0Reserved · future standard assignment: scripts, trit numerals, math8,748
±7 to ±13+-+..+++-+-..---Private use · never standardized; define your own10,206

Planes are allocated in ± pairs: a plane and its negation belong together, so negating a tword never leaves its allocation. Plane 0 is its own negation, so it has no twin: it is the storage plane, and nothing is transmitted on it. Communication re-planes content into an allocated ± pair.

Build your own plane for your own system. Planes ±7 to ±13 are private use. The standard may later assign the reserved planes, but it will never touch the private ones.

Forks

Settled in v0.3 (2026-09-30)

  1. 1
    Plane promotion: closed. Planes are promoted with the registry above: plane 0 locked, ±1 to ±6 reserved, ±7 to ±13 private use, allocated in ± pairs. Plane-0 values are unchanged.
  2. 2
    Fold letters: closed, dropped. The 26 case-neutral 0+0 letters are removed (154 → 128 characters, exactly ASCII's count; TASCII↔ASCII is now lossless). Case-fold is redefined as clamp t3 to lower, and block 0+0 is vacant headroom.
Still open
3
Word sizing for the machine. Leaning toward a 6-trit address (a dtreble gives native X/Y select on a 27×27 grid; populate about 270 to 277 twords centered on zero and grow by adding rows, since the prime is just a population count, not a layout constraint) over 5-trit/243. Not yet locked.
TASCII v0.3 (2026-09-30). Table generated from tascii.py build_assignments(): 128 characters, each a unique tword and a unique integer.