Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

JF v3.2 i2c support #252

Merged
merged 10 commits into from Jun 20, 2020
@@ -18,6 +18,8 @@
#define II_MAX_RECEIVE_LEN 10
#define II_QUEUE_LENGTH 16
#define II_GET 128 // cmd >= are getter requests
#define II_TT_VOLT ((float)1638.3)
#define II_TT_iVOLT ((float)1.0/II_TT_VOLT)


///////////////////////////
@@ -324,7 +326,7 @@ static float decode( uint8_t* data, ii_Type_t type )
case ii_s16V:
u16 = ((uint16_t)*data++)<<8;
u16 |= *data++;
val = ((float)*(int16_t*)&u16)/1638.4; // Scale Teletype down to float
val = ((float)*(int16_t*)&u16)*II_TT_iVOLT; // Scale Teletype down to float
break;
case ii_float:
val = *(float*)data;
@@ -352,7 +354,7 @@ static uint8_t encode( uint8_t* dest, ii_Type_t type, float data )
d[len++] = (uint8_t)(u16 & 0x00FF); // Low byte
break;
case ii_s16V:
data *= 1638.4; // Scale float up to Teletype
data *= II_TT_VOLT; // Scale float up to Teletype
// FLOWS THROUGH
case ii_s16:
s16 = (int16_t)lim_f(data, -32768.0, 32767.0);
@@ -11,8 +11,8 @@
I2S_HandleTypeDef dac_i2s;

// pointer to the malloc()d buffer from DAC_Init()
uint32_t samp_count;
uint32_t* samples;
uint32_t samp_count = 0;
uint32_t* samples = NULL;

#define DAC_ZERO_VOLTS ((uint16_t)(((uint32_t)0xFFFF * 2)/3))
#define DAC_V_TO_U16 ((float)(65535.0 / 15.0))
@@ -17,6 +17,7 @@ typedef enum{ OP_NULL
, OP_FOLLOW_TX
, OP_FOLLOW_TX_READY
, OP_FOLLOW_RX
, OP_ABORT
} I2C_OP_t;

typedef struct{
@@ -184,7 +185,31 @@ void I2C_SetAddress( uint8_t address )
////////////////////////////
// leader set/get

int I2C_is_ready( void ){ return (buf.operation == OP_LISTEN); }
#define I2C_READY_TIMEOUT 20000
int timeout = I2C_READY_TIMEOUT;

int I2C_is_ready( void )
{
switch( buf.operation ){
case OP_LISTEN:
timeout = I2C_READY_TIMEOUT;
break;

case OP_ABORT:
case OP_NULL:
// waiting
break;

default: // all others
if( --timeout <= 0 ){
printf("timeout\n");
buf.operation = OP_ABORT;
HAL_I2C_Master_Abort_IT( &i2c_handle, buf.address );
}
break;
}
return (buf.operation == OP_LISTEN);
}

int I2C_LeadTx( uint8_t address
, uint8_t* data
@@ -194,6 +219,7 @@ int I2C_LeadTx( uint8_t address
address <<= 1;
int error = 0;
if( buf.operation == OP_LISTEN ){
buf.address = address; // save in case of abort
BLOCK_IRQS(
if( HAL_I2C_DisableListen_IT( &i2c_handle ) != HAL_OK ){ error |= 1; }
if( HAL_I2C_Master_Transmit_IT( &i2c_handle
@@ -398,3 +424,10 @@ void HAL_I2C_ErrorCallback( I2C_HandleTypeDef* h )
}
HAL_I2C_ListenCpltCallback( &i2c_handle ); // Re-enable Listen
}

void HAL_I2C_AbortCpltCallback( I2C_HandleTypeDef* h )
{
printf("aborted\n");
timeout = I2C_READY_TIMEOUT;
HAL_I2C_ListenCpltCallback( &i2c_handle );
}
@@ -6,23 +6,27 @@ do return
, commands =
{ { name = 'trigger'
, cmd = 1
, get = true
, docs = 'Set TRIGGER *channel* to *state*'
, args = { { 'channel', s8 }
, { 'state', s8 }
}
}
, { name = 'run_mode'
, cmd = 2
, get = true
, docs = 'Activate RUN if *mode* is non-zero'
, args = { 'mode', s8 }
}
, { name = 'run'
, cmd = 3
, get = true
, docs = 'Set RUN value to *volts*. Requires run_mode(1)'
, args = { 'volts', s16V }
}
, { name = 'transpose'
, cmd = 4
, get = true
, docs = 'Add *pitch* to the current TIME setting'
, args = { 'pitch', s16V }
}
@@ -35,11 +39,13 @@ do return
}
, { name = 'mode'
, cmd = 6
, get = true
, docs = 'If *mode* is non-zero, enter Synthesis / Geode'
, args = { 'mode', s8 }
}
, { name = 'tick'
, cmd = 7
, get = true
, docs = 'Set geode tempo to *bpm*, or accept *clock* for geode'
, args = { 'clock_or_bpm', s8 }
}
@@ -48,20 +54,21 @@ do return
, docs = 'Synthesis: Set *channel* to *pitch* at *level*\n\r' ..
'Geode: At *channel* make *repeats* envs with *divs* time'
, args = { { 'channel', s8 }
, { 'pitch_divs', s16V }
, { 'level_repeats', s16V }
, { 'pitch_or_divs', s16V }
, { 'level_or_repeats', s16V }
}
}
, { name = 'play_note'
, cmd = 9
, docs = 'Synthesis: Assign a note with *pitch* at *level*\n\r' ..
'Geode: Create *repeats* envelopes with *divs* timing'
, args = { { 'pitch_divs', s16V }
, { 'level_repeats', s16V }
, args = { { 'pitch_or_divs', s16V }
, { 'level_or_repeats', s16V }
}
}
, { name = 'god_mode'
, cmd = 10
, get = true
, docs = 'If *state* is non-zero, shift pitch base to A=432Hz'
, args = { 'state', s8 }
}
@@ -75,9 +82,60 @@ do return
}
, { name = 'quantize'
, cmd = 12
, get = true
, docs = 'Quantize commands to every (bar/*divisions*)'
, args = { 'divisions', s8 }
}
, { name = 'pitch'
, cmd = 13
, docs = 'Synthesis: Set *channel* to *pitch*'
, args = { { 'channel', s8 }
, { 'pitch', s16V }
}
}
, { name = 'address'
, cmd = 14
, get = true
, docs = 'Set i2c address to *index* (default)1 or 2'
, args = { 'index', s8 }
}
}
, getters =
{ { name = 'speed'
, cmd = 15 + get_offset
, docs = 'Speed switch setting: 0 for shape and 1 for sound'
, retval = { 'is_sound', s8 }
}
, { name = 'tsc'
, cmd = 16 + get_offset
, docs = 'MODE switch setting: 0/1/2 for transient/sustain/cycle'
, retval = { 'transient_sustain_cycle', s8 }
}
, { name = 'ramp'
, cmd = 17 + get_offset
, docs = 'knob + cv for RAMP parameter'
, retval = { 'volts', s16V }
}
, { name = 'curve'
, cmd = 18 + get_offset
, docs = 'knob + cv for CURVE parameter'
, retval = { 'volts', s16V }
}
, { name = 'fm'
, cmd = 19 + get_offset
, docs = 'value of FM knob'
, retval = { 'volts', s16V }
}
, { name = 'time'
, cmd = 20 + get_offset
, docs = 'knob + cv for TIME parameter'
, retval = { 'volts', s16V }
}
, { name = 'intone'
, cmd = 21 + get_offset
, docs = 'knob + cv for INTONE parameter'
, retval = { 'volts', s16V }
}
}
}
end
ProTip! Use n and p to navigate between commits in a pull request.