From e3a5a9a6faab47164083abd85f77f644a693794e Mon Sep 17 00:00:00 2001 From: kevin Date: Tue, 24 Nov 2020 08:38:06 -0500 Subject: [PATCH] app/README.md,tiny/README.md,ctrl/READM.md : Initial commit. --- control/README.md | 81 +++++++-------------- control/app/README.md | 1 + control/ctrl/README.md | 23 ++++++ control/tiny/README.md | 157 +++++++++++++++++++++++++++++++++++++++++ 4 files changed, 208 insertions(+), 54 deletions(-) create mode 100644 control/app/README.md create mode 100644 control/ctrl/README.md create mode 100644 control/tiny/README.md diff --git a/control/README.md b/control/README.md index 4c3ac3b..e2354c7 100644 --- a/control/README.md +++ b/control/README.md @@ -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 `` bytes from channel `` - - 'r' - -Write a register value of `` bytes from channel `` - - 'w' ... -# 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 diff --git a/control/app/README.md b/control/app/README.md new file mode 100644 index 0000000..bef198a --- /dev/null +++ b/control/app/README.md @@ -0,0 +1 @@ +# Picadea control and monitor shell diff --git a/control/ctrl/README.md b/control/ctrl/README.md new file mode 100644 index 0000000..8a0d5e9 --- /dev/null +++ b/control/ctrl/README.md @@ -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 `` bytes from a channel beginning at offset = 'offset' + + 'r' + +## Write: Host to Channel + +Write `` bytes from from the host to a channel + + 'w' ... diff --git a/control/tiny/README.md b/control/tiny/README.md new file mode 100644 index 0000000..cd1befe --- /dev/null +++ b/control/tiny/README.md @@ -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 + + + +