TASCII
A native balanced-ternary character set
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
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
| Block | Trits | Category | Rule for the offset |
|---|---|---|---|
| -13 | --- | Control | Device signals (overflow into --0) |
| -12 | --0 | Control | (continuation) |
| -3 | 0-0 | Delimiters | Paired: negate offset = open ↔ close |
| -2 | 0-+ | Spill | Symbols with no family seat |
| -1 | 00- | Symbols | Family = leading trit of the offset |
| 0 | 000 | Neutrals | Nothing → blank → whitespace ramp |
| 1 | 00+ | Digits | Offset = the digit's value (char → int is free) |
| 2 | 0+- | Lowercase | Uppercase with the 3rd block trit negated |
| 3 | 0+0 | vacant | Headroom (the v0.2 fold letters were dropped in v0.3) |
| 4 | 0++ | Uppercase | Offset = signed A to Z |
Value bands, fully disjoint
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 charsNothing, then blank, then whitespace: the amount-of-emptiness ramp.
Control
---/--029 charsDevice signals. NUL, HT, LF and CR moved out to the neutrals, and their old slots stay vacant.
Symbols
00-19 charsOperators, quotes and marks. The family is the leading trit of the offset.
Spill
0-+5 charsSymbols with no family seat.
Delimiters
0-08 charsPaired. Negating the offset flips open and close.
Digits
00+10 charsThe offset is the digit's value, so char to int needs no table.
Uppercase
0++26 charsThe offset is the signed position, A to Z.
Lowercase
0+-26 charsUppercase 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.
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.
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.
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.
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
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.
The offset is the value: +-+ = 9 - 3 + 1 = 7. Converting a digit character to an integer is just reading its low treble.
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.
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
| Plane | Trits | Status | Code points |
|---|---|---|---|
| 0 | 000 | TASCII core · locked; this spec | 729 |
| ±1 to ±6 | 00+..+-000-..-+0 | Reserved · future standard assignment: scripts, trit numerals, math | 8,748 |
| ±7 to ±13 | +-+..+++-+-..--- | Private use · never standardized; define your own | 10,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.
Forks
Settled in v0.3 (2026-09-30)
- 1Plane 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.
- 2Fold 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.