app/README.md,tiny/README.md,ctrl/READM.md : Initial commit.
This commit is contained in:
parent
5008c67002
commit
e3a5a9a6fa
@ -2,19 +2,19 @@ This folder contains the _picadae_ control code.
|
|||||||
|
|
||||||
The _picadae_ control program consists of three parts:
|
The _picadae_ control program consists of three parts:
|
||||||
|
|
||||||
- _tiny_ : Keyboard solenoid driver
|
- _tiny_ : [ATtiny85 solenoid driver firmware](tiny/README.md)
|
||||||
- _ctrl_ : Keyboard central controller
|
|
||||||
- _app_ : Monitor and command utility.
|
- _ctrl_ : [ATmega328 interface unit](ctrl/README.md)
|
||||||
|
|
||||||
|
- _app_ : [Python monitor and command utility](app/README.md)
|
||||||
|
|
||||||
# Architecture
|
# Architecture
|
||||||
|
|
||||||
The keyboard control hardware consists of 8 driver boards
|
The keyboard control hardware consists of 8 driver boards mounted
|
||||||
mounted above the solenoids on the keyboard assembly.
|
above the solenoids on the keyboard assembly. Each driver board has
|
||||||
Each driver board has 11 key driver circuits and can
|
11 key driver circuits which control 11 piano keys. Each key driver
|
||||||
therefore control 11 piano keys. Each key driver
|
circuit consists of an ATtiny85 microcontroller which controls a set
|
||||||
circuit consists of an ATtiny85 microcontroller
|
of power transistors which in turn control the state of the solenoid.
|
||||||
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:
|
The solenoid can be in one of three states:
|
||||||
|
|
||||||
- off
|
- off
|
||||||
@ -25,56 +25,29 @@ The attack state is triggered by pulsing the
|
|||||||
the solenoid with a fast (250 microsecond to
|
the solenoid with a fast (250 microsecond to
|
||||||
30 millisecond) 36 volt pulse. The duration
|
30 millisecond) 36 volt pulse. The duration
|
||||||
of the pulse determines the attack dynamic.
|
of the pulse determines the attack dynamic.
|
||||||
The hold state then holds the key down
|
Longer pulses produce louder notes.
|
||||||
during the sustain portion of the note.
|
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
|
All 88 ATtiny85 microncontrollers are attached
|
||||||
to a single I2C bus which is shared with
|
to a single I2C bus which is mastered by an ATmega328 MCU
|
||||||
an Arduino Uno. The application computer
|
which acts as a serial to I2C translator for the host computer.
|
||||||
communicate with the Uno via
|
|
||||||
a serial connection. The Uno in turn
|
The host API is implemented as the Python class 'Picadae' in app/picadae_api.py.
|
||||||
translates messages between the
|
The control shell program app/picadae_shell.py shows an example
|
||||||
ATtiny85 channel computers and the
|
usage of the API.
|
||||||
application computer.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
# 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
1
control/app/README.md
Normal file
@ -0,0 +1 @@
|
|||||||
|
# Picadea control and monitor shell
|
23
control/ctrl/README.md
Normal file
23
control/ctrl/README.md
Normal 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
157
control/tiny/README.md
Normal 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
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user