app/README.md,tiny/README.md,ctrl/READM.md : Initial commit.

This commit is contained in:
kevin 2020-11-24 08:38:06 -05:00
parent 5008c67002
commit e3a5a9a6fa
4 changed files with 208 additions and 54 deletions

View File

@ -2,19 +2,19 @@ This folder contains the _picadae_ control code.
The _picadae_ control program consists of three parts:
- _tiny_ : Keyboard solenoid driver
- _ctrl_ : Keyboard central controller
- _app_ : Monitor and command utility.
- _tiny_ : [ATtiny85 solenoid driver firmware](tiny/README.md)
- _ctrl_ : [ATmega328 interface unit](ctrl/README.md)
- _app_ : [Python monitor and command utility](app/README.md)
# Architecture
The keyboard control hardware consists of 8 driver boards
mounted above the solenoids on the keyboard assembly.
Each driver board has 11 key driver circuits and can
therefore control 11 piano keys. Each key driver
circuit consists of an ATtiny85 microcontroller
which controls a set of power transistors
which in turn control the state of the solenoid.
The keyboard control hardware consists of 8 driver boards mounted
above the solenoids on the keyboard assembly. Each driver board has
11 key driver circuits which control 11 piano keys. Each key driver
circuit consists of an ATtiny85 microcontroller which controls a set
of power transistors which in turn control the state of the solenoid.
The solenoid can be in one of three states:
- off
@ -25,56 +25,29 @@ The attack state is triggered by pulsing the
the solenoid with a fast (250 microsecond to
30 millisecond) 36 volt pulse. The duration
of the pulse determines the attack dynamic.
The hold state then holds the key down
during the sustain portion of the note.
Longer pulses produce louder notes.
At the end of the attack state the solenoid
transitions into a hold state. During
this time the key is held down with just
enough force to sustain the note.
All 88 ATtiny85 microncontrollers are attached
to a single I2C bus which is shared with
an Arduino Uno. The application computer
communicate with the Uno via
a serial connection. The Uno in turn
translates messages between the
ATtiny85 channel computers and the
application computer.
to a single I2C bus which is mastered by an ATmega328 MCU
which acts as a serial to I2C translator for the host computer.
The host API is implemented as the Python class 'Picadae' in app/picadae_api.py.
The control shell program app/picadae_shell.py shows an example
usage of the API.
# Keyboard central controller : Arduino Uno Serial Interface
Read a register value of `<count>` bytes from channel `<i2c-addr>`
'r' <i2c-addr> <register> <count>
Write a register value of `<count>` bytes from channel `<i2c-addr>`
'w' <i2c-addr> <register> <count> <value-0> <value-1> ... <value-n>
# Keyboard solenoid driver : ATtiny85 Firmware
PWM counter frequency and period.
for each possible `div` setting
with 16 Mhz system clock.
Value | Div | Frequency | Period
------|------|-------------|-------
1 | 1 | 16 M | 62.5 n
2 | 2 | 8 M | 125 n
3 | 4 | 4 M | 250 n
4 | 8 | 2 M | 500 n
5 | 16 | 1 M | 1 u
6 | 32 | 500 K | 2 u
7 | 64 | 250 K | 4 u
8 | 128 | 125 K | 8 u
9 | 256 | 62500 Hz | 16 u
10 | 512 | 31250 Hz | 32 u
11 | 1024 | 15625 Hz | 64 u
12 | 2048 | 7812.5 Hz | 128 u
13 | 4096 | 3906.25 Hz | 256 u
14 | 8192 | 1953.125 Hz | 512 u
15 |16384 | 976.6625 Hz | 1024 u
# Monitor and command utility : Python Utility

1
control/app/README.md Normal file
View File

@ -0,0 +1 @@
# Picadea control and monitor shell

23
control/ctrl/README.md Normal file
View File

@ -0,0 +1,23 @@
# ATmega328 Interface Unit
This MCU acts as a serial to I2C translator for the host
computer. The serial protocol implements two
interfaces. One for read requests and another for write commands.
The data format of the write commands is given
in the ATtiny85 I2C protocol document.
Read requests return blocks of memory begining with the address
specified in the last 'Set read address' command.
## Read: Channel to Host
Read a `<count>` bytes from a channel beginning at offset = 'offset'
'r' <i2c-addr> <offset> <count>
## Write: Host to Channel
Write `<count>` bytes from from the host to a channel
'w' <i2c-addr> <register> <count> <value-0> <value-1> ... <value-n>

157
control/tiny/README.md Normal file
View File

@ -0,0 +1,157 @@
# ATtiny85 I2C protocol
Arguments in curly braces are optional.
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Set hold PWM duty cycle | 0 | (duty) { (freq) { (div) }}
Arguments | Range | Default | Note
----------|-------|---------|------------------------------------------------------
(duty) | 0-255 | 127 | 0=0%, 255=100%
(freq) | 0-255 | 255 | Sets PWM top value
(div) | 1-15 | 5 | Set the PWM base clock frequency (See table below)
PWM frequency and period for each possible (div) setting.
Reg. | | Base |
Value | Div | Frequency | Period
------|------|-------------|-------
1 | 1 | 16 M | 62.5 n
2 | 2 | 8 M | 125 n
3 | 4 | 4 M | 250 n
4 | 8 | 2 M | 500 n
5 | 16 | 1 M | 1 u
6 | 32 | 500 K | 2 u
7 | 64 | 250 K | 4 u
8 | 128 | 125 K | 8 u
9 | 256 | 62500 Hz | 16 u
10 | 512 | 31250 Hz | 32 u
11 | 1024 | 15625 Hz | 64 u
12 | 2048 | 7812.5 Hz | 128 u
13 | 4096 | 3906.25 Hz | 256 u
14 | 8192 | 1953.125 Hz | 512 u
15 |16384 | 976.6625 Hz | 1024 u
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Note on velocity | 1 | (vel)
Arguments | Range | Default | Note
----------|-------|---------|------------------------------------------------------
(vel) | 0-127 | n/a | Note on velocity.
Execute a note onset.
The (vel) value is translated to an attack pulse duration
by looking up the pulse tick count in the velocity table.
Function | Opcode | Arguments
-------------------------|--------|-------------------------------------------------
Note on ticks | 2 | (pulse-ticks-high-byte) (pulse-ticks-low-byte)
Execute a note onset.
The 16 bit attack duration in ticks is calculated from microseconds.
pulse-ticks = (usec / 1e6) * (16e6/256)
Where 16e6 is the system clock frequency and 256 is the timer0 clock divider.
`TCCR0B:C02,C01,C00 = 100b (4)`
ticks to micoseconds:
usecs = (pulse-ticks * 1e6)*(256/16e6)
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Note off | 3 | None
Turn off a sounding note by settting the hold-voltage to 0.
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Set read address | 4 | (src) {(addr)}
Set the source and address of the next I2C read request.
The read can come from one of three memory banks:
Register File, MIDI velocity table or EEPROM.
See the _Memory Location Id_ table below for the (src) id values.
Arguments | Range | Default | Note
------------|-------|---------|-------------------------------------------------------
(src) | 0-2 | n/a | Memory location id. See _Memory Location Id_ table.
(addr) | 0-255 | n/a | Offset from base address set by (src)
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Write memory | 5 |
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Set hold delay | 6 | { high {low}}
Set the length of the delay, in ticks, between when the attack pulse ends and when the
hold voltage is applied.
The high and low byte values are calculated identically to the
attack pulse duration values.
Function | Opcode | Arguments
-------------------------|--------|---------------------------
Set flags variable | 7 | (flags)
7 | 6 | 5 | 4 | 3 | 2 | 1 | 0
-----|-----|-----|-----|-----|-----|-----|-----
n/a | n/a | n/a | n/a | n/a | n/a | n/a | HOA
_HOA_ : Set to apply the hold voltage at the beginning of the attack.
Register file
Address | Label | Note
--------|-----------------|------------------------------------------------------------------------------------------------
0 | Reg_Rd_Addr | Next register file address to read.
1 | Table_Rd_Addr | Next MIDI velocity address to read.
2 | EEPROM_Rd_Addr | Next EEPROM address to read.
3 | Read_Src_Addr | Source of the next I2C read request. See Memory Location Id table below.
4 | Reg_Wr_Addr | Next register file address to write.
5 | Table_Rd_Addr | Next MIDI velocity address to write.
6 | EEPROM_Rd_Addr | Next EEPROM address to write.
7 | Write_Dst_Addr | Destination of the next 'write operation'. See Memory Location id table below.
8 | Tmr_High_Addr | Current attack pulse tick count high byte
9 | Tmr_Low_Addr | Current attack pulse tick count low byte
10 | Tmr_Div_Addr | Attack pulse counter frequency divider.
11 | Pwm_Duty_Addr | Duty cycle of the hold PWM generator
12 | Pwm_Freq_Addr | PWM counter max values. Determines the PWM frequency.
13 | Pwm_Div_Addr | PWM clock divider
14 | State_Addr | Current solenoied state.
15 | Error_Addr | Error status
16 | Max_Tmr_Hi_Addr | Max attack pulse high byte tick count.
17 | Delay_High_Addr | Hold delay onset tick count high byte
18 | Delay_Low_Addr | Hold delay onset tick count low byte
19 | Flags_Addr | Binary variable field.
Memory Location Id table.
Id | Memory | Note
---|----------------|-------------------------------
0 | Register file | See register table file
1 | Velocity table | MIDI velocity to pulse ticks lookup table
2 | EEPROM | EEPROM data memory