From 690a08cbbbf41300214d9b74daffbbccefab4a87 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 15 Jan 2018 16:06:49 -0500 Subject: [PATCH 01/59] fix up arm audio implementation --- quantum/audio/audio_arm.c | 223 ++++++++++++++++++++++++++++++-------- 1 file changed, 178 insertions(+), 45 deletions(-) diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 43c8d67c48..6f8b5e3078 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -77,23 +77,48 @@ bool glissando = true; #endif float startup_song[][2] = STARTUP_SONG; -static void gpt_cb6(GPTDriver *gptp); -static void gpt_cb7(GPTDriver *gptp); static void gpt_cb8(GPTDriver *gptp); +#define DAC_BUFFER_SIZE 360 + +#define START_CHANNEL_1() gptStart(&GPTD6, &gpt6cfg1); \ + gptStartContinuous(&GPTD6, 2U) +#define START_CHANNEL_2() gptStart(&GPTD7, &gpt7cfg1); \ + gptStartContinuous(&GPTD7, 2U) +#define STOP_CHANNEL_1() gptStopTimer(&GPTD6) +#define STOP_CHANNEL_2() gptStopTimer(&GPTD7) +#define RESTART_CHANNEL_1() STOP_CHANNEL_1(); \ + START_CHANNEL_1() +#define RESTART_CHANNEL_2() STOP_CHANNEL_1(); \ + START_CHANNEL_1() +#define UPDATE_CHANNEL_1_FREQ(freq) gpt6cfg1.frequency = freq * DAC_BUFFER_SIZE; \ + RESTART_CHANNEL_1() +#define UPDATE_CHANNEL_2_FREQ(freq) gpt7cfg1.frequency = freq * DAC_BUFFER_SIZE; \ + RESTART_CHANNEL_2() +#define GET_CHANNEL_1_FREQ gpt6cfg1.frequency +#define GET_CHANNEL_2_FREQ gpt7cfg1.frequency + + /* * GPT6 configuration. */ +// static const GPTConfig gpt6cfg1 = { +// .frequency = 1000000U, +// .callback = NULL, +// .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ +// .dier = 0U +// }; + GPTConfig gpt6cfg1 = { - .frequency = 440, - .callback = gpt_cb6, + .frequency = 440U*DAC_BUFFER_SIZE, + .callback = NULL, .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ .dier = 0U }; GPTConfig gpt7cfg1 = { - .frequency = 440, - .callback = gpt_cb7, + .frequency = 440U*DAC_BUFFER_SIZE, + .callback = NULL, .cr2 = TIM_CR2_MMS_1, /* MMS = 010 = TRGO on Update Event. */ .dier = 0U }; @@ -105,15 +130,122 @@ GPTConfig gpt8cfg1 = { .dier = 0U }; -static void gpt_cb6(GPTDriver *gptp) { - palTogglePad(GPIOA, 4); + +/* + * DAC test buffer (sine wave). + */ +// static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { +// 2047, 2082, 2118, 2154, 2189, 2225, 2260, 2296, 2331, 2367, 2402, 2437, +// 2472, 2507, 2542, 2576, 2611, 2645, 2679, 2713, 2747, 2780, 2813, 2846, +// 2879, 2912, 2944, 2976, 3008, 3039, 3070, 3101, 3131, 3161, 3191, 3221, +// 3250, 3278, 3307, 3335, 3362, 3389, 3416, 3443, 3468, 3494, 3519, 3544, +// 3568, 3591, 3615, 3637, 3660, 3681, 3703, 3723, 3744, 3763, 3782, 3801, +// 3819, 3837, 3854, 3870, 3886, 3902, 3917, 3931, 3944, 3958, 3970, 3982, +// 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4062, 4068, 4074, 4078, +// 4082, 4086, 4089, 4091, 4092, 4093, 4094, 4093, 4092, 4091, 4089, 4086, +// 4082, 4078, 4074, 4068, 4062, 4056, 4049, 4041, 4033, 4024, 4014, 4004, +// 3993, 3982, 3970, 3958, 3944, 3931, 3917, 3902, 3886, 3870, 3854, 3837, +// 3819, 3801, 3782, 3763, 3744, 3723, 3703, 3681, 3660, 3637, 3615, 3591, +// 3568, 3544, 3519, 3494, 3468, 3443, 3416, 3389, 3362, 3335, 3307, 3278, +// 3250, 3221, 3191, 3161, 3131, 3101, 3070, 3039, 3008, 2976, 2944, 2912, +// 2879, 2846, 2813, 2780, 2747, 2713, 2679, 2645, 2611, 2576, 2542, 2507, +// 2472, 2437, 2402, 2367, 2331, 2296, 2260, 2225, 2189, 2154, 2118, 2082, +// 2047, 2012, 1976, 1940, 1905, 1869, 1834, 1798, 1763, 1727, 1692, 1657, +// 1622, 1587, 1552, 1518, 1483, 1449, 1415, 1381, 1347, 1314, 1281, 1248, +// 1215, 1182, 1150, 1118, 1086, 1055, 1024, 993, 963, 933, 903, 873, +// 844, 816, 787, 759, 732, 705, 678, 651, 626, 600, 575, 550, +// 526, 503, 479, 457, 434, 413, 391, 371, 350, 331, 312, 293, +// 275, 257, 240, 224, 208, 192, 177, 163, 150, 136, 124, 112, +// 101, 90, 80, 70, 61, 53, 45, 38, 32, 26, 20, 16, +// 12, 8, 5, 3, 2, 1, 0, 1, 2, 3, 5, 8, +// 12, 16, 20, 26, 32, 38, 45, 53, 61, 70, 80, 90, +// 101, 112, 124, 136, 150, 163, 177, 192, 208, 224, 240, 257, +// 275, 293, 312, 331, 350, 371, 391, 413, 434, 457, 479, 503, +// 526, 550, 575, 600, 626, 651, 678, 705, 732, 759, 787, 816, +// 844, 873, 903, 933, 963, 993, 1024, 1055, 1086, 1118, 1150, 1182, +// 1215, 1248, 1281, 1314, 1347, 1381, 1415, 1449, 1483, 1518, 1552, 1587, +// 1622, 1657, 1692, 1727, 1763, 1798, 1834, 1869, 1905, 1940, 1976, 2012 +// }; + +// squarewave +static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + +/* + * DAC streaming callback. + */ +size_t nx = 0, ny = 0, nz = 0; +static void end_cb1(DACDriver *dacp, const dacsample_t *buffer, size_t n) { + + (void)dacp; + + nz++; + if (dac_buffer == buffer) { + nx += n; + } + else { + ny += n; + } + + if ((nz % 1000) == 0) { + // palTogglePad(GPIOD, GPIOD_LED3); + } } +/* + * DAC error callback. + */ +static void error_cb1(DACDriver *dacp, dacerror_t err) { -static void gpt_cb7(GPTDriver *gptp) { - palTogglePad(GPIOA, 5); + (void)dacp; + (void)err; + + chSysHalt("DAC failure"); } +static const DACConfig dac1cfg1 = { + .init = 2047U, + .datamode = DAC_DHRM_12BIT_RIGHT +}; + +static const DACConversionGroup dacgrpcfg1 = { + .num_channels = 1U, + .end_cb = end_cb1, + .error_cb = error_cb1, + .trigger = DAC_TRG(0) +}; + void audio_init() { @@ -128,8 +260,27 @@ void audio_init() // audio_config.raw = eeconfig_read_audio(); audio_config.enable = true; - palSetPadMode(GPIOA, 4, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 5, PAL_MODE_OUTPUT_PUSHPULL); + /* + * Starting DAC1 driver, setting up the output pin as analog as suggested + * by the Reference Manual. + */ + palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); + palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); + dacStart(&DACD1, &dac1cfg1); + + /* + * Starting GPT6 driver, it is used for triggering the DAC. + */ + START_CHANNEL_1(); + START_CHANNEL_2(); + + /* + * Starting a continuous conversion. + */ + dacStartConversion(&DACD1, &dacgrpcfg1, + (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); + // gptStartContinuous(&GPTD6, 2U); + audio_initialized = true; @@ -193,8 +344,8 @@ void stop_note(float freq) voice_place = 0; } if (voices == 0) { - gptStopTimer(&GPTD6); - gptStopTimer(&GPTD7); + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); gptStopTimer(&GPTD8); frequency = 0; frequency_alt = 0; @@ -224,20 +375,6 @@ float vibrato(float average_freq) { #endif -static void restart_gpt6(void) { - // gptStopTimer(&GPTD6); - - gptStart(&GPTD6, &gpt6cfg1); - gptStartContinuous(&GPTD6, 2U); -} - -static void restart_gpt7(void) { - // gptStopTimer(&GPTD7); - - gptStart(&GPTD7, &gpt7cfg1); - gptStartContinuous(&GPTD7, 2U); -} - static void gpt_cb8(GPTDriver *gptp) { float freq; @@ -280,13 +417,12 @@ static void gpt_cb8(GPTDriver *gptp) { freq_alt = 30.52; } - if (gpt6cfg1.frequency != (uint16_t)freq_alt) { - gpt6cfg1.frequency = freq_alt; - restart_gpt6(); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq_alt) { + UPDATE_CHANNEL_1_FREQ(freq_alt); } //note_timbre; } else { - // gptStopTimer(&GPTD6); + STOP_CHANNEL_1(); } if (polyphony_rate > 0) { @@ -342,9 +478,8 @@ static void gpt_cb8(GPTDriver *gptp) { } - if (gpt7cfg1.frequency != (uint16_t)freq) { - gpt7cfg1.frequency = freq; - restart_gpt7(); + if (GET_CHANNEL_2_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_2_FREQ(freq); } //note_timbre; } else { @@ -370,11 +505,9 @@ static void gpt_cb8(GPTDriver *gptp) { freq = voice_envelope(freq); - if (gpt6cfg1.frequency != (uint16_t)freq) { - gpt6cfg1.frequency = freq; - restart_gpt6(); - gpt7cfg1.frequency = freq; - restart_gpt7(); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); + UPDATE_CHANNEL_2_FREQ(freq); } //note_timbre; } else { @@ -384,7 +517,7 @@ static void gpt_cb8(GPTDriver *gptp) { note_position++; bool end_of_note = false; - if (gpt6cfg1.frequency > 0) { + if (GET_CHANNEL_1_FREQ > 0) { if (!note_resting) end_of_note = (note_position >= (note_length*16 - 1)); else @@ -399,8 +532,8 @@ static void gpt_cb8(GPTDriver *gptp) { if (notes_repeat) { current_note = 0; } else { - gptStopTimer(&GPTD6); - gptStopTimer(&GPTD7); + STOP_CHANNEL_1(); + STOP_CHANNEL_2(); // gptStopTimer(&GPTD8); playing_notes = false; return; @@ -492,8 +625,8 @@ void play_notes(float (*np)[][2], uint16_t n_count, bool n_repeat) gptStart(&GPTD8, &gpt8cfg1); gptStartContinuous(&GPTD8, 2U); - restart_gpt6(); - restart_gpt7(); + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); } } From 31df12c84fc5bf2e938394b026d9027aa881e71b Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 26 Jan 2018 23:56:48 -0500 Subject: [PATCH 02/59] chibios stack size inc --- tmk_core/chibios.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index cb0482d757..bc3097f4b2 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -6,7 +6,7 @@ # Stack size to be allocated to the Cortex-M process stack. This stack is # the stack used by the main() thread. ifeq ($(USE_PROCESS_STACKSIZE),) - USE_PROCESS_STACKSIZE = 0x200 + USE_PROCESS_STACKSIZE = 0x800 endif # Stack size to the allocated to the Cortex-M main/exceptions stack. This From 2165f9d654a3c44fc51f2e6638807f1be21ff9da Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sat, 27 Jan 2018 02:05:09 -0500 Subject: [PATCH 03/59] get one channel working --- quantum/audio/audio_arm.c | 69 ++++++++++++++++++++++++++++++++------- 1 file changed, 58 insertions(+), 11 deletions(-) diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 6f8b5e3078..f5ca417ba5 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -89,8 +89,8 @@ static void gpt_cb8(GPTDriver *gptp); #define STOP_CHANNEL_2() gptStopTimer(&GPTD7) #define RESTART_CHANNEL_1() STOP_CHANNEL_1(); \ START_CHANNEL_1() -#define RESTART_CHANNEL_2() STOP_CHANNEL_1(); \ - START_CHANNEL_1() +#define RESTART_CHANNEL_2() STOP_CHANNEL_2(); \ + START_CHANNEL_2() #define UPDATE_CHANNEL_1_FREQ(freq) gpt6cfg1.frequency = freq * DAC_BUFFER_SIZE; \ RESTART_CHANNEL_1() #define UPDATE_CHANNEL_2_FREQ(freq) gpt7cfg1.frequency = freq * DAC_BUFFER_SIZE; \ @@ -202,6 +202,41 @@ static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +// squarewave +static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 +}; + /* * DAC streaming callback. */ @@ -246,6 +281,18 @@ static const DACConversionGroup dacgrpcfg1 = { .trigger = DAC_TRG(0) }; +static const DACConfig dac1cfg2 = { + .init = 2047U, + .datamode = DAC_DHRM_12BIT_RIGHT +}; + +static const DACConversionGroup dacgrpcfg2 = { + .num_channels = 1U, + .end_cb = end_cb1, + .error_cb = error_cb1, + .trigger = DAC_TRG(0) +}; + void audio_init() { @@ -267,6 +314,7 @@ void audio_init() palSetPadMode(GPIOA, 4, PAL_MODE_INPUT_ANALOG); palSetPadMode(GPIOA, 5, PAL_MODE_INPUT_ANALOG); dacStart(&DACD1, &dac1cfg1); + dacStart(&DACD2, &dac1cfg2); /* * Starting GPT6 driver, it is used for triggering the DAC. @@ -279,6 +327,8 @@ void audio_init() */ dacStartConversion(&DACD1, &dacgrpcfg1, (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); + dacStartConversion(&DACD2, &dacgrpcfg2, + (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); // gptStartContinuous(&GPTD6, 2U); @@ -417,12 +467,10 @@ static void gpt_cb8(GPTDriver *gptp) { freq_alt = 30.52; } - if (GET_CHANNEL_1_FREQ != (uint16_t)freq_alt) { - UPDATE_CHANNEL_1_FREQ(freq_alt); + if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) { + UPDATE_CHANNEL_2_FREQ(freq_alt); } //note_timbre; - } else { - STOP_CHANNEL_1(); } if (polyphony_rate > 0) { @@ -478,12 +526,10 @@ static void gpt_cb8(GPTDriver *gptp) { } - if (GET_CHANNEL_2_FREQ != (uint16_t)freq) { - UPDATE_CHANNEL_2_FREQ(freq); + if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { + UPDATE_CHANNEL_1_FREQ(freq); } //note_timbre; - } else { - // gptStopTimer(&GPTD7); } } @@ -592,7 +638,8 @@ void play_note(float freq, int vol) { gptStart(&GPTD8, &gpt8cfg1); gptStartContinuous(&GPTD8, 2U); - + RESTART_CHANNEL_1(); + RESTART_CHANNEL_2(); } } From 78ea99d154eab6afb26389cb279728094fb0a7d9 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 31 Jan 2018 13:31:20 -0500 Subject: [PATCH 04/59] start f303 handwire --- keyboards/_qmk_handwire/_qmk_handwire.c | 25 + keyboards/_qmk_handwire/_qmk_handwire.h | 45 + .../boards/GENERIC_STM32_F303XC/board.c | 124 ++ .../boards/GENERIC_STM32_F303XC/board.h | 1187 +++++++++++++++++ .../boards/GENERIC_STM32_F303XC/board.mk | 5 + keyboards/_qmk_handwire/bootloader_defs.h | 7 + keyboards/_qmk_handwire/chconf.h | 520 ++++++++ keyboards/_qmk_handwire/config.h | 133 ++ keyboards/_qmk_handwire/halconf.h | 388 ++++++ .../_qmk_handwire/keymaps/default/keymap.c | 127 ++ .../_qmk_handwire/keymaps/default/readme.md | 1 + keyboards/_qmk_handwire/led.c | 53 + keyboards/_qmk_handwire/matrix.c | 175 +++ keyboards/_qmk_handwire/mcuconf.h | 257 ++++ keyboards/_qmk_handwire/readme.md | 14 + keyboards/_qmk_handwire/rules.mk | 55 + 16 files changed, 3116 insertions(+) create mode 100644 keyboards/_qmk_handwire/_qmk_handwire.c create mode 100644 keyboards/_qmk_handwire/_qmk_handwire.h create mode 100644 keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c create mode 100644 keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h create mode 100644 keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk create mode 100644 keyboards/_qmk_handwire/bootloader_defs.h create mode 100644 keyboards/_qmk_handwire/chconf.h create mode 100644 keyboards/_qmk_handwire/config.h create mode 100644 keyboards/_qmk_handwire/halconf.h create mode 100644 keyboards/_qmk_handwire/keymaps/default/keymap.c create mode 100644 keyboards/_qmk_handwire/keymaps/default/readme.md create mode 100644 keyboards/_qmk_handwire/led.c create mode 100644 keyboards/_qmk_handwire/matrix.c create mode 100644 keyboards/_qmk_handwire/mcuconf.h create mode 100644 keyboards/_qmk_handwire/readme.md create mode 100644 keyboards/_qmk_handwire/rules.mk diff --git a/keyboards/_qmk_handwire/_qmk_handwire.c b/keyboards/_qmk_handwire/_qmk_handwire.c new file mode 100644 index 0000000000..a7f460b1a9 --- /dev/null +++ b/keyboards/_qmk_handwire/_qmk_handwire.c @@ -0,0 +1,25 @@ +/* Copyright 2017 skully + * 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "_qmk_handwire.h" + +void matrix_init_kb(void) { + +} + +void matrix_scan_kb(void) { + +} diff --git a/keyboards/_qmk_handwire/_qmk_handwire.h b/keyboards/_qmk_handwire/_qmk_handwire.h new file mode 100644 index 0000000000..886b92016a --- /dev/null +++ b/keyboards/_qmk_handwire/_qmk_handwire.h @@ -0,0 +1,45 @@ +/* Copyright 2017 skully + * 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef QMK_HANDWIRE_H +#define QMK_HANDWIRE_H + +#include "quantum.h" + +/* + * These are shortcuts to help you work with the various layout options. If your + * keymap works with one of the LAYOUT_...() macros you are encouraged to use that + * and to contribute your keymap to the corresponding layout in + * `qmk_firmware/layouts/community`. + */ + +/* The fully-featured KEYMAP() that has every single key available in the matrix. + */ +#define KEYMAP(\ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1e, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2e, \ + k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3e, \ + k40, k41, k42, k47, k4a, k4b, k4c, k4e \ +) { \ + { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, }, \ + { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, KC_NO, k1e, }, \ + { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, KC_NO, k2e, }, \ + { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, KC_NO, k3e, }, \ + { k40, k41, k42, KC_NO, KC_NO, KC_NO, KC_NO, k47, KC_NO, KC_NO, k4a, k4b, k4c, KC_NO, k4e, }, \ +} + +#endif \ No newline at end of file diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c new file mode 100644 index 0000000000..897f20a887 --- /dev/null +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c @@ -0,0 +1,124 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +const PALConfig pal_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} +#endif +}; +#endif + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h new file mode 100644 index 0000000000..7405c0ea90 --- /dev/null +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h @@ -0,0 +1,1187 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for Clueboard 60% Keyboard + */ + +/* + * Board identifier. + */ +#define BOARD_GENERIC_STM32_F303XC +#define BOARD_NAME "Clueboard 60 PCB" + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 0U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +// #define STM32_HSE_BYPASS + +/* + * MCU type as defined in the ST header. + */ +#define STM32F303xC + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_PIN1 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_PIN4 4U +#define GPIOA_PIN5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_PIN8 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_I2C2_SDA 0U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_PIN0 0U +#define GPIOH_PIN1 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_L3GD20_SDI PAL_LINE(GPIOA, 7U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_PIN6 PAL_LINE(GPIOF, 0U) +#define LINE_PIN7 PAL_LINE(GPIOF, 1U) + +#define LINE_CAPS_LOCK PAL_LINE(GPIOB, 7U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - NC + * PA1 - NC + * PA2 - COL1 + * PA3 - COL2 + * PA4 - SPEAKER1 + * PA5 - SPEAKER2 + * PA6 - COL3 + * PA7 - COL8 + * PA8 - COL6 + * PA9 - COL7 + * PA10 - ROW5 + * PA11 - USB_DM (alternate 14). + * PA12 - USB_DP (alternate 14). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ROW4 + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_INPUT(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_PIN2) | \ + PIN_MODE_INPUT(GPIOA_PIN3) | \ + PIN_MODE_INPUT(GPIOA_PIN4) | \ + PIN_MODE_INPUT(GPIOA_PIN5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_PIN2) | \ + PIN_ODR_HIGH(GPIOA_PIN3) | \ + PIN_ODR_HIGH(GPIOA_PIN4) | \ + PIN_ODR_HIGH(GPIOA_PIN5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \ + PIN_AFIO_AF(GPIOA_PIN1, 0) | \ + PIN_AFIO_AF(GPIOA_PIN2, 0) | \ + PIN_AFIO_AF(GPIOA_PIN3, 0) | \ + PIN_AFIO_AF(GPIOA_PIN4, 0) | \ + PIN_AFIO_AF(GPIOA_PIN5, 5) | \ + PIN_AFIO_AF(GPIOA_PIN6, 5) | \ + PIN_AFIO_AF(GPIOA_PIN7, 5)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 14) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 14) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - PIN3 (alternate 0). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - PIN6 LSM303DLHC_SCL (alternate 4). + * PB7 - PIN7 LSM303DLHC_SDA (alternate 4). + * PB8 - PIN8 (input pullup). + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN6) | \ + PIN_MODE_OUTPUT(GPIOB_PIN7) | \ + PIN_MODE_INPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ + PIN_OSPEED_HIGH(GPIOB_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN6) | \ + PIN_PUPDR_PULLDOWN(GPIOB_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_PIN3) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_HIGH(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_PIN6) | \ + PIN_ODR_LOW(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0) | \ + PIN_AFIO_AF(GPIOB_PIN6, 4) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input floating). + * PC15 - PIN15 (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD11 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 L3GD20_CS (output pushpull maximum). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (output pushpull maximum). + * PE9 - PIN9 (output pushpull maximum). + * PE10 - PIN10 (output pushpull maximum). + * PE11 - PIN11 (output pushpull maximum). + * PE12 - PIN12 (output pushpull maximum). + * PE13 - PIN13 (output pushpull maximum). + * PE14 - PIN14 (output pushpull maximum). + * PE15 - PIN15 (output pushpull maximum). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) |\ + PIN_MODE_OUTPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) |\ + PIN_MODE_INPUT(GPIOE_PIN5) |\ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_OUTPUT(GPIOE_PIN8) | \ + PIN_MODE_OUTPUT(GPIOE_PIN9) | \ + PIN_MODE_OUTPUT(GPIOE_PIN10) | \ + PIN_MODE_OUTPUT(GPIOE_PIN11) | \ + PIN_MODE_OUTPUT(GPIOE_PIN12) | \ + PIN_MODE_OUTPUT(GPIOE_PIN13) | \ + PIN_MODE_OUTPUT(GPIOE_PIN14) | \ + PIN_MODE_OUTPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN5) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN14) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_LOW(GPIOE_PIN8) | \ + PIN_ODR_LOW(GPIOE_PIN9) | \ + PIN_ODR_LOW(GPIOE_PIN10) | \ + PIN_ODR_LOW(GPIOE_PIN11) | \ + PIN_ODR_LOW(GPIOE_PIN12) | \ + PIN_ODR_LOW(GPIOE_PIN13) | \ + PIN_ODR_LOW(GPIOE_PIN14) | \ + PIN_ODR_LOW(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0) |\ + PIN_AFIO_AF(GPIOE_PIN3, 0) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0) |\ + PIN_AFIO_AF(GPIOE_PIN5, 0) |\ + PIN_AFIO_AF(GPIOE_PIN6, 0) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0)) + +/* + * GPIOF setup: + * + * PF0 - I2C2_SDA (input floating). + * PF1 - I2C2_SCL (input floating). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_I2C2_SDA) | \ + PIN_MODE_INPUT(GPIOF_I2C2_SCL) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) | \ + PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) | \ + PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_I2C2_SDA) | \ + PIN_ODR_HIGH(GPIOF_I2C2_SCL) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) | \ + PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0)) + +/* + * GPIOH setup: + * + * PH0 - PIN0 (input pullup). + * PH1 - PIN1 (input pullup). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_PIN0) | \ + PIN_MODE_INPUT(GPIOH_PIN1) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOH_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_PULLUP(GPIOH_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_PIN0) | \ + PIN_ODR_HIGH(GPIOH_PIN1) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_PIN0, 0) | \ + PIN_AFIO_AF(GPIOH_PIN1, 0) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0)) + + +/* + * USB bus activation macro, required by the USB driver. + */ +// #define usb_lld_connect_bus(usbp) +#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14))) +// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT) +/* + * USB bus de-activation macro, required by the USB driver. + */ +// #define usb_lld_disconnect_bus(usbp) +#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)) +// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk new file mode 100644 index 0000000000..43377629a3 --- /dev/null +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC diff --git a/keyboards/_qmk_handwire/bootloader_defs.h b/keyboards/_qmk_handwire/bootloader_defs.h new file mode 100644 index 0000000000..3b0e9d20a6 --- /dev/null +++ b/keyboards/_qmk_handwire/bootloader_defs.h @@ -0,0 +1,7 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/keyboards/_qmk_handwire/chconf.h b/keyboards/_qmk_handwire/chconf.h new file mode 100644 index 0000000000..5a9b833107 --- /dev/null +++ b/keyboards/_qmk_handwire/chconf.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/_qmk_handwire/config.h new file mode 100644 index 0000000000..0832fffc2a --- /dev/null +++ b/keyboards/_qmk_handwire/config.h @@ -0,0 +1,133 @@ +/* + * Copyright 2017 skully + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef CONFIG_H +#define CONFIG_H + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xC1ED +#define PRODUCT_ID 0x2350 +#define DEVICE_VER 0x0001 +#define MANUFACTURER "QMK" +#define USBSTR_MANUFACTURER 'Q', '\x00', 'M', '\x00', 'K', '\x00' +#define PRODUCT "Handwire" +#define USBSTR_PRODUCT 'H', '\x00', 'a', '\x00', 'n', '\x00', 'd', '\x00', 'w', '\x00', 'i', '\x00', 'r', '\x00', 'e', '\x00' +#define DESCRIPTION "Handwire protoboard" + +/* key matrix size */ +#define MATRIX_ROWS 5 +#define MATRIX_COLS 15 + +/* + * Keyboard Matrix Assignments + * + * Change this to how you wired your keyboard + * COLS: AVR pins used for columns, left to right + * ROWS: AVR pins used for rows, top to bottom + * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) + * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) + * +*/ +/* Note: These are not used for arm boards. They're here purely as documentation. + * #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 } + * #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 } + * #define UNUSED_PINS + */ + +/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ +#define DEBOUNCE 6 + +/* Prevent modifiers from being stuck on after layer changes. */ +#define PREVENT_STUCK_MODIFIERS + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +//#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +//#define LOCKING_RESYNC_ENABLE + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +//#define FORCE_NKRO + +/* key combination for magic key command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +//#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 1 + +#endif + + /* Backlight configuration + */ +#define BACKLIGHT_LEVELS 1 diff --git a/keyboards/_qmk_handwire/halconf.h b/keyboards/_qmk_handwire/halconf.h new file mode 100644 index 0000000000..254470cbd0 --- /dev/null +++ b/keyboards/_qmk_handwire/halconf.h @@ -0,0 +1,388 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC TRUE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT TRUE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 256 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c new file mode 100644 index 0000000000..96b507877d --- /dev/null +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -0,0 +1,127 @@ +#include "_qmk_handwire.h" + +#define _______ KC_TRNS + +enum keyboard_layers { + _BL, + _FL, + _CL +}; + +enum custom_keycodes { + S_BSKTC = SAFE_RANGE, + S_ODEJY, + S_RCKBY, + S_DOEDR, + S_SCALE, + S_ONEUP, + S_COIN, + S_SONIC, + S_ZELDA +}; + +#ifdef AUDIO_ENABLE + float song_basketcase[][2] = SONG(BASKET_CASE); + float song_ode_to_joy[][2] = SONG(ODE_TO_JOY); + float song_rock_a_bye_baby[][2] = SONG(ROCK_A_BYE_BABY); + float song_doe_a_deer[][2] = SONG(DOE_A_DEER); + float song_scale[][2] = SONG(MUSIC_SCALE_SOUND); + float song_coin[][2] = SONG(COIN_SOUND); + float song_one_up[][2] = SONG(ONE_UP_SOUND); + float song_sonic_ring[][2] = SONG(SONIC_RING); + float song_zelda_puzzle[][2] = SONG(ZELDA_PUZZLE); +#endif + +const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + /* Layer 0: Default Layer + * ,-----------------------------------------------------------. + * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp| + * |-----------------------------------------------------------| + * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| + * |-----------------------------------------------------------| + * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter | + * |-----------------------------------------------------------| + * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| + * |-----------------------------------------------------------' + * |Ctrl |Gui|Alt | Space |Alt |Gui|Fn |Ctrl | + * `-----------------------------------------------------------' + */ + [_BL] = KEYMAP( + KC_GESC,KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL, KC_GRV, KC_BSPC,\ + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSLS, \ + KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_NUHS, KC_ENT, \ + KC_LSFT, KC_NUBS,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, KC_BSLS, \ + KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(_FL), KC_RCTL), + [_FL] = KEYMAP( + KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,_______,\ + _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, \ + _______, _______,MO(_CL),_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ + _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, _______, \ + _______,_______,_______, _______, _______, _______, MO(_FL), _______), + [_CL] = KEYMAP( + BL_STEP,S_BSKTC,S_ODEJY,S_RCKBY,S_DOEDR,S_SCALE,S_ONEUP,S_COIN, S_SONIC,S_ZELDA,_______,_______,_______,_______,_______,\ + _______, _______,_______,_______,RESET, _______,_______,_______,_______,_______,_______,_______,_______,_______, \ + _______, _______,MO(_CL),_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ + _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ + _______, _______, _______, _______, _______, _______, MO(_FL), _______) +}; + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case S_BSKTC: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_basketcase); + } + return false; + case S_ODEJY: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_ode_to_joy); + } + return false; + case S_RCKBY: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_rock_a_bye_baby); + } + return false; + case S_DOEDR: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_doe_a_deer); + } + return false; + case S_SCALE: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_scale); + } + return false; + case S_ONEUP: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_one_up); + } + return false; + case S_COIN: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_coin); + } + return false; + case S_SONIC: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_sonic_ring); + } + return false; + case S_ZELDA: + if (record->event.pressed) { + stop_all_notes(); + PLAY_SONG(song_zelda_puzzle); + } + return false; + } + return true; +} diff --git a/keyboards/_qmk_handwire/keymaps/default/readme.md b/keyboards/_qmk_handwire/keymaps/default/readme.md new file mode 100644 index 0000000000..32d4bfba61 --- /dev/null +++ b/keyboards/_qmk_handwire/keymaps/default/readme.md @@ -0,0 +1 @@ +# The default keymap for clueboard 60% diff --git a/keyboards/_qmk_handwire/led.c b/keyboards/_qmk_handwire/led.c new file mode 100644 index 0000000000..350696736b --- /dev/null +++ b/keyboards/_qmk_handwire/led.c @@ -0,0 +1,53 @@ +/* + * Copyright 2017 skully + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . +*/ + +#include "hal.h" +#include "backlight.h" +#include "led.h" +#include "printf.h" + +void backlight_init_ports(void) { + printf("backlight_init_ports()\n"); + #ifdef BACKLIGHT_ENABLE + palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL); + palSetPad(GPIOB, 8); + #endif +} + +void backlight_set(uint8_t level) { + printf("backlight_set(%d)\n", level); + #ifdef BACKLIGHT_ENABLE + if (level == 0) { + // Turn backlight off + palSetPad(GPIOB, 8); + } else { + // Turn backlight on + palClearPad(GPIOB, 8); + } + #endif +} + +void led_set_kb(uint8_t usb_led) { + printf("led_set_kb(%d)\n", usb_led); + if (usb_led & (1< +#include +#include +#include "hal.h" +#include "timer.h" +#include "wait.h" +#include "printf.h" +#include "backlight.h" +#include "matrix.h" + + +/* QMK Handwire + * + * Column pins are input with internal pull-down. + * Row pins are output and strobe with high. + * Key is high or 1 when it turns on. + * + * col: { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC15, PC14, PC13, PB5, PB6 } + * row: { PB0, PB1, PB2, PA15, PA10 } + */ +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t matrix_debouncing[MATRIX_COLS]; +static bool debouncing = false; +static uint16_t debouncing_time = 0; + +__attribute__ ((weak)) +void matrix_init_user(void) {} + +__attribute__ ((weak)) +void matrix_scan_user(void) {} + +__attribute__ ((weak)) +void matrix_init_kb(void) { + matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void matrix_init(void) { + printf("matrix init\n"); + //debug_matrix = true; + + /* Column(sense) */ + palSetPadMode(GPIOA, 2, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 3, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 6, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 14, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 15, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 8, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 9, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 3, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 4, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOC, 15, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOC, 14, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOC, 13, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 5, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 6, PAL_MODE_OUTPUT_PUSHPULL); + + /* Row(strobe) */ + palSetPadMode(GPIOB, 0, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 1, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 2, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN); + + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); + + palClearPad(GPIOB, 7); // Turn off capslock + matrix_init_quantum(); +} + +uint8_t matrix_scan(void) { + for (int col = 0; col < MATRIX_COLS; col++) { + matrix_row_t data = 0; + + // strobe col { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 } + switch (col) { + case 0: palSetPad(GPIOA, 2); break; + case 1: palSetPad(GPIOA, 3); break; + case 2: palSetPad(GPIOA, 6); break; + case 3: palSetPad(GPIOB, 14); break; + case 4: palSetPad(GPIOB, 15); break; + case 5: palSetPad(GPIOA, 8); break; + case 6: palSetPad(GPIOA, 9); break; + case 7: palSetPad(GPIOA, 7); break; + case 8: palSetPad(GPIOB, 3); break; + case 9: palSetPad(GPIOB, 4); break; + case 10: palSetPad(GPIOC, 15); break; + case 11: palSetPad(GPIOC, 14); break; + case 12: palSetPad(GPIOC, 13); break; + case 13: palSetPad(GPIOB, 5); break; + case 14: palSetPad(GPIOB, 6); break; + } + + // need wait to settle pin state + wait_us(20); + + // read row data { PB0, PB1, PB2, PA15, PA10 } + data = ( + (palReadPad(GPIOB, 0) << 0 ) | + (palReadPad(GPIOB, 1) << 1 ) | + (palReadPad(GPIOB, 2) << 2 ) | + (palReadPad(GPIOA, 15) << 3 ) | + (palReadPad(GPIOA, 10) << 4 ) + ); + + // unstrobe col { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC15, PC14, PC13, PB5, PB6 } + switch (col) { + case 0: palClearPad(GPIOA, 2); break; + case 1: palClearPad(GPIOA, 3); break; + case 2: palClearPad(GPIOA, 6); break; + case 3: palClearPad(GPIOB, 14); break; + case 4: palClearPad(GPIOB, 15); break; + case 5: palClearPad(GPIOA, 8); break; + case 6: palClearPad(GPIOA, 9); break; + case 7: palClearPad(GPIOA, 7); break; + case 8: palClearPad(GPIOB, 3); break; + case 9: palClearPad(GPIOB, 4); break; + case 10: palClearPad(GPIOC, 15); break; + case 11: palClearPad(GPIOC, 14); break; + case 12: palClearPad(GPIOC, 13); break; + case 13: palClearPad(GPIOB, 5); break; + case 14: palClearPad(GPIOB, 6); break; + } + + if (matrix_debouncing[col] != data) { + matrix_debouncing[col] = data; + debouncing = true; + debouncing_time = timer_read(); + } + } + + if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + for (int row = 0; row < MATRIX_ROWS; row++) { + matrix[row] = 0; + for (int col = 0; col < MATRIX_COLS; col++) { + matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); + } + } + debouncing = false; + } + + matrix_scan_quantum(); + + return 1; +} + +bool matrix_is_on(uint8_t row, uint8_t col) { + return (matrix[row] & (1</os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F3xx + +# Linker script to use +# - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT = STM32F303xC + +# Startup code to use +# - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f3xx + +# Board: it should exist either in /os/hal/boards/ +# or /boards +BOARD = GENERIC_STM32_F303XC + +# Cortex version +MCU = cortex-m4 + +# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +ARMV = 7 + +USE_FPU = yes + +# Vector table for application +# 0x00000000-0x00001000 area is occupied by bootlaoder.*/ +# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB +# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000 +OPT_DEFS = + +# Options to pass to dfu-util when flashing +DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000 -R + +# Build Options +# comment out to disable the options. +# +BACKLIGHT_ENABLE = no +BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration +## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.) +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +CONSOLE_ENABLE = yes # Console for debug +COMMAND_ENABLE = yes # Commands for debug and configuration +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover +CUSTOM_MATRIX = yes # Custom matrix file +AUDIO_ENABLE = yes +# SERIAL_LINK_ENABLE = yes From fc91bf4a659d3cdfc0712b2aa7dcadb32674ca6d Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 1 Feb 2018 14:48:25 -0500 Subject: [PATCH 05/59] updated matrix and keymap --- keyboards/_qmk_handwire/_qmk_handwire.h | 22 ++-- keyboards/_qmk_handwire/config.h | 8 +- keyboards/_qmk_handwire/halconf.h | 2 +- .../_qmk_handwire/keymaps/default/keymap.c | 39 ++---- keyboards/_qmk_handwire/led.c | 12 +- keyboards/_qmk_handwire/matrix.c | 119 +++++++----------- keyboards/_qmk_handwire/mcuconf.h | 2 +- keyboards/_qmk_handwire/rules.mk | 2 +- 8 files changed, 79 insertions(+), 127 deletions(-) diff --git a/keyboards/_qmk_handwire/_qmk_handwire.h b/keyboards/_qmk_handwire/_qmk_handwire.h index 886b92016a..e16ae3ba9b 100644 --- a/keyboards/_qmk_handwire/_qmk_handwire.h +++ b/keyboards/_qmk_handwire/_qmk_handwire.h @@ -29,17 +29,19 @@ /* The fully-featured KEYMAP() that has every single key available in the matrix. */ #define KEYMAP(\ - k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, \ - k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, k1e, \ - k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, k2e, \ - k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, k3e, \ - k40, k41, k42, k47, k4a, k4b, k4c, k4e \ + k00, k01, k02, k03, k04, k05, k06, \ + k10, k11, k12, k13, k14, k15, k16, \ + k20, k21, k22, k23, k24, k25, k26, \ + k31, k32, k33, k34, k35, k36, \ + k42, k43, k44, k45, k46, \ + k50, k51, k52 \ ) { \ - { k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, k0c, k0d, k0e, }, \ - { k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, k1c, KC_NO, k1e, }, \ - { k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, k2c, KC_NO, k2e, }, \ - { k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b, k3c, KC_NO, k3e, }, \ - { k40, k41, k42, KC_NO, KC_NO, KC_NO, KC_NO, k47, KC_NO, KC_NO, k4a, k4b, k4c, KC_NO, k4e, }, \ + { k00, k01, k02, k03, k04, k05, k06 }, \ + { k10, k11, k12, k13, k14, k15, k16 }, \ + { k20, k21, k22, k23, k24, k25, k26 }, \ + { 0, k31, k32, k33, k34, k35, k36 }, \ + { 0, 0, k42, k43, k44, k45, k46 }, \ + { k50, k51, k52, 0, 0, 0, 0 } \ } #endif \ No newline at end of file diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/_qmk_handwire/config.h index 0832fffc2a..70930b25f6 100644 --- a/keyboards/_qmk_handwire/config.h +++ b/keyboards/_qmk_handwire/config.h @@ -19,8 +19,8 @@ #define CONFIG_H /* USB Device descriptor parameter */ -#define VENDOR_ID 0xC1ED -#define PRODUCT_ID 0x2350 +#define VENDOR_ID 0x125A +#define PRODUCT_ID 0x1770 #define DEVICE_VER 0x0001 #define MANUFACTURER "QMK" #define USBSTR_MANUFACTURER 'Q', '\x00', 'M', '\x00', 'K', '\x00' @@ -29,8 +29,8 @@ #define DESCRIPTION "Handwire protoboard" /* key matrix size */ -#define MATRIX_ROWS 5 -#define MATRIX_COLS 15 +#define MATRIX_ROWS 6 +#define MATRIX_COLS 7 /* * Keyboard Matrix Assignments diff --git a/keyboards/_qmk_handwire/halconf.h b/keyboards/_qmk_handwire/halconf.h index 254470cbd0..d2a7653f5d 100644 --- a/keyboards/_qmk_handwire/halconf.h +++ b/keyboards/_qmk_handwire/halconf.h @@ -76,7 +76,7 @@ * @brief Enables the I2C subsystem. */ #if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) -#define HAL_USE_I2C FALSE +#define HAL_USE_I2C TRUE #endif /** diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index 96b507877d..01af53408c 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -33,37 +33,14 @@ enum custom_keycodes { #endif const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { - /* Layer 0: Default Layer - * ,-----------------------------------------------------------. - * |Esc| 1| 2| 3| 4| 5| 6| 7| 8| 9| 0| -| =| `|BSp| - * |-----------------------------------------------------------| - * |Tab | Q| W| E| R| T| Y| U| I| O| P| [| ]| \| - * |-----------------------------------------------------------| - * |Contro| A| S| D| F| G| H| J| K| L| ;| '|Enter | - * |-----------------------------------------------------------| - * |Shift | Z| X| C| V| B| N| M| ,| .| /|Shift |Fn0| - * |-----------------------------------------------------------' - * |Ctrl |Gui|Alt | Space |Alt |Gui|Fn |Ctrl | - * `-----------------------------------------------------------' - */ - [_BL] = KEYMAP( - KC_GESC,KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_MINS,KC_EQL, KC_GRV, KC_BSPC,\ - KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC,KC_RBRC,KC_BSLS, \ - KC_CAPS, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN,KC_QUOT,KC_NUHS, KC_ENT, \ - KC_LSFT, KC_NUBS,KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM,KC_DOT, KC_SLSH, KC_RSFT, KC_BSLS, \ - KC_LCTL, KC_LGUI, KC_LALT, KC_SPC, KC_RALT, KC_RGUI, MO(_FL), KC_RCTL), - [_FL] = KEYMAP( - KC_ESC, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, _______,_______,\ - _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, \ - _______, _______,MO(_CL),_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ - _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, _______, \ - _______,_______,_______, _______, _______, _______, MO(_FL), _______), - [_CL] = KEYMAP( - BL_STEP,S_BSKTC,S_ODEJY,S_RCKBY,S_DOEDR,S_SCALE,S_ONEUP,S_COIN, S_SONIC,S_ZELDA,_______,_______,_______,_______,_______,\ - _______, _______,_______,_______,RESET, _______,_______,_______,_______,_______,_______,_______,_______,_______, \ - _______, _______,MO(_CL),_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ - _______, _______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______,_______, _______, \ - _______, _______, _______, _______, _______, _______, MO(_FL), _______) + [0] = KEYMAP( + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, + KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, + KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, + MO(2), MO(1), KC_SPC + ) }; bool process_record_user(uint16_t keycode, keyrecord_t *record) { diff --git a/keyboards/_qmk_handwire/led.c b/keyboards/_qmk_handwire/led.c index 350696736b..42cbe0d4d9 100644 --- a/keyboards/_qmk_handwire/led.c +++ b/keyboards/_qmk_handwire/led.c @@ -23,8 +23,8 @@ void backlight_init_ports(void) { printf("backlight_init_ports()\n"); #ifdef BACKLIGHT_ENABLE - palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL); - palSetPad(GPIOB, 8); + // palSetPadMode(GPIOB, 8, PAL_MODE_OUTPUT_PUSHPULL); + // palSetPad(GPIOB, 8); #endif } @@ -33,10 +33,10 @@ void backlight_set(uint8_t level) { #ifdef BACKLIGHT_ENABLE if (level == 0) { // Turn backlight off - palSetPad(GPIOB, 8); + // palSetPad(GPIOB, 8); } else { // Turn backlight on - palClearPad(GPIOB, 8); + // palClearPad(GPIOB, 8); } #endif } @@ -45,9 +45,9 @@ void led_set_kb(uint8_t usb_led) { printf("led_set_kb(%d)\n", usb_led); if (usb_led & (1< DEBOUNCE) { for (int row = 0; row < MATRIX_ROWS; row++) { - matrix[row] = 0; - for (int col = 0; col < MATRIX_COLS; col++) { - matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); - } + matrix[row] = matrix_debouncing[row]; } debouncing = false; } - matrix_scan_quantum(); return 1; diff --git a/keyboards/_qmk_handwire/mcuconf.h b/keyboards/_qmk_handwire/mcuconf.h index 94cb540ec9..226da48d59 100644 --- a/keyboards/_qmk_handwire/mcuconf.h +++ b/keyboards/_qmk_handwire/mcuconf.h @@ -154,7 +154,7 @@ /* * I2C driver system settings. */ -#define STM32_I2C_USE_I2C1 FALSE +#define STM32_I2C_USE_I2C1 TRUE #define STM32_I2C_USE_I2C2 FALSE #define STM32_I2C_BUSY_TIMEOUT 50 #define STM32_I2C_I2C1_IRQ_PRIORITY 10 diff --git a/keyboards/_qmk_handwire/rules.mk b/keyboards/_qmk_handwire/rules.mk index 2def050b2b..acabc0f950 100644 --- a/keyboards/_qmk_handwire/rules.mk +++ b/keyboards/_qmk_handwire/rules.mk @@ -36,7 +36,7 @@ USE_FPU = yes OPT_DEFS = # Options to pass to dfu-util when flashing -DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000 -R +DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave # Build Options # comment out to disable the options. From fae437cfadcd393009e148442e48c046c126a5b0 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 7 Feb 2018 17:17:39 -0500 Subject: [PATCH 06/59] update matrix --- drivers/arm/twi2c.c | 33 +++++++++++++++++++ drivers/arm/twi2c.h | 18 ++++++++++ keyboards/_qmk_handwire/_qmk_handwire.h | 12 +++++++ keyboards/_qmk_handwire/config.h | 2 +- .../_qmk_handwire/keymaps/default/keymap.c | 7 ++++ 5 files changed, 71 insertions(+), 1 deletion(-) create mode 100644 drivers/arm/twi2c.c create mode 100644 drivers/arm/twi2c.h diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c new file mode 100644 index 0000000000..e6cab25b50 --- /dev/null +++ b/drivers/arm/twi2c.c @@ -0,0 +1,33 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "twi2c.h" + +#ifndef I2C_DRIVER + #define I2C_DRIVER &I2CD1 +#endif + +static const I2CConfig i2cconfig = { + STM32_TIMINGR_PRESC(15U) | + STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | + STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), + 0, + 0 +}; + +void twi2c_init(void) { + i2cStart(I2C_DRIVER, &i2cconfig); +} \ No newline at end of file diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h new file mode 100644 index 0000000000..a1847d436d --- /dev/null +++ b/drivers/arm/twi2c.h @@ -0,0 +1,18 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ch.h" +#include "hal.h" \ No newline at end of file diff --git a/keyboards/_qmk_handwire/_qmk_handwire.h b/keyboards/_qmk_handwire/_qmk_handwire.h index e16ae3ba9b..f482861f9a 100644 --- a/keyboards/_qmk_handwire/_qmk_handwire.h +++ b/keyboards/_qmk_handwire/_qmk_handwire.h @@ -29,6 +29,12 @@ /* The fully-featured KEYMAP() that has every single key available in the matrix. */ #define KEYMAP(\ + j00, j01, j02, j03, j04, j05, j06, \ + j10, j11, j12, j13, j14, j15, j16, \ + j20, j21, j22, j23, j24, j25, j26, \ + j30, j31, j32, j33, j34, j35, \ + j40, j41, j42, j43, j44, \ + j54, j55, j56, \ k00, k01, k02, k03, k04, k05, k06, \ k10, k11, k12, k13, k14, k15, k16, \ k20, k21, k22, k23, k24, k25, k26, \ @@ -36,6 +42,12 @@ k42, k43, k44, k45, k46, \ k50, k51, k52 \ ) { \ + { j00, j01, j02, j03, j04, j05, j06 }, \ + { j10, j11, j12, j13, j14, j15, j16 }, \ + { j20, j21, j22, j23, j24, j25, j26 }, \ + { j30, j31, j32, j33, j34, j35, 0 }, \ + { j40, j41, j42, j43, j44, 0, 0 }, \ + { 0, 0, 0, 0, j54, j55, j56 }, \ { k00, k01, k02, k03, k04, k05, k06 }, \ { k10, k11, k12, k13, k14, k15, k16 }, \ { k20, k21, k22, k23, k24, k25, k26 }, \ diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/_qmk_handwire/config.h index 70930b25f6..6b3042ce01 100644 --- a/keyboards/_qmk_handwire/config.h +++ b/keyboards/_qmk_handwire/config.h @@ -29,7 +29,7 @@ #define DESCRIPTION "Handwire protoboard" /* key matrix size */ -#define MATRIX_ROWS 6 +#define MATRIX_ROWS 12 #define MATRIX_COLS 7 /* diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index 01af53408c..8469b6c395 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -34,6 +34,13 @@ enum custom_keycodes { const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, + KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, + KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, + MO(2), MO(1), KC_SPC, + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, From be81cd8c98315fc3b90ce1cf049b533eafecb88a Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sat, 10 Feb 2018 16:32:05 -0500 Subject: [PATCH 07/59] adds i2c slave implementation --- common_features.mk | 11 + drivers/arm/twi2c.c | 196 +++++++++++++++++- .../boards/GENERIC_STM32_F303XC/board.h | 4 +- keyboards/_qmk_handwire/config.h | 7 +- keyboards/_qmk_handwire/halconf.h | 7 + .../_qmk_handwire/keymaps/default/keymap.c | 22 +- keyboards/_qmk_handwire/matrix.c | 94 ++++++--- keyboards/_qmk_handwire/rules.mk | 1 + lib/chibios | 2 +- tmk_core/avr.mk | 14 +- tmk_core/protocol/chibios/main.c | 5 +- 11 files changed, 300 insertions(+), 63 deletions(-) diff --git a/common_features.mk b/common_features.mk index 1c0b3546a1..8dfa64f9e8 100644 --- a/common_features.mk +++ b/common_features.mk @@ -20,6 +20,12 @@ SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c) SERIAL_DEFS += -DSERIAL_LINK_ENABLE COMMON_VPATH += $(SERIAL_PATH) +ifeq ($(PLATFORM),AVR) + COMMON_VPATH += $(DRIVER_PATH)/avr +else + COMMON_VPATH += $(DRIVER_PATH)/arm +endif + ifeq ($(strip $(API_SYSEX_ENABLE)), yes) OPT_DEFS += -DAPI_SYSEX_ENABLE SRC += $(QUANTUM_DIR)/api/api_sysex.c @@ -184,6 +190,11 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes) include $(TMK_DIR)/protocol/usb_hid.mk endif +ifeq ($(strip $(I2C_SLAVE_ENABLE)), yes) + SRC += twi2c.c + OPT_DEFS += -DI2C_SLAVE_ENABLE +endif + QUANTUM_SRC:= \ $(QUANTUM_DIR)/quantum.c \ $(QUANTUM_DIR)/keymap_common.c \ diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index e6cab25b50..b6dc2d27ed 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -15,19 +15,203 @@ */ #include "twi2c.h" +#include +#include +#include "hal_i2cslave.h" +#include "chprintf.h" +#include "memstreams.h" +#include "printf.h" #ifndef I2C_DRIVER - #define I2C_DRIVER &I2CD1 + #define I2C_DRIVER I2CD1 #endif -static const I2CConfig i2cconfig = { +/** + * I2C slave test routine. + * + * To use: Add file to a project, call startComms() with the address of a serial stream + * + * There are two different responses: + * a) A read-only transaction - returns the "Initial Reply" message + * b) A write then read transaction - calls a message processor and returns the generated reply. + * Stretches clock until reply available. + */ + + +#define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ +//#define myOtherI2Caddress 0x19 + +I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; + +static const I2CConfig slaveI2Cconfig = { STM32_TIMINGR_PRESC(15U) | STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), 0, - 0 + 0, + NULL }; -void twi2c_init(void) { - i2cStart(I2C_DRIVER, &i2cconfig); -} \ No newline at end of file +char initialReplyBody[50] = "Initial reply"; // 'Status' response if read without preceding write + + +uint32_t messageCounter = 0; /* Counts number of messages received to return as part of response */ + +uint8_t rxBody[240]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */ +uint8_t txBody[256]; /* Return message buffer for computed replies */ + +BaseSequentialStream *chp = NULL; // Used for serial logging + +// Handler when something sent to us +const I2CSlaveMsg echoRx = +{ + sizeof(rxBody), /* max sizeof received msg body */ + rxBody, /* body of received msg */ + NULL, /* do nothing on address match */ + twi2c_slave_message_process, /* Routine to process received messages */ + catchError /* Error hook */ +}; + + +// 'Empty' reply when nothing to say, and no message received. In RAM, to allow update +I2CSlaveMsg initialReply = +{ + sizeof(initialReplyBody), /* trailing zero byte will be repeated as needed */ + (uint8_t *)initialReplyBody, + NULL, /* do nothing on address match */ + NULL, /* do nothing after reply sent */ + catchError /* Error hook */ +}; + + +// Response to received messages +I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ + 0, /* filled in with the length of the message to send */ + txBody, /* Response message */ + NULL, /* do nothing special on address match */ + clearAfterSend, /* Clear receive buffer once replied */ + catchError /* Error hook */ +}; + + +/** + * Track I2C errors + */ +uint8_t gotI2cError = 0; +uint32_t lastI2cErrorFlags = 0; + +// Called from ISR to log error +void noteI2cError(uint32_t flags) +{ + lastI2cErrorFlags = flags; + gotI2cError = 1; +} + + + +/** + * Generic error handler + * + * Called in interrupt context, so need to watch what we do + */ +void catchError(I2CDriver *i2cp) +{ + noteI2cError(i2cp->errors); +} + + + +const char hexString[16] = "0123456789abcdef"; + + +/** + * Message processor - looks at received message, determines reply as quickly as possible + * + * Responds with the value of the messageCounter (in hex), followed by the received message in [..] + * + * Note: Called in interrupt context, so need to be quick! + */ +void twi2c_slave_message_process(I2CDriver *i2cp) { + uint8_t i; + uint8_t *txPtr = txBody + 8; + uint8_t txLen; + uint32_t curCount; + + size_t len = i2cSlaveBytes(i2cp); // Number of bytes received + if (len >= sizeof(rxBody)) + len = sizeof(rxBody)-1; + rxBody[len]=0; // String termination sometimes useful + + /* A real-world application would read and decode the message in rxBody, then generate an appropriate reply in txBody */ + + curCount = ++messageCounter; + txLen = len + 11; // Add in the overhead + + for (i = 0; i < 8; i++) + { + *--txPtr = hexString[curCount & 0xf]; + curCount = curCount >> 4; + } + + txPtr = txBody + 8; + *txPtr++ = ' '; + *txPtr++ = '['; + memcpy(txPtr, rxBody, len); // Echo received message + txPtr += len; + *txPtr++ = ']'; + *txPtr = '\0'; + + /** Message ready to go here */ + echoReply.size = txLen; + i2cSlaveReplyI(i2cp, &echoReply); +} + + +/** + * Callback after sending of response complete - restores default reply in case polled + */ +void clearAfterSend(I2CDriver *i2cp) +{ + echoReply.size = 0; // Clear receive message + i2cSlaveReplyI(i2cp, &initialReply); +} + + +/** + * Start the I2C Slave port to accept comms from master CPU + * + * We then go into a loop checking for errors, and never return + */ + +void twi2c_slave_init(void) { + + palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time + chThdSleepMilliseconds(10); + + /* I2C1 SCL on PF1, SDA on PF0 */ + palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + + + i2cStart(&I2C_DRIVER, &slaveI2Cconfig); +#if HAL_USE_I2C_SLAVE + I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message +#endif + + i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); + + // Enable match address after everything else set up + i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); +// i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); +// i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ + + printf("Slave I2C started\n\r"); + +} + +void twi2c_slave_task(void) { + if (gotI2cError) { + gotI2cError = 0; + printf("I2cError: %04x\r\n", lastI2cErrorFlags); + } +} diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h index 7405c0ea90..254c84a097 100644 --- a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h @@ -539,7 +539,7 @@ PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ - PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN13) | \ PIN_PUPDR_FLOATING(GPIOC_PIN14) | \ PIN_PUPDR_FLOATING(GPIOC_PIN15)) #define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ @@ -1164,7 +1164,7 @@ /* * USB bus activation macro, required by the USB driver. */ -// #define usb_lld_connect_bus(usbp) +// #define usb_lld_connect_bus(usbp) #define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14))) // #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT) /* diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/_qmk_handwire/config.h index 6b3042ce01..7243e13647 100644 --- a/keyboards/_qmk_handwire/config.h +++ b/keyboards/_qmk_handwire/config.h @@ -126,8 +126,11 @@ /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 1 -#endif - /* Backlight configuration */ #define BACKLIGHT_LEVELS 1 + +#define NO_USB_STARTUP_CHECK + +#endif + diff --git a/keyboards/_qmk_handwire/halconf.h b/keyboards/_qmk_handwire/halconf.h index d2a7653f5d..bf2b69e225 100644 --- a/keyboards/_qmk_handwire/halconf.h +++ b/keyboards/_qmk_handwire/halconf.h @@ -79,6 +79,13 @@ #define HAL_USE_I2C TRUE #endif +/** + * @brief Enables the I2C Slave subsystem. + */ +#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) +#define HAL_USE_I2C_SLAVE TRUE +#endif + /** * @brief Enables the I2S subsystem. */ diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index 8469b6c395..d0e727825e 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -34,18 +34,18 @@ enum custom_keycodes { const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( - KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, - KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, - KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, - KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, - KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, - MO(2), MO(1), KC_SPC, + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_HOME, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_END, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, + KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_LGUI, + KC_SPC, MO(2), MO(1), - KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, - KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, - KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, - KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, - KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, + KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, + KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, MO(2), MO(1), KC_SPC ) }; diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index c76a93db70..8800183aab 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -8,6 +8,7 @@ #include "backlight.h" #include "matrix.h" +#include "usb_main.h" /* QMK Handwire * @@ -24,6 +25,9 @@ static matrix_row_t matrix_debouncing[MATRIX_ROWS]; static bool debouncing = false; static uint16_t debouncing_time = 0; +static bool master = false; +static bool right_hand = false; + __attribute__ ((weak)) void matrix_init_user(void) {} @@ -44,6 +48,14 @@ void matrix_init(void) { printf("matrix init\n"); //debug_matrix = true; + // C13 is connected to VCC on the right hand + palSetPadMode(GPIOC, 13, PAL_MODE_INPUT); + wait_us(20); + right_hand = palReadPad(GPIOC, 13); + + // if USB is active, this is the master + master = (USB_DRIVER.state == USB_ACTIVE); + /* Column(sense) */ palSetPadMode(GPIOA, 13, PAL_MODE_INPUT_PULLDOWN); palSetPadMode(GPIOA, 14, PAL_MODE_INPUT_PULLDOWN); @@ -68,42 +80,60 @@ void matrix_init(void) { matrix_init_quantum(); } +matrix_row_t matrix_scan_common(uint8_t row) { + matrix_row_t data; + + // strobe row { A6, A7, B0, B1, B2, B10 } + switch (row) { + case 5: palSetPad(GPIOA, 6); break; + case 4: palSetPad(GPIOA, 7); break; + case 3: palSetPad(GPIOB, 0); break; + case 2: palSetPad(GPIOB, 1); break; + case 1: palSetPad(GPIOB, 2); break; + case 0: palSetPad(GPIOB, 10); break; + } + + // need wait to settle pin state + wait_us(20); + + // read col data { B6, B5, B4, B3, A15, A14, A13 } + data = ( + (palReadPad(GPIOB, 6) << 6 ) | + (palReadPad(GPIOB, 5) << 5 ) | + (palReadPad(GPIOB, 4) << 4 ) | + (palReadPad(GPIOB, 3) << 3 ) | + (palReadPad(GPIOA, 15) << 2 ) | + (palReadPad(GPIOA, 14) << 1 ) | + (palReadPad(GPIOA, 13) << 0 ) + ); + + // unstrobe row { A6, A7, B0, B1, B2, B10 } + switch (row) { + case 5: palClearPad(GPIOA, 6); break; + case 4: palClearPad(GPIOA, 7); break; + case 3: palClearPad(GPIOB, 0); break; + case 2: palClearPad(GPIOB, 1); break; + case 1: palClearPad(GPIOB, 2); break; + case 0: palClearPad(GPIOB, 10); break; + } + + return data; +} + +uint8_t matrix_scan_master(void) { + +} + +uint8_t matrix_scan_slave(void) { + +} + uint8_t matrix_scan(void) { for (int row = 0; row < MATRIX_ROWS; row++) { matrix_row_t data = 0; - // strobe row { A6, A7, B0, B1, B2, B10 } - switch (row) { - case 5: palSetPad(GPIOA, 6); break; - case 4: palSetPad(GPIOA, 7); break; - case 3: palSetPad(GPIOB, 0); break; - case 2: palSetPad(GPIOB, 1); break; - case 1: palSetPad(GPIOB, 2); break; - case 0: palSetPad(GPIOB, 10); break; - } - - // need wait to settle pin state - wait_us(20); - - // read col data { B6, B5, B4, B3, A15, A14, A13 } - data = ( - (palReadPad(GPIOB, 6) << 6 ) | - (palReadPad(GPIOB, 5) << 5 ) | - (palReadPad(GPIOB, 4) << 4 ) | - (palReadPad(GPIOB, 3) << 3 ) | - (palReadPad(GPIOA, 15) << 2 ) | - (palReadPad(GPIOA, 14) << 1 ) | - (palReadPad(GPIOA, 13) << 0 ) - ); - - // unstrobe row { A6, A7, B0, B1, B2, B10 } - switch (row) { - case 5: palClearPad(GPIOA, 6); break; - case 4: palClearPad(GPIOA, 7); break; - case 3: palClearPad(GPIOB, 0); break; - case 2: palClearPad(GPIOB, 1); break; - case 1: palClearPad(GPIOB, 2); break; - case 0: palClearPad(GPIOB, 10); break; + if (right_hand && row >= 6) { + data = matrix_scan_common(row % 6); } if (matrix_debouncing[row] != data) { diff --git a/keyboards/_qmk_handwire/rules.mk b/keyboards/_qmk_handwire/rules.mk index acabc0f950..9ca7e779a3 100644 --- a/keyboards/_qmk_handwire/rules.mk +++ b/keyboards/_qmk_handwire/rules.mk @@ -53,3 +53,4 @@ NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes # SERIAL_LINK_ENABLE = yes +I2C_SLAVE_ENABLE = yes diff --git a/lib/chibios b/lib/chibios index 587968d6cb..f9643c88ad 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit 587968d6cbc2b0e1c7147540872f2a67e59ca18b +Subproject commit f9643c88ad5cd0704d57bed83fe64f45b3e6be4e diff --git a/tmk_core/avr.mk b/tmk_core/avr.mk index 106b771507..00d67f76aa 100644 --- a/tmk_core/avr.mk +++ b/tmk_core/avr.mk @@ -9,11 +9,9 @@ SIZE = avr-size AR = avr-ar rcs NM = avr-nm HEX = $(OBJCOPY) -O $(FORMAT) -R .eeprom -R .fuse -R .lock -R .signature -EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) +EEP = $(OBJCOPY) -j .eeprom --set-section-flags=.eeprom="alloc,load" --change-section-lma .eeprom=0 --no-change-warnings -O $(FORMAT) BIN = -COMMON_VPATH += $(DRIVER_PATH)/avr - COMPILEFLAGS += -funsigned-char COMPILEFLAGS += -funsigned-bitfields COMPILEFLAGS += -ffunction-sections @@ -126,14 +124,14 @@ program: $(BUILD_DIR)/$(TARGET).hex $(BUILD_DIR)/$(TARGET).eep check-size teensy: $(BUILD_DIR)/$(TARGET).hex check-size $(TEENSY_LOADER_CLI) -mmcu=$(MCU) -w -v $(BUILD_DIR)/$(TARGET).hex - -BATCHISP ?= batchisp + +BATCHISP ?= batchisp flip: $(BUILD_DIR)/$(TARGET).hex check-size $(BATCHISP) -hardware usb -device $(MCU) -operation erase f $(BATCHISP) -hardware usb -device $(MCU) -operation loadbuffer $(BUILD_DIR)/$(TARGET).hex program $(BATCHISP) -hardware usb -device $(MCU) -operation start reset 0 - + DFU_PROGRAMMER ?= dfu-programmer dfu: $(BUILD_DIR)/$(TARGET).hex cpfirmware check-size @@ -194,7 +192,7 @@ bin: $(BUILD_DIR)/$(TARGET).hex # copy bin to FLASH.bin flashbin: bin - $(COPY) $(BUILD_DIR)/$(TARGET).bin FLASH.bin; + $(COPY) $(BUILD_DIR)/$(TARGET).bin FLASH.bin; # Generate avr-gdb config/init file which does the following: # define the reset signal, load the target file, connect to target, and set @@ -245,7 +243,7 @@ extcoff: $(BUILD_DIR)/$(TARGET).elf @$(SECHO) $(MSG_EXTENDED_COFF) $(BUILD_DIR)/$(TARGET).cof $(COFFCONVERT) -O coff-ext-avr $< $(BUILD_DIR)/$(TARGET).cof -bootloader: +bootloader: make -C lib/lufa/Bootloaders/DFU/ clean echo "#ifndef QMK_KEYBOARD\n#define QMK_KEYBOARD\n" > lib/lufa/Bootloaders/DFU/Keyboard.h echo `grep "MANUFACTURER" $(ALL_CONFIGS) -h | tail -1` >> lib/lufa/Bootloaders/DFU/Keyboard.h diff --git a/tmk_core/protocol/chibios/main.c b/tmk_core/protocol/chibios/main.c index f2abc438d4..8bb00583de 100644 --- a/tmk_core/protocol/chibios/main.c +++ b/tmk_core/protocol/chibios/main.c @@ -135,7 +135,10 @@ int main(void) { /* Wait until the USB or serial link is active */ while (true) { - if(USB_DRIVER.state == USB_ACTIVE) { + #if !defined(NO_USB_STARTUP_CHECK) + if(USB_DRIVER.state == USB_ACTIVE) + #endif + { driver = &chibios_driver; break; } From 7d59f83b2e43ac8c6d6d39e7e45311f2300a994d Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 14 Feb 2018 15:35:24 -0500 Subject: [PATCH 08/59] adds matrix i2c swap --- drivers/arm/twi2c.c | 52 +++++++------------ drivers/arm/twi2c.h | 12 ++++- .../_qmk_handwire/keymaps/default/keymap.c | 4 +- keyboards/_qmk_handwire/matrix.c | 44 ++++++++++++++-- 4 files changed, 70 insertions(+), 42 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index b6dc2d27ed..561a601eaa 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -21,6 +21,7 @@ #include "chprintf.h" #include "memstreams.h" #include "printf.h" +#include "matrix.h" #ifndef I2C_DRIVER #define I2C_DRIVER I2CD1 @@ -37,13 +38,7 @@ * Stretches clock until reply available. */ - -#define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ -//#define myOtherI2Caddress 0x19 - -I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; - -static const I2CConfig slaveI2Cconfig = { +static const I2CConfig uniI2CConfig = { STM32_TIMINGR_PRESC(15U) | STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), @@ -119,11 +114,10 @@ void catchError(I2CDriver *i2cp) noteI2cError(i2cp->errors); } - +extern void matrix_copy(matrix_row_t * copy); const char hexString[16] = "0123456789abcdef"; - /** * Message processor - looks at received message, determines reply as quickly as possible * @@ -132,36 +126,18 @@ const char hexString[16] = "0123456789abcdef"; * Note: Called in interrupt context, so need to be quick! */ void twi2c_slave_message_process(I2CDriver *i2cp) { - uint8_t i; - uint8_t *txPtr = txBody + 8; + uint8_t *txPtr = txBody; uint8_t txLen; - uint32_t curCount; size_t len = i2cSlaveBytes(i2cp); // Number of bytes received - if (len >= sizeof(rxBody)) - len = sizeof(rxBody)-1; - rxBody[len]=0; // String termination sometimes useful - /* A real-world application would read and decode the message in rxBody, then generate an appropriate reply in txBody */ - - curCount = ++messageCounter; - txLen = len + 11; // Add in the overhead - - for (i = 0; i < 8; i++) - { - *--txPtr = hexString[curCount & 0xf]; - curCount = curCount >> 4; + if (len >= 2 && rxBody[0] == 0x01 && rxBody[1] == 0x00) { + matrix_row_t matrix[MATRIX_ROWS / 2]; + matrix_copy(matrix); + memcpy(txPtr, matrix, MATRIX_ROWS / 2); + txLen = MATRIX_ROWS / 2; } - txPtr = txBody + 8; - *txPtr++ = ' '; - *txPtr++ = '['; - memcpy(txPtr, rxBody, len); // Echo received message - txPtr += len; - *txPtr++ = ']'; - *txPtr = '\0'; - - /** Message ready to go here */ echoReply.size = txLen; i2cSlaveReplyI(i2cp, &echoReply); } @@ -193,7 +169,7 @@ void twi2c_slave_init(void) { palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); - i2cStart(&I2C_DRIVER, &slaveI2Cconfig); + i2cStart(&I2C_DRIVER, &uniI2CConfig); #if HAL_USE_I2C_SLAVE I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif @@ -215,3 +191,11 @@ void twi2c_slave_task(void) { printf("I2cError: %04x\r\n", lastI2cErrorFlags); } } + +void twi2c_master_init(void) { + i2cStart(&I2C_DRIVER, &uniI2CConfig); +} + +msg_t twi2c_master_send(i2caddr_t address, const uint8_t * txbuf, uint8_t * rxbuf, systime_t timeout) { + return i2cMasterTransmitTimeout(&I2C_DRIVER, address, txbuf, sizeof(txbuf), rxbuf, sizeof(rxbuf), timeout); +} diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index a1847d436d..175572189b 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -15,4 +15,14 @@ */ #include "ch.h" -#include "hal.h" \ No newline at end of file +#include "hal.h" + +#define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ +//#define myOtherI2Caddress 0x19 + +I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; + +void twi2c_slave_init(void); + +void twi2c_master_init(void); +msg_t twi2c_master_send(i2caddr_t address, const uint8_t * txbuf, uint8_t * rxbuf, systime_t timeout); diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index d0e727825e..2611f570c3 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -35,14 +35,14 @@ enum custom_keycodes { const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL, - KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_HOME, + KC_TAB, DEBUG, KC_W, KC_E, KC_R, KC_T, KC_HOME, KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_END, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_LGUI, KC_SPC, MO(2), MO(1), KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, - KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, + KC_PGUP, KC_Y, KC_U, KC_I, KC_O, DEBUG, KC_DEL, KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index 8800183aab..1d67851ba2 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -9,6 +9,7 @@ #include "matrix.h" #include "usb_main.h" +#include "twi2c.h" /* QMK Handwire * @@ -46,7 +47,7 @@ void matrix_scan_kb(void) { void matrix_init(void) { printf("matrix init\n"); - //debug_matrix = true; + // debug_matrix = true; // C13 is connected to VCC on the right hand palSetPadMode(GPIOC, 13, PAL_MODE_INPUT); @@ -56,6 +57,12 @@ void matrix_init(void) { // if USB is active, this is the master master = (USB_DRIVER.state == USB_ACTIVE); + if (master) { + twi2c_master_init(); + } else { + twi2c_slave_init(); + } + /* Column(sense) */ palSetPadMode(GPIOA, 13, PAL_MODE_INPUT_PULLDOWN); palSetPadMode(GPIOA, 14, PAL_MODE_INPUT_PULLDOWN); @@ -120,19 +127,31 @@ matrix_row_t matrix_scan_common(uint8_t row) { return data; } -uint8_t matrix_scan_master(void) { +void matrix_scan_master(void) { -} + const uint8_t command[2] = { 0x01, 0x00 }; + uint8_t other_matrix[MATRIX_ROWS]; -uint8_t matrix_scan_slave(void) { + msg_t resp; + resp = twi2c_master_send(slaveI2Caddress/2, command, other_matrix, TIME_INFINITE); + printf("%x\n", resp); + uint8_t * matrix_pointer; + if (right_hand) { + matrix_pointer = matrix; + } else { + matrix_pointer = matrix + (MATRIX_ROWS / 2); + } + + memcpy(matrix_pointer, other_matrix, MATRIX_ROWS / 2); } uint8_t matrix_scan(void) { + for (int row = 0; row < MATRIX_ROWS; row++) { matrix_row_t data = 0; - if (right_hand && row >= 6) { + if ((right_hand && row >= 6) || (!right_hand && row < 6)) { data = matrix_scan_common(row % 6); } @@ -149,6 +168,11 @@ uint8_t matrix_scan(void) { } debouncing = false; } + + if (master) { + matrix_scan_master(); + } + matrix_scan_quantum(); return 1; @@ -162,6 +186,16 @@ matrix_row_t matrix_get_row(uint8_t row) { return matrix[row]; } +void matrix_copy(matrix_row_t * copy) { + uint8_t * matrix_pointer; + if (right_hand) { + matrix_pointer = matrix + (MATRIX_ROWS / 2); + } else { + matrix_pointer = matrix; + } + memcpy(copy, matrix_pointer, MATRIX_ROWS / 2); +} + void matrix_print(void) { printf("\nr/c 01234567\n"); for (uint8_t row = 0; row < MATRIX_ROWS; row++) { From 3c0d86eb47b2eb92b8300bc726dc242c8af594f4 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 15 Feb 2018 02:06:06 -0500 Subject: [PATCH 09/59] a little progress --- drivers/arm/twi2c.c | 15 ++++----------- keyboards/_qmk_handwire/matrix.c | 29 ++++++++++++++++------------- 2 files changed, 20 insertions(+), 24 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 561a601eaa..299e52eb2a 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -53,7 +53,7 @@ char initialReplyBody[50] = "Initial reply"; // 'Status' response if read uint32_t messageCounter = 0; /* Counts number of messages received to return as part of response */ uint8_t rxBody[240]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */ -uint8_t txBody[256]; /* Return message buffer for computed replies */ +uint8_t txBody[MATRIX_ROWS/2]; /* Return message buffer for computed replies */ BaseSequentialStream *chp = NULL; // Used for serial logging @@ -126,19 +126,12 @@ const char hexString[16] = "0123456789abcdef"; * Note: Called in interrupt context, so need to be quick! */ void twi2c_slave_message_process(I2CDriver *i2cp) { - uint8_t *txPtr = txBody; - uint8_t txLen; - size_t len = i2cSlaveBytes(i2cp); // Number of bytes received + // size_t len = i2cSlaveBytes(i2cp); // Number of bytes received - if (len >= 2 && rxBody[0] == 0x01 && rxBody[1] == 0x00) { - matrix_row_t matrix[MATRIX_ROWS / 2]; - matrix_copy(matrix); - memcpy(txPtr, matrix, MATRIX_ROWS / 2); - txLen = MATRIX_ROWS / 2; - } + matrix_copy(txBody); - echoReply.size = txLen; + echoReply.size = MATRIX_ROWS / 2; i2cSlaveReplyI(i2cp, &echoReply); } diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index 1d67851ba2..cbf4537bf6 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -55,7 +55,8 @@ void matrix_init(void) { right_hand = palReadPad(GPIOC, 13); // if USB is active, this is the master - master = (USB_DRIVER.state == USB_ACTIVE); + // master = usbGetDriverStateI(&USB_DRIVER) == USB_ACTIVE; + master = right_hand; if (master) { twi2c_master_init(); @@ -127,23 +128,25 @@ matrix_row_t matrix_scan_common(uint8_t row) { return data; } +const uint8_t command[2] = { 0x01, 0x00 }; +uint8_t other_matrix[MATRIX_ROWS] = { 0 }; + void matrix_scan_master(void) { - const uint8_t command[2] = { 0x01, 0x00 }; - uint8_t other_matrix[MATRIX_ROWS]; - msg_t resp; - resp = twi2c_master_send(slaveI2Caddress/2, command, other_matrix, TIME_INFINITE); - printf("%x\n", resp); + resp = twi2c_master_send(slaveI2Caddress/2, command, other_matrix, TIME_IMMEDIATE); + // printf("%x\n", resp); - uint8_t * matrix_pointer; - if (right_hand) { - matrix_pointer = matrix; - } else { - matrix_pointer = matrix + (MATRIX_ROWS / 2); + if (resp == MSG_OK) { + uint8_t * matrix_pointer; + if (right_hand) { + matrix_pointer = matrix; + } else { + matrix_pointer = matrix + (MATRIX_ROWS / 2); + } + + memcpy(matrix_pointer, other_matrix, MATRIX_ROWS / 2); } - - memcpy(matrix_pointer, other_matrix, MATRIX_ROWS / 2); } uint8_t matrix_scan(void) { From 8b5b41bb4781c5fa08d9d1a149aa416631095f11 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 19 Feb 2018 22:00:38 -0500 Subject: [PATCH 10/59] update handwire with arm changes --- keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h | 2 +- keyboards/_qmk_handwire/config.h | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h index 254c84a097..23d0037b21 100644 --- a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h @@ -1171,7 +1171,7 @@ * USB bus de-activation macro, required by the USB driver. */ // #define usb_lld_disconnect_bus(usbp) -#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)) +#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP) // #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12) #if !defined(_FROM_ASM_) diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/_qmk_handwire/config.h index 7243e13647..fe0ad1d5c4 100644 --- a/keyboards/_qmk_handwire/config.h +++ b/keyboards/_qmk_handwire/config.h @@ -22,10 +22,8 @@ #define VENDOR_ID 0x125A #define PRODUCT_ID 0x1770 #define DEVICE_VER 0x0001 -#define MANUFACTURER "QMK" -#define USBSTR_MANUFACTURER 'Q', '\x00', 'M', '\x00', 'K', '\x00' -#define PRODUCT "Handwire" -#define USBSTR_PRODUCT 'H', '\x00', 'a', '\x00', 'n', '\x00', 'd', '\x00', 'w', '\x00', 'i', '\x00', 'r', '\x00', 'e', '\x00' +#define MANUFACTURER QMK +#define PRODUCT Handwire #define DESCRIPTION "Handwire protoboard" /* key matrix size */ From 00fc38435f0266872bdf35b0a943ac599ce57883 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 22 Feb 2018 21:22:47 -0500 Subject: [PATCH 11/59] master working --- drivers/arm/twi2c.c | 54 +++++++++++++------ drivers/arm/twi2c.h | 5 +- .../boards/GENERIC_STM32_F303XC/board.c | 4 +- .../_qmk_handwire/keymaps/default/keymap.c | 4 +- keyboards/_qmk_handwire/matrix.c | 9 +++- 5 files changed, 55 insertions(+), 21 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 299e52eb2a..2b9209f5db 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -23,10 +23,6 @@ #include "printf.h" #include "matrix.h" -#ifndef I2C_DRIVER - #define I2C_DRIVER I2CD1 -#endif - /** * I2C slave test routine. * @@ -37,8 +33,13 @@ * b) A write then read transaction - calls a message processor and returns the generated reply. * Stretches clock until reply available. */ +// static const I2CConfig masterI2CConfig = { +// 400000 +// }; -static const I2CConfig uniI2CConfig = { +I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; + +static const I2CConfig slaveI2CConfig = { STM32_TIMINGR_PRESC(15U) | STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), @@ -52,7 +53,7 @@ char initialReplyBody[50] = "Initial reply"; // 'Status' response if read uint32_t messageCounter = 0; /* Counts number of messages received to return as part of response */ -uint8_t rxBody[240]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */ +uint8_t rxBody[2]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */ uint8_t txBody[MATRIX_ROWS/2]; /* Return message buffer for computed replies */ BaseSequentialStream *chp = NULL; // Used for serial logging @@ -68,16 +69,26 @@ const I2CSlaveMsg echoRx = }; -// 'Empty' reply when nothing to say, and no message received. In RAM, to allow update +// // 'Empty' reply when nothing to say, and no message received. In RAM, to allow update I2CSlaveMsg initialReply = { - sizeof(initialReplyBody), /* trailing zero byte will be repeated as needed */ + sizeof(initialReplyBody), /* trailing zero byte will be repeated as needed */ (uint8_t *)initialReplyBody, NULL, /* do nothing on address match */ NULL, /* do nothing after reply sent */ catchError /* Error hook */ }; +// // 'Empty' reply when nothing to say, and no message received. In RAM, to allow update +// I2CSlaveMsg initialReply = +// { +// 0, /* trailing zero byte will be repeated as needed */ +// NULL, +// NULL, /* do nothing on address match */ +// NULL, /* do nothing after reply sent */ +// catchError /* Error hook */ +// }; + // Response to received messages I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ @@ -129,7 +140,8 @@ void twi2c_slave_message_process(I2CDriver *i2cp) { // size_t len = i2cSlaveBytes(i2cp); // Number of bytes received - matrix_copy(txBody); + memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); + // matrix_copy(txBody); echoReply.size = MATRIX_ROWS / 2; i2cSlaveReplyI(i2cp, &echoReply); @@ -162,17 +174,18 @@ void twi2c_slave_init(void) { palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); - i2cStart(&I2C_DRIVER, &uniI2CConfig); + i2cStart(&I2C_DRIVER, &slaveI2CConfig); #if HAL_USE_I2C_SLAVE I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif - i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); + // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); + i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); // Enable match address after everything else set up i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); // i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); -// i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ + // i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ printf("Slave I2C started\n\r"); @@ -186,9 +199,18 @@ void twi2c_slave_task(void) { } void twi2c_master_init(void) { - i2cStart(&I2C_DRIVER, &uniI2CConfig); -} -msg_t twi2c_master_send(i2caddr_t address, const uint8_t * txbuf, uint8_t * rxbuf, systime_t timeout) { - return i2cMasterTransmitTimeout(&I2C_DRIVER, address, txbuf, sizeof(txbuf), rxbuf, sizeof(rxbuf), timeout); + palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time + chThdSleepMilliseconds(10); + + palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + + i2cStart(&I2C_DRIVER, &slaveI2CConfig); + + // try high drive (from kiibohd) + // I2C_DRIVER.i2c->C2 |= I2Cx_C2_HDRS; + // try glitch fixing (from kiibohd) + // I2C_DRIVER.i2c->FLT = 4; + } diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index 175572189b..bc7a064a58 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -17,6 +17,10 @@ #include "ch.h" #include "hal.h" +#ifndef I2C_DRIVER + #define I2C_DRIVER I2CD1 +#endif + #define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ //#define myOtherI2Caddress 0x19 @@ -25,4 +29,3 @@ I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; void twi2c_slave_init(void); void twi2c_master_init(void); -msg_t twi2c_master_send(i2caddr_t address, const uint8_t * txbuf, uint8_t * rxbuf, systime_t timeout); diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c index 897f20a887..4331155df4 100644 --- a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c +++ b/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c @@ -62,13 +62,15 @@ const PALConfig pal_default_config = { }; #endif +void enter_bootloader_mode_if_requested(void); + /** * @brief Early initialization code. * @details This initialization must be performed just after stack setup * and before any other initialization. */ void __early_init(void) { - + enter_bootloader_mode_if_requested(); stm32_clock_init(); } diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index 2611f570c3..4874eb91c8 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -34,14 +34,14 @@ enum custom_keycodes { const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( - KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL, + RESET, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL, KC_TAB, DEBUG, KC_W, KC_E, KC_R, KC_T, KC_HOME, KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_END, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_LGUI, KC_SPC, MO(2), MO(1), - KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, RESET, KC_PGUP, KC_Y, KC_U, KC_I, KC_O, DEBUG, KC_DEL, KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index cbf4537bf6..a651d33940 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -134,8 +134,15 @@ uint8_t other_matrix[MATRIX_ROWS] = { 0 }; void matrix_scan_master(void) { msg_t resp; - resp = twi2c_master_send(slaveI2Caddress/2, command, other_matrix, TIME_IMMEDIATE); + // resp = twi2c_master_send(slaveI2Caddress/2, command, 2, other_matrix, US2ST(100)); + // resp = i2cMasterTransmitTimeout(&I2C_DRIVER, slaveI2Caddress/2, command, 2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); + resp = i2cMasterReceiveTimeout(&I2C_DRIVER, slaveI2Caddress/2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); // printf("%x\n", resp); + // if (resp != MSG_OK) { + // for (i = 0; i < MATRIX_ROWS / 2; i++) { + // resp = i2cMasterReceiveTimeout(&I2C_DRIVER, slaveI2Caddress/2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); + // } + // } if (resp == MSG_OK) { uint8_t * matrix_pointer; From 123ad0de952039aa135fdda80fb83c65a65fd054 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 23 Feb 2018 11:29:30 -0500 Subject: [PATCH 12/59] try more stuff --- drivers/arm/twi2c.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 2b9209f5db..c1ab3c6594 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -179,13 +179,13 @@ void twi2c_slave_init(void) { I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif - // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); - i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); + i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); + // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); // Enable match address after everything else set up - i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); + // i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); // i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); - // i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ + i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ printf("Slave I2C started\n\r"); From b308d6709efed34037e6645384d98c2e1ae7503e Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 23 Feb 2018 12:09:03 -0500 Subject: [PATCH 13/59] working --- drivers/arm/twi2c.c | 21 ++++++++++++--------- keyboards/_qmk_handwire/matrix.c | 4 ++-- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index c1ab3c6594..7200d2db95 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -92,7 +92,7 @@ I2CSlaveMsg initialReply = // Response to received messages I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ - 0, /* filled in with the length of the message to send */ + MATRIX_ROWS / 2, /* filled in with the length of the message to send */ txBody, /* Response message */ NULL, /* do nothing special on address match */ clearAfterSend, /* Clear receive buffer once replied */ @@ -140,8 +140,8 @@ void twi2c_slave_message_process(I2CDriver *i2cp) { // size_t len = i2cSlaveBytes(i2cp); // Number of bytes received - memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); - // matrix_copy(txBody); + // memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); + matrix_copy(txBody); echoReply.size = MATRIX_ROWS / 2; i2cSlaveReplyI(i2cp, &echoReply); @@ -153,8 +153,8 @@ void twi2c_slave_message_process(I2CDriver *i2cp) { */ void clearAfterSend(I2CDriver *i2cp) { - echoReply.size = 0; // Clear receive message - i2cSlaveReplyI(i2cp, &initialReply); + // echoReply.size = 0; // Clear receive message + // i2cSlaveReplyI(i2cp, &initialReply); } @@ -179,13 +179,16 @@ void twi2c_slave_init(void) { I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif - i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); - // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); + // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); + + memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); + + i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); // Enable match address after everything else set up - // i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); + i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); // i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); - i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ + // i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ printf("Slave I2C started\n\r"); diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index a651d33940..499c92f8ca 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -135,8 +135,8 @@ void matrix_scan_master(void) { msg_t resp; // resp = twi2c_master_send(slaveI2Caddress/2, command, 2, other_matrix, US2ST(100)); - // resp = i2cMasterTransmitTimeout(&I2C_DRIVER, slaveI2Caddress/2, command, 2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); - resp = i2cMasterReceiveTimeout(&I2C_DRIVER, slaveI2Caddress/2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); + resp = i2cMasterTransmitTimeout(&I2C_DRIVER, slaveI2Caddress/2, command, 2, other_matrix, MATRIX_ROWS / 2, MS2ST(100)); + // resp = i2cMasterReceiveTimeout(&I2C_DRIVER, slaveI2Caddress/2, other_matrix, MATRIX_ROWS / 2, US2ST(100)); // printf("%x\n", resp); // if (resp != MSG_OK) { // for (i = 0; i < MATRIX_ROWS / 2; i++) { From da32068f489e94eff7ebf57b83c6a55d405ca81f Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 26 Feb 2018 21:29:07 -0500 Subject: [PATCH 14/59] update to qwerty --- .../_qmk_handwire/keymaps/default/keymap.c | 29 ++++++++++++++----- 1 file changed, 22 insertions(+), 7 deletions(-) diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/_qmk_handwire/keymaps/default/keymap.c index 4874eb91c8..168be875c2 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/_qmk_handwire/keymaps/default/keymap.c @@ -34,20 +34,35 @@ enum custom_keycodes { const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS] = { [0] = KEYMAP( - RESET, KC_1, KC_2, KC_3, KC_4, KC_0, KC_DEL, - KC_TAB, DEBUG, KC_W, KC_E, KC_R, KC_T, KC_HOME, + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_DEL, + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_HOME, KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_END, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_N, - KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_LGUI, - KC_SPC, MO(2), MO(1), + KC_NO, KC_LCTL, KC_LALT, KC_LGUI, MO(1), + KC_SPC, MO(1), RESET, - KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, RESET, - KC_PGUP, KC_Y, KC_U, KC_I, KC_O, DEBUG, KC_DEL, + KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_PGUP, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_DEL, KC_PGDN, KC_H, KC_J, KC_K, KC_L, KC_COLN, KC_QUOT, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, KC_RCTL, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, - MO(2), MO(1), KC_SPC + RESET, MO(2), KC_SPC ) + // [0] = KEYMAP( + // KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_DEL, + // KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_HOME, + // KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_END, + // KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, + // KC_NO, KC_LCTL, KC_LALT, KC_LGUI, MO(1), + // KC_SPC, MO(1), RESET, + + // KC_INS, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + // KC_PGUP, KC_J, KC_L, KC_U, KC_Y, KC_COLN, KC_DEL, + // KC_PGDN, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, + // KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + // KC_RGUI, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT, + // RESET, MO(2), KC_SPC + // ) }; bool process_record_user(uint16_t keycode, keyrecord_t *record) { From 2bd625b75431df090a2297199cce98c1fba0c748 Mon Sep 17 00:00:00 2001 From: Some Person Date: Mon, 5 Mar 2018 19:56:09 -0500 Subject: [PATCH 15/59] bla --- lib/chibios | 2 +- lib/chibios-contrib | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/chibios b/lib/chibios index f9643c88ad..8fce03b3a7 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit f9643c88ad5cd0704d57bed83fe64f45b3e6be4e +Subproject commit 8fce03b3a75c743e5d5c40b9d59c1637c59d22a7 diff --git a/lib/chibios-contrib b/lib/chibios-contrib index ede48346ee..e1311c4db6 160000 --- a/lib/chibios-contrib +++ b/lib/chibios-contrib @@ -1 +1 @@ -Subproject commit ede48346eee4b8d6847c19bc01420bee76a5e486 +Subproject commit e1311c4db6cd366cf760673f769e925741ac0ad3 From b034896cd303270eea2b217b9f0d234d003b4507 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 5 Mar 2018 20:24:20 -0500 Subject: [PATCH 16/59] update submodule --- .gitmodules | 1 + lib/chibios | 2 +- lib/chibios-contrib | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitmodules b/.gitmodules index 0e870021f0..eab2ee2bba 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,7 @@ [submodule "lib/chibios"] path = lib/chibios url = https://github.com/qmk/ChibiOS + branch = handwire [submodule "lib/chibios-contrib"] path = lib/chibios-contrib url = https://github.com/qmk/ChibiOS-Contrib diff --git a/lib/chibios b/lib/chibios index 8fce03b3a7..f9643c88ad 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit 8fce03b3a75c743e5d5c40b9d59c1637c59d22a7 +Subproject commit f9643c88ad5cd0704d57bed83fe64f45b3e6be4e diff --git a/lib/chibios-contrib b/lib/chibios-contrib index e1311c4db6..ede48346ee 160000 --- a/lib/chibios-contrib +++ b/lib/chibios-contrib @@ -1 +1 @@ -Subproject commit e1311c4db6cd366cf760673f769e925741ac0ad3 +Subproject commit ede48346eee4b8d6847c19bc01420bee76a5e486 From 12a64ff24b1dbdaf69dda529dd95219371206a58 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 16 Mar 2018 03:38:20 -0400 Subject: [PATCH 17/59] initial files for rev 6 with encoder --- keyboards/planck/config.h | 2 + keyboards/planck/keymaps/default/keymap.c | 88 +- keyboards/planck/planck.c | 2 + keyboards/planck/planck.h | 94 ++ .../rev6/boards/GENERIC_STM32_F303XC/board.c | 126 ++ .../rev6/boards/GENERIC_STM32_F303XC/board.h | 1187 +++++++++++++++++ .../rev6/boards/GENERIC_STM32_F303XC/board.mk | 5 + keyboards/planck/rev6/bootloader_defs.h | 7 + keyboards/planck/rev6/chconf.h | 520 ++++++++ keyboards/planck/rev6/config.h | 124 ++ keyboards/planck/rev6/halconf.h | 388 ++++++ keyboards/planck/rev6/matrix.c | 168 +++ keyboards/planck/rev6/mcuconf.h | 257 ++++ keyboards/planck/rev6/rev6.c | 24 + keyboards/planck/rev6/rev6.h | 21 + keyboards/planck/rev6/rules.mk | 55 + 16 files changed, 3026 insertions(+), 42 deletions(-) create mode 100644 keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.c create mode 100644 keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h create mode 100644 keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.mk create mode 100644 keyboards/planck/rev6/bootloader_defs.h create mode 100644 keyboards/planck/rev6/chconf.h create mode 100644 keyboards/planck/rev6/config.h create mode 100644 keyboards/planck/rev6/halconf.h create mode 100644 keyboards/planck/rev6/matrix.c create mode 100644 keyboards/planck/rev6/mcuconf.h create mode 100644 keyboards/planck/rev6/rev6.c create mode 100644 keyboards/planck/rev6/rev6.h create mode 100644 keyboards/planck/rev6/rules.mk diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h index 452a99d746..097bacd715 100644 --- a/keyboards/planck/config.h +++ b/keyboards/planck/config.h @@ -18,7 +18,9 @@ along with this program. If not, see . #ifndef CONFIG_H #define CONFIG_H +#ifdef __AVR__ #include "config_common.h" +#endif /* USB Device descriptor parameter */ #define VENDOR_ID 0xFEED diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 04fc33640d..0bb70ca7b1 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -53,12 +53,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | * `-----------------------------------------------------------------------------------' */ -[_QWERTY] = { - {KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC}, - {KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT}, - {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT }, - {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT} -}, +[_QWERTY] = LAYOUT_planck_grid( + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT +), /* Colemak * ,-----------------------------------------------------------------------------------. @@ -71,12 +71,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | * `-----------------------------------------------------------------------------------' */ -[_COLEMAK] = { - {KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC}, - {KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT}, - {KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT }, - {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT} -}, +[_COLEMAK] = LAYOUT_planck_grid( + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, + KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , + KC_SPC, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT +), /* Dvorak * ,-----------------------------------------------------------------------------------. @@ -89,12 +89,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | * `-----------------------------------------------------------------------------------' */ -[_DVORAK] = { - {KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC}, - {KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH}, - {KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT }, - {BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT} -}, +[_DVORAK] = LAYOUT_planck_grid( + KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, + KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, + KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT , + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT +), /* Lower * ,-----------------------------------------------------------------------------------. @@ -107,12 +107,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | | | | | | | Next | Vol- | Vol+ | Play | * `-----------------------------------------------------------------------------------' */ -[_LOWER] = { - {KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC}, - {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE}, - {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, S(KC_NUHS), S(KC_NUBS), KC_HOME, KC_END, _______}, - {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY} -}, +[_LOWER] = LAYOUT_planck_grid( + KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, + KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, + _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, S(KC_NUHS), S(KC_NUBS), KC_HOME, KC_END, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY +), /* Raise * ,-----------------------------------------------------------------------------------. @@ -125,12 +125,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | | | | | | | Next | Vol- | Vol+ | Play | * `-----------------------------------------------------------------------------------' */ -[_RAISE] = { - {KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC}, - {KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS}, - {_______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______}, - {_______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY} -}, +[_RAISE] = LAYOUT_planck_grid( + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, + _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, KC_F12, KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______, + _______, _______, _______, _______, _______, _______, _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY +), /* Plover layer (http://opensteno.org) * ,-----------------------------------------------------------------------------------. @@ -144,12 +144,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * `-----------------------------------------------------------------------------------' */ -[_PLOVER] = { - {KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 }, - {XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC}, - {XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT}, - {EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX} -}, +[_PLOVER] = LAYOUT_planck_grid( + KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 , + XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, + XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, + EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX, XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX +), /* Adjust (Lower + Raise) * ,-----------------------------------------------------------------------------------. @@ -162,12 +162,12 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { * | | | | | | | | | | | | * `-----------------------------------------------------------------------------------' */ -[_ADJUST] = { - {_______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL }, - {_______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______}, - {_______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______}, - {_______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______} -} +[_ADJUST] = LAYOUT_planck_grid( + _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL , + _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______, + _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______, + _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______, _______ +) }; @@ -224,10 +224,14 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { #ifdef BACKLIGHT_ENABLE backlight_step(); #endif + #ifdef __AVR__ PORTE &= ~(1<<6); + #endif } else { unregister_code(KC_RSFT); + #ifdef __AVR__ PORTE |= (1<<6); + #endif } return false; break; diff --git a/keyboards/planck/planck.c b/keyboards/planck/planck.c index 1d2f91bc55..9f7ffde8e9 100644 --- a/keyboards/planck/planck.c +++ b/keyboards/planck/planck.c @@ -13,8 +13,10 @@ const keypos_t hand_swap_config[MATRIX_ROWS][MATRIX_COLS] = { __attribute__ ((weak)) void matrix_init_kb(void) { // Turn status LED on + #ifdef __AVR__ DDRE |= (1<<6); PORTE |= (1<<6); + #endif matrix_init_user(); } diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h index b663ba1c7c..626798912b 100644 --- a/keyboards/planck/planck.h +++ b/keyboards/planck/planck.h @@ -3,6 +3,7 @@ #include "quantum.h" +#ifdef __AVR__ #define LAYOUT_planck_mit( \ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ @@ -47,4 +48,97 @@ #define LAYOUT_ortho_4x12 LAYOUT_planck_grid #define KC_LAYOUT_ortho_4x12 KC_KEYMAP +#else + + #define LAYOUT_planck_1x2uC( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \ + k30, k31, k32, k33, k34, k35, k37, k38, k39, k3a, k3b \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k06, k07, k08, k09, k0a, k0b }, \ + { k16, k17, k18, k19, k1a, k1b }, \ + { k26, k27, k28, k29, k2a, k2b }, \ + { k36, k37, k38, k39, k3a, k3b } \ +} + +#define LAYOUT_planck_1x2uR( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \ + k30, k31, k32, k33, k34, k35, k37, k38, k39, k3a, k3b \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k06, k07, k08, k09, k0a, k0b }, \ + { k16, k17, k18, k19, k1a, k1b }, \ + { k26, k27, k28, k29, k2a, k2b }, \ + { k36, k37, k38, k39, k3a, k3b } \ +} + +#define LAYOUT_planck_1x2uL( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \ + k30, k31, k32, k33, k34, k36, k37, k38, k39, k3a, k3b \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k06, k07, k08, k09, k0a, k0b }, \ + { k16, k17, k18, k19, k1a, k1b }, \ + { k26, k27, k28, k29, k2a, k2b }, \ + { k36, k37, k38, k39, k3a, k3b } \ +} + +#define LAYOUT_planck_2x2u( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \ + k30, k31, k32, k33, k34, k36, k38, k39, k3a, k3b \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k06, k07, k08, k09, k0a, k0b }, \ + { k16, k17, k18, k19, k1a, k1b }, \ + { k26, k27, k28, k29, k2a, k2b }, \ + { k36, k37, k38, k39, k3a, k3b } \ +} + +#define LAYOUT_planck_grid( \ + k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ + k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ + k20, k21, k22, k23, k24, k25, k26, k27, k28, k29, k2a, k2b, \ + k30, k31, k32, k33, k34, k35, k36, k37, k38, k39, k3a, k3b \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 }, \ + { k06, k07, k08, k09, k0a, k0b }, \ + { k16, k17, k18, k19, k1a, k1b }, \ + { k26, k27, k28, k29, k2a, k2b }, \ + { k36, k37, k38, k39, k3a, k3b } \ +} + +#define KEYMAP LAYOUT_planck_grid +#define LAYOUT_ortho_4x12 LAYOUT_planck_grid +#define KC_LAYOUT_ortho_4x12 KC_KEYMAP + +#endif + #endif diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.c b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.c new file mode 100644 index 0000000000..4331155df4 --- /dev/null +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.c @@ -0,0 +1,126 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +const PALConfig pal_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} +#endif +}; +#endif + +void enter_bootloader_mode_if_requested(void); + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + enter_bootloader_mode_if_requested(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h new file mode 100644 index 0000000000..e09112eb98 --- /dev/null +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h @@ -0,0 +1,1187 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for Clueboard 60% Keyboard + */ + +/* + * Board identifier. + */ +#define BOARD_GENERIC_STM32_F303XC +#define BOARD_NAME "Clueboard 60 PCB" + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 0U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +// #define STM32_HSE_BYPASS + +/* + * MCU type as defined in the ST header. + */ +#define STM32F303xC + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_PIN1 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_PIN4 4U +#define GPIOA_PIN5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_PIN8 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_I2C2_SDA 0U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_PIN0 0U +#define GPIOH_PIN1 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_L3GD20_SDI PAL_LINE(GPIOA, 7U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_PIN6 PAL_LINE(GPIOF, 0U) +#define LINE_PIN7 PAL_LINE(GPIOF, 1U) + +#define LINE_CAPS_LOCK PAL_LINE(GPIOB, 7U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - NC + * PA1 - NC + * PA2 - COL1 + * PA3 - COL2 + * PA4 - SPEAKER1 + * PA5 - SPEAKER2 + * PA6 - COL3 + * PA7 - COL8 + * PA8 - COL6 + * PA9 - COL7 + * PA10 - ROW5 + * PA11 - USB_DM (alternate 14). + * PA12 - USB_DP (alternate 14). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ROW4 + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_INPUT(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_PIN2) | \ + PIN_MODE_INPUT(GPIOA_PIN3) | \ + PIN_MODE_INPUT(GPIOA_PIN4) | \ + PIN_MODE_INPUT(GPIOA_PIN5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_PIN2) | \ + PIN_ODR_HIGH(GPIOA_PIN3) | \ + PIN_ODR_HIGH(GPIOA_PIN4) | \ + PIN_ODR_HIGH(GPIOA_PIN5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \ + PIN_AFIO_AF(GPIOA_PIN1, 0) | \ + PIN_AFIO_AF(GPIOA_PIN2, 0) | \ + PIN_AFIO_AF(GPIOA_PIN3, 0) | \ + PIN_AFIO_AF(GPIOA_PIN4, 0) | \ + PIN_AFIO_AF(GPIOA_PIN5, 5) | \ + PIN_AFIO_AF(GPIOA_PIN6, 5) | \ + PIN_AFIO_AF(GPIOA_PIN7, 5)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 14) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 14) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - PIN3 (alternate 0). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - PIN6 LSM303DLHC_SCL (alternate 4). + * PB7 - PIN7 LSM303DLHC_SDA (alternate 4). + * PB8 - PIN8 (input pullup). + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN6) | \ + PIN_MODE_OUTPUT(GPIOB_PIN7) | \ + PIN_MODE_INPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ + PIN_OSPEED_HIGH(GPIOB_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN6) | \ + PIN_PUPDR_PULLDOWN(GPIOB_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_PIN3) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_HIGH(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_PIN6) | \ + PIN_ODR_LOW(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0) | \ + PIN_AFIO_AF(GPIOB_PIN6, 4) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input floating). + * PC15 - PIN15 (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD11 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 L3GD20_CS (output pushpull maximum). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (output pushpull maximum). + * PE9 - PIN9 (output pushpull maximum). + * PE10 - PIN10 (output pushpull maximum). + * PE11 - PIN11 (output pushpull maximum). + * PE12 - PIN12 (output pushpull maximum). + * PE13 - PIN13 (output pushpull maximum). + * PE14 - PIN14 (output pushpull maximum). + * PE15 - PIN15 (output pushpull maximum). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) |\ + PIN_MODE_OUTPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) |\ + PIN_MODE_INPUT(GPIOE_PIN5) |\ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_OUTPUT(GPIOE_PIN8) | \ + PIN_MODE_OUTPUT(GPIOE_PIN9) | \ + PIN_MODE_OUTPUT(GPIOE_PIN10) | \ + PIN_MODE_OUTPUT(GPIOE_PIN11) | \ + PIN_MODE_OUTPUT(GPIOE_PIN12) | \ + PIN_MODE_OUTPUT(GPIOE_PIN13) | \ + PIN_MODE_OUTPUT(GPIOE_PIN14) | \ + PIN_MODE_OUTPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN5) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN14) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_LOW(GPIOE_PIN8) | \ + PIN_ODR_LOW(GPIOE_PIN9) | \ + PIN_ODR_LOW(GPIOE_PIN10) | \ + PIN_ODR_LOW(GPIOE_PIN11) | \ + PIN_ODR_LOW(GPIOE_PIN12) | \ + PIN_ODR_LOW(GPIOE_PIN13) | \ + PIN_ODR_LOW(GPIOE_PIN14) | \ + PIN_ODR_LOW(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0) |\ + PIN_AFIO_AF(GPIOE_PIN3, 0) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0) |\ + PIN_AFIO_AF(GPIOE_PIN5, 0) |\ + PIN_AFIO_AF(GPIOE_PIN6, 0) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0)) + +/* + * GPIOF setup: + * + * PF0 - I2C2_SDA (input floating). + * PF1 - I2C2_SCL (input floating). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_I2C2_SDA) | \ + PIN_MODE_INPUT(GPIOF_I2C2_SCL) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) | \ + PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) | \ + PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_I2C2_SDA) | \ + PIN_ODR_HIGH(GPIOF_I2C2_SCL) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) | \ + PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0)) + +/* + * GPIOH setup: + * + * PH0 - PIN0 (input pullup). + * PH1 - PIN1 (input pullup). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_PIN0) | \ + PIN_MODE_INPUT(GPIOH_PIN1) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOH_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_PULLUP(GPIOH_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_PIN0) | \ + PIN_ODR_HIGH(GPIOH_PIN1) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_PIN0, 0) | \ + PIN_AFIO_AF(GPIOH_PIN1, 0) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0)) + + +/* + * USB bus activation macro, required by the USB driver. + */ +// #define usb_lld_connect_bus(usbp) +#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14))) +// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT) +/* + * USB bus de-activation macro, required by the USB driver. + */ +// #define usb_lld_disconnect_bus(usbp) +#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP) +// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.mk b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.mk new file mode 100644 index 0000000000..43377629a3 --- /dev/null +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC diff --git a/keyboards/planck/rev6/bootloader_defs.h b/keyboards/planck/rev6/bootloader_defs.h new file mode 100644 index 0000000000..3b0e9d20a6 --- /dev/null +++ b/keyboards/planck/rev6/bootloader_defs.h @@ -0,0 +1,7 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/keyboards/planck/rev6/chconf.h b/keyboards/planck/rev6/chconf.h new file mode 100644 index 0000000000..5a9b833107 --- /dev/null +++ b/keyboards/planck/rev6/chconf.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h new file mode 100644 index 0000000000..05d3ed49ef --- /dev/null +++ b/keyboards/planck/rev6/config.h @@ -0,0 +1,124 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef REV6_CONFIG_H +#define REV6_CONFIG_H + +/* USB Device descriptor parameter */ +#define DEVICE_VER 0x0006 + +#undef MATRIX_ROWS +#undef MATRIX_COLS +/* key matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 6 + +/* + * Keyboard Matrix Assignments + * + * Change this to how you wired your keyboard + * COLS: AVR pins used for columns, left to right + * ROWS: AVR pins used for rows, top to bottom + * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) + * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) + * +*/ +/* Note: These are not used for arm boards. They're here purely as documentation. + * #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 } + * #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 } + * #define UNUSED_PINS + */ + +/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ +#define DEBOUNCE 6 + +/* Prevent modifiers from being stuck on after layer changes. */ +#define PREVENT_STUCK_MODIFIERS + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +//#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +//#define LOCKING_RESYNC_ENABLE + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +//#define FORCE_NKRO + +/* key combination for magic key command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +//#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 1 + +#endif diff --git a/keyboards/planck/rev6/halconf.h b/keyboards/planck/rev6/halconf.h new file mode 100644 index 0000000000..8fe8e0c6f5 --- /dev/null +++ b/keyboards/planck/rev6/halconf.h @@ -0,0 +1,388 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC TRUE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT TRUE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C FALSE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 1 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c new file mode 100644 index 0000000000..098e8311d2 --- /dev/null +++ b/keyboards/planck/rev6/matrix.c @@ -0,0 +1,168 @@ +#include +#include +#include +#include "hal.h" +#include "timer.h" +#include "wait.h" +#include "printf.h" +#include "backlight.h" +#include "matrix.h" +#include "action.h" +#include "keycode.h" + +/* + * col: { B11, B10, B2, B1, A7, B0 } + * row: { A10, A9, A8, B15, C13, C14, C15, A2 } + */ +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t matrix_debouncing[MATRIX_COLS]; +static bool debouncing = false; +static uint16_t debouncing_time = 0; +static uint8_t encoder_state = 0; +static int8_t encoder_value = 0; +static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; + +__attribute__ ((weak)) +void matrix_init_user(void) {} + +__attribute__ ((weak)) +void matrix_scan_user(void) {} + +__attribute__ ((weak)) +void matrix_init_kb(void) { + matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void matrix_init(void) { + printf("matrix init\n"); + //debug_matrix = true; + + palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); + + palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN); + + palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); + + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); + + encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); + + matrix_init_quantum(); +} + +uint8_t matrix_scan(void) { + encoder_state <<= 2; + encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); + encoder_value += encoder_LUT[encoder_state & 0xF]; + if (encoder_value >= 4) { + register_code(KC_PGUP); + unregister_code(KC_PGUP); + } + if (encoder_value <= -4) { + register_code(KC_PGDN); + unregister_code(KC_PGDN); + } + encoder_value %= 4; + + for (int col = 0; col < MATRIX_COLS; col++) { + matrix_row_t data = 0; + + // strobe col { B11, B10, B2, B1, A7, B0 } + switch (col) { + case 0: palSetPad(GPIOB, 11); break; + case 1: palSetPad(GPIOB, 10); break; + case 2: palSetPad(GPIOB, 2); break; + case 3: palSetPad(GPIOB, 1); break; + case 4: palSetPad(GPIOA, 7); break; + case 5: palSetPad(GPIOB, 0); break; + } + + // need wait to settle pin state + wait_us(20); + + // read row data { A10, A9, A8, B15, C13, C14, C15, A2 } + data = ( + (palReadPad(GPIOA, 10) << 0 ) | + (palReadPad(GPIOA, 9) << 1 ) | + (palReadPad(GPIOA, 8) << 2 ) | + (palReadPad(GPIOB, 15) << 3 ) | + (palReadPad(GPIOC, 13) << 4 ) | + (palReadPad(GPIOC, 14) << 5 ) | + (palReadPad(GPIOC, 15) << 6 ) | + (palReadPad(GPIOA, 2) << 7 ) + ); + + // unstrobe col { B11, B10, B2, B1, A7, B0 } + switch (col) { + case 0: palClearPad(GPIOB, 11); break; + case 1: palClearPad(GPIOB, 10); break; + case 2: palClearPad(GPIOB, 2); break; + case 3: palClearPad(GPIOB, 1); break; + case 4: palClearPad(GPIOA, 7); break; + case 5: palClearPad(GPIOB, 0); break; + } + + if (matrix_debouncing[col] != data) { + matrix_debouncing[col] = data; + debouncing = true; + debouncing_time = timer_read(); + } + } + + if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + for (int row = 0; row < MATRIX_ROWS; row++) { + matrix[row] = 0; + for (int col = 0; col < MATRIX_COLS; col++) { + matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); + } + } + debouncing = false; + } + + matrix_scan_quantum(); + + return 1; +} + +bool matrix_is_on(uint8_t row, uint8_t col) { + return (matrix[row] & (1< + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "rev6.h" + +void matrix_init_kb(void) { + +} + +void matrix_scan_kb(void) { + +} diff --git a/keyboards/planck/rev6/rev6.h b/keyboards/planck/rev6/rev6.h new file mode 100644 index 0000000000..75c2904c5c --- /dev/null +++ b/keyboards/planck/rev6/rev6.h @@ -0,0 +1,21 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef REV6_H +#define REV6_H + +#include "planck.h" + +#endif diff --git a/keyboards/planck/rev6/rules.mk b/keyboards/planck/rev6/rules.mk new file mode 100644 index 0000000000..c49b528e3c --- /dev/null +++ b/keyboards/planck/rev6/rules.mk @@ -0,0 +1,55 @@ +# project specific files +SRC = matrix.c +LAYOUTS += ortho_4x12 + +## chip/board settings +# - the next two should match the directories in +# /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F3xx + +# Linker script to use +# - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT = STM32F303xC + +# Startup code to use +# - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f3xx + +# Board: it should exist either in /os/hal/boards/ +# or /boards +BOARD = GENERIC_STM32_F303XC + +# Cortex version +MCU = cortex-m4 + +# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +ARMV = 7 + +USE_FPU = yes + +# Vector table for application +# 0x00000000-0x00001000 area is occupied by bootlaoder.*/ +# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB +# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000 +OPT_DEFS = + +# Options to pass to dfu-util when flashing +DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave + +# Build Options +# comment out to disable the options. +# +BACKLIGHT_ENABLE = no +BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration +## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.) +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +CONSOLE_ENABLE = yes # Console for debug +COMMAND_ENABLE = yes # Commands for debug and configuration +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover +CUSTOM_MATRIX = yes # Custom matrix file +AUDIO_ENABLE = yes +# SERIAL_LINK_ENABLE = yes From 91efe7436579733769b53f330fcc2f1be5c4373a Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 22 Mar 2018 01:35:33 -0400 Subject: [PATCH 18/59] music map init, dip scan added --- keyboards/planck/planck.c | 7 ++++ .../rev6/boards/GENERIC_STM32_F303XC/board.h | 2 +- keyboards/planck/rev6/config.h | 6 ++- keyboards/planck/rev6/matrix.c | 35 ++++++++++++---- keyboards/planck/rev6/mcuconf.h | 2 +- keyboards/planck/rev6/rev6.c | 4 +- quantum/audio/audio_arm.c | 40 +++++++++---------- quantum/process_keycode/process_music.c | 33 +++++++++------ quantum/process_keycode/process_music.h | 5 +++ tmk_core/protocol/chibios/usb_main.c | 12 +++--- 10 files changed, 97 insertions(+), 49 deletions(-) diff --git a/keyboards/planck/planck.c b/keyboards/planck/planck.c index 9f7ffde8e9..1296f1b632 100644 --- a/keyboards/planck/planck.c +++ b/keyboards/planck/planck.c @@ -20,3 +20,10 @@ void matrix_init_kb(void) { matrix_init_user(); } + +const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_planck_grid( + 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, + 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, + 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, + 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11 +); \ No newline at end of file diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h index e09112eb98..7b8b826f68 100644 --- a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h @@ -297,7 +297,7 @@ PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ - PIN_PUPDR_FLOATING(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN5) | \ PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ PIN_PUPDR_FLOATING(GPIOA_PIN7) | \ PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h index 05d3ed49ef..831dabe62c 100644 --- a/keyboards/planck/rev6/config.h +++ b/keyboards/planck/rev6/config.h @@ -19,7 +19,7 @@ #define REV6_CONFIG_H /* USB Device descriptor parameter */ -#define DEVICE_VER 0x0006 +#define DEVICE_VER 0x0006 #undef MATRIX_ROWS #undef MATRIX_COLS @@ -43,6 +43,10 @@ * #define UNUSED_PINS */ +#define MUSIC_MAP +#undef AUDIO_VOICES +#undef C6_AUDIO + /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ #define DEBOUNCE 6 diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index 098e8311d2..007c42f0a8 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -19,10 +19,13 @@ static matrix_row_t matrix[MATRIX_ROWS]; static matrix_row_t matrix_debouncing[MATRIX_COLS]; static bool debouncing = false; static uint16_t debouncing_time = 0; + static uint8_t encoder_state = 0; static int8_t encoder_value = 0; static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; +static bool dip_switch[4] = {0, 0, 0, 0}; + __attribute__ ((weak)) void matrix_init_user(void) {} @@ -43,6 +46,19 @@ void matrix_init(void) { printf("matrix init\n"); //debug_matrix = true; + // dip switch setup + palSetPadMode(GPIOB, 14, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP); + + // encoder setup + palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); + + encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); + + // actual matrix setup palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); @@ -59,31 +75,36 @@ void matrix_init(void) { palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN); palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); - encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); matrix_init_quantum(); } uint8_t matrix_scan(void) { + // dip switch + dip_switch[0] = palReadPad(GPIOB, 14); + dip_switch[1] = palReadPad(GPIOA, 15); + dip_switch[2] = palReadPad(GPIOA, 10); + dip_switch[3] = palReadPad(GPIOB, 9); + + // encoder on B12 and B13 encoder_state <<= 2; encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); encoder_value += encoder_LUT[encoder_state & 0xF]; if (encoder_value >= 4) { - register_code(KC_PGUP); - unregister_code(KC_PGUP); + register_code(KC_MS_WH_UP); + unregister_code(KC_MS_WH_UP); } if (encoder_value <= -4) { - register_code(KC_PGDN); - unregister_code(KC_PGDN); + register_code(KC_MS_WH_DOWN); + unregister_code(KC_MS_WH_DOWN); } encoder_value %= 4; + // actual matrix for (int col = 0; col < MATRIX_COLS; col++) { matrix_row_t data = 0; diff --git a/keyboards/planck/rev6/mcuconf.h b/keyboards/planck/rev6/mcuconf.h index 94cb540ec9..00179f69f1 100644 --- a/keyboards/planck/rev6/mcuconf.h +++ b/keyboards/planck/rev6/mcuconf.h @@ -197,7 +197,7 @@ * SERIAL driver system settings. */ #define STM32_SERIAL_USE_USART1 FALSE -#define STM32_SERIAL_USE_USART2 FALSE +#define STM32_SERIAL_USE_USART2 TRUE #define STM32_SERIAL_USE_USART3 FALSE #define STM32_SERIAL_USE_UART4 FALSE #define STM32_SERIAL_USE_UART5 FALSE diff --git a/keyboards/planck/rev6/rev6.c b/keyboards/planck/rev6/rev6.c index 16d382a3f8..650e1a194d 100644 --- a/keyboards/planck/rev6/rev6.c +++ b/keyboards/planck/rev6/rev6.c @@ -16,9 +16,9 @@ #include "rev6.h" void matrix_init_kb(void) { - + matrix_init_user(); } void matrix_scan_kb(void) { - + matrix_scan_user(); } diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 247dc337d5..36e4c9904c 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -204,22 +204,6 @@ static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { // squarewave static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -234,7 +218,23 @@ static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047 + }; /* @@ -565,11 +565,11 @@ static void gpt_cb8(GPTDriver *gptp) { bool end_of_note = false; if (GET_CHANNEL_1_FREQ > 0) { if (!note_resting) - end_of_note = (note_position >= (note_length*16 - 1)); + end_of_note = (note_position >= (note_length*8 - 1)); else - end_of_note = (note_position >= (note_length*16)); + end_of_note = (note_position >= (note_length*8)); } else { - end_of_note = (note_position >= (note_length*16)); + end_of_note = (note_position >= (note_length*8)); } if (end_of_note) { diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index c7f41cc388..41a5bd5737 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -28,7 +28,7 @@ bool music_activated = false; bool midi_activated = false; uint8_t music_starting_note = 0x0C; int music_offset = 7; -uint8_t music_mode = MUSIC_MODE_CHROMATIC; +uint8_t music_mode = MUSIC_MODE_MAJOR; // music sequencer static bool music_sequence_recording = false; @@ -201,17 +201,26 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } } - uint8_t note; - if (music_mode == MUSIC_MODE_CHROMATIC) - note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); - else if (music_mode == MUSIC_MODE_GUITAR) - note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); - else if (music_mode == MUSIC_MODE_VIOLIN) - note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); - else if (music_mode == MUSIC_MODE_MAJOR) - note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); - else - note = music_starting_note; + uint8_t note = 36; + #ifdef MUSIC_MAP + if (music_mode == MUSIC_MODE_CHROMATIC) { + note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col]; + } else { + uint8_t position = music_map[record->event.key.row][record->event.key.col]; + note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12)*12; + } + #else + if (music_mode == MUSIC_MODE_CHROMATIC) + note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_GUITAR) + note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_VIOLIN) + note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); + else if (music_mode == MUSIC_MODE_MAJOR) + note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); + else + note = music_starting_note; + #endif if (record->event.pressed) { music_noteon(note); diff --git a/quantum/process_keycode/process_music.h b/quantum/process_keycode/process_music.h index 773bbfa6ba..13e5252ad5 100644 --- a/quantum/process_keycode/process_music.h +++ b/quantum/process_keycode/process_music.h @@ -29,6 +29,11 @@ enum music_modes { NUMBER_OF_MODES }; + +#ifdef MUSIC_MAP + extern const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS]; +#endif + bool process_music(uint16_t keycode, keyrecord_t *record); bool is_music_on(void); diff --git a/tmk_core/protocol/chibios/usb_main.c b/tmk_core/protocol/chibios/usb_main.c index f980024ab8..2ba6f20205 100644 --- a/tmk_core/protocol/chibios/usb_main.c +++ b/tmk_core/protocol/chibios/usb_main.c @@ -717,12 +717,14 @@ void send_mouse(report_mouse_t *report) { } osalSysUnlock(); - /* TODO: LUFA manually waits for the endpoint to become ready - * for about 10ms for mouse, kbd, system; 1ms for nkro - * is this really needed? - */ - osalSysLock(); + if(usbGetTransmitStatusI(&USB_DRIVER, MOUSE_IN_EPNUM)) { + /* Need to either suspend, or loop and call unlock/lock during + * every iteration - otherwise the system will remain locked, + * no interrupts served, so USB not going through as well. + * Note: for suspend, need USB_USE_WAIT == TRUE in halconf.h */ + osalThreadSuspendS(&(&USB_DRIVER)->epc[MOUSE_IN_EPNUM]->in_state->thread); + } usbStartTransmitI(&USB_DRIVER, MOUSE_IN_EPNUM, (uint8_t *)report, sizeof(report_mouse_t)); osalSysUnlock(); } From ddee61c9bae4160326cd422934cb6ab0a5f9eced Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 25 Mar 2018 16:09:40 -0400 Subject: [PATCH 19/59] adds ws2812 driver for arm --- drivers/arm/ws2812.c | 556 ++++++++++++++++++++++++++++++++++++++ drivers/arm/ws2812.h | 94 +++++++ quantum/audio/audio_arm.c | 15 +- 3 files changed, 658 insertions(+), 7 deletions(-) create mode 100644 drivers/arm/ws2812.c create mode 100644 drivers/arm/ws2812.h diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c new file mode 100644 index 0000000000..e39c2554e5 --- /dev/null +++ b/drivers/arm/ws2812.c @@ -0,0 +1,556 @@ +/* + + WS2812B CPU and memory efficient library + + Date: 28.9.2016 + + Author: Martin Hubacek + http://www.martinhubacek.cz + @hubmartin + + Licence: MIT License + +*/ + +#include + +#include "stm32f3xx_hal.h" +#include "ws2812.h" + +extern WS2812_Struct ws2812b; + +// Define source arrays for my DMAs +uint32_t WS2812_IO_High[] = { WS2812B_PINS }; +uint32_t WS2812_IO_Low[] = {WS2812B_PINS << 16}; + +// WS2812 framebuffer - buffer for 2 LEDs - two times 24 bits +uint16_t ws2812bDmaBitBuffer[24 * 2]; + +// Gamma correction table +const uint8_t gammaTable[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, + 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, + 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, + 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, + 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, + 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, + 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, + 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, + 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, + 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, + 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, + 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, + 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, + 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; + +static void ws2812b_gpio_init(void) +{ + // WS2812B outputs + WS2812B_GPIO_CLK_ENABLE(); + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = WS2812B_PINS; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(WS2812B_PORT, &GPIO_InitStruct); + + // Enable output pins for debuging to see DMA Full and Half transfer interrupts + #if defined(LED4_PORT) && defined(LED5_PORT) + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; + + GPIO_InitStruct.Pin = LED4_PIN; + HAL_GPIO_Init(LED4_PORT, &GPIO_InitStruct); + GPIO_InitStruct.Pin = LED5_PIN; + HAL_GPIO_Init(LED5_PORT, &GPIO_InitStruct); + #endif +} + +TIM_HandleTypeDef Tim2Handle; +TIM_OC_InitTypeDef tim2OC1; +TIM_OC_InitTypeDef tim2OC2; + +uint32_t tim_period; +static void TIM2_init(void) +{ + // TIM2 Periph clock enable + __HAL_RCC_TIM2_CLK_ENABLE(); + + // This computation of pulse length should work ok, + // at some slower core speeds it needs some tuning. + tim_period = SystemCoreClock / 800000; // 0,125us period (10 times lower the 1,25us period to have fixed math below) + uint32_t cc1 = (10 * tim_period) / 36; + uint32_t cc2 = (10 * tim_period) / 15; + + Tim2Handle.Instance = TIM2; + + Tim2Handle.Init.Period = tim_period; + Tim2Handle.Init.RepetitionCounter = 0; + Tim2Handle.Init.Prescaler = 0; + Tim2Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; + Tim2Handle.Init.CounterMode = TIM_COUNTERMODE_UP; + HAL_TIM_PWM_Init(&Tim2Handle); + + HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(TIM2_IRQn); + + tim2OC1.OCMode = TIM_OCMODE_PWM1; + tim2OC1.OCPolarity = TIM_OCPOLARITY_HIGH; + tim2OC1.Pulse = cc1; + tim2OC1.OCNPolarity = TIM_OCNPOLARITY_HIGH; + tim2OC1.OCFastMode = TIM_OCFAST_DISABLE; + HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1); + + tim2OC2.OCMode = TIM_OCMODE_PWM1; + tim2OC2.OCPolarity = TIM_OCPOLARITY_HIGH; + tim2OC2.Pulse = cc2; + tim2OC2.OCNPolarity = TIM_OCNPOLARITY_HIGH; + tim2OC2.OCFastMode = TIM_OCFAST_DISABLE; + tim2OC2.OCIdleState = TIM_OCIDLESTATE_RESET; + tim2OC2.OCNIdleState = TIM_OCNIDLESTATE_RESET; + HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2); + + HAL_TIM_Base_Start(&Tim2Handle); + HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_1); + +} + + +DMA_HandleTypeDef dmaUpdate; +DMA_HandleTypeDef dmaCC1; +DMA_HandleTypeDef dmaCC2; +#define BUFFER_SIZE (sizeof(ws2812bDmaBitBuffer)/sizeof(uint16_t)) + +static void DMA_init(void) +{ + + // TIM2 Update event + __HAL_RCC_DMA1_CLK_ENABLE(); + dmaUpdate.Init.Direction = DMA_MEMORY_TO_PERIPH; + dmaUpdate.Init.PeriphInc = DMA_PINC_DISABLE; + dmaUpdate.Init.MemInc = DMA_MINC_DISABLE; + dmaUpdate.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dmaUpdate.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dmaUpdate.Init.Mode = DMA_CIRCULAR; + dmaUpdate.Init.Priority = DMA_PRIORITY_VERY_HIGH; + dmaUpdate.Instance = DMA1_Channel2; + //dmaUpdate.XferCpltCallback = TransferComplete; + //dmaUpdate.XferErrorCallback = TransferError; + HAL_DMA_Init(&dmaUpdate); + //HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0); + //HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn); + HAL_DMA_Start(&dmaUpdate, (uint32_t)WS2812_IO_High, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE); + + + // TIM2 CC1 event + dmaCC1.Init.Direction = DMA_MEMORY_TO_PERIPH; + dmaCC1.Init.PeriphInc = DMA_PINC_DISABLE; + dmaCC1.Init.MemInc = DMA_MINC_ENABLE; + dmaCC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dmaCC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; + dmaCC1.Init.Mode = DMA_CIRCULAR; + dmaCC1.Init.Priority = DMA_PRIORITY_VERY_HIGH; + dmaCC1.Instance = DMA1_Channel5; + //dmaUpdate.XferCpltCallback = TransferComplete; + //dmaUpdate.XferErrorCallback = TransferError; + //dmaUpdate.XferHalfCpltCallback = TransferHalf; + //HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); + //HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); + HAL_DMA_Init(&dmaCC1); + HAL_DMA_Start(&dmaCC1, (uint32_t)ws2812bDmaBitBuffer, (uint32_t)&WS2812B_PORT->BRR, BUFFER_SIZE); + + + // TIM2 CC2 event + dmaCC2.Init.Direction = DMA_MEMORY_TO_PERIPH; + dmaCC2.Init.PeriphInc = DMA_PINC_DISABLE; + dmaCC2.Init.MemInc = DMA_MINC_DISABLE; + dmaCC2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; + dmaCC2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; + dmaCC2.Init.Mode = DMA_CIRCULAR; + dmaCC2.Init.Priority = DMA_PRIORITY_VERY_HIGH; + dmaCC2.Instance = DMA1_Channel7; + dmaCC2.XferCpltCallback = DMA_TransferCompleteHandler; + dmaCC2.XferHalfCpltCallback = DMA_TransferHalfHandler; + //dmaUpdate.XferErrorCallback = TransferError; + HAL_DMA_Init(&dmaCC2); + HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0); + HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn); + HAL_DMA_Start_IT(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE); + +} + +/* +void DMA1_Channel2_IRQHandler(void) +{ + // Check the interrupt and clear flag + HAL_DMA_IRQHandler(&dmaUpdate); +} + +void DMA1_Channel5_IRQHandler(void) +{ + // Check the interrupt and clear flag + HAL_DMA_IRQHandler(&dmaCC1); +}*/ + +void DMA1_Channel7_IRQHandler(void) +{ + // Check the interrupt and clear flag + HAL_DMA_IRQHandler(&dmaCC2); +} + + + +static void loadNextFramebufferData(WS2812_BufferItem *bItem, uint32_t row) +{ + + uint32_t r = bItem->frameBufferPointer[bItem->frameBufferCounter++]; + uint32_t g = bItem->frameBufferPointer[bItem->frameBufferCounter++]; + uint32_t b = bItem->frameBufferPointer[bItem->frameBufferCounter++]; + + if(bItem->frameBufferCounter == bItem->frameBufferSize) + bItem->frameBufferCounter = 0; + + ws2812b_set_pixel(bItem->channel, row, r, g, b); +} + + +// Transmit the framebuffer +static void WS2812_sendbuf() +{ + // transmission complete flag + ws2812b.transferComplete = 0; + + uint32_t i; + + for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) + { + ws2812b.item[i].frameBufferCounter = 0; + + loadNextFramebufferData(&ws2812b.item[i], 0); // ROW 0 + loadNextFramebufferData(&ws2812b.item[i], 1); // ROW 0 + } + + // clear all DMA flags + __HAL_DMA_CLEAR_FLAG(&dmaUpdate, DMA_FLAG_TC2 | DMA_FLAG_HT2 | DMA_FLAG_TE2); + __HAL_DMA_CLEAR_FLAG(&dmaCC1, DMA_FLAG_TC5 | DMA_FLAG_HT5 | DMA_FLAG_TE5); + __HAL_DMA_CLEAR_FLAG(&dmaCC2, DMA_FLAG_TC7 | DMA_FLAG_HT7 | DMA_FLAG_TE7); + + // configure the number of bytes to be transferred by the DMA controller + dmaUpdate.Instance->CNDTR = BUFFER_SIZE; + dmaCC1.Instance->CNDTR = BUFFER_SIZE; + dmaCC2.Instance->CNDTR = BUFFER_SIZE; + + // clear all TIM2 flags + __HAL_TIM_CLEAR_FLAG(&Tim2Handle, TIM_FLAG_UPDATE | TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4); + + // enable DMA channels + __HAL_DMA_ENABLE(&dmaUpdate); + __HAL_DMA_ENABLE(&dmaCC1); + __HAL_DMA_ENABLE(&dmaCC2); + + // IMPORTANT: enable the TIM2 DMA requests AFTER enabling the DMA channels! + __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_UPDATE); + __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_CC1); + __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_CC2); + + TIM2->CNT = tim_period-1; + + // start TIM2 + __HAL_TIM_ENABLE(&Tim2Handle); +} + + + + + +void DMA_TransferHalfHandler(DMA_HandleTypeDef *DmaHandle) +{ + #if defined(LED4_PORT) + LED4_PORT->BSRR = LED4_PIN; + #endif + + // Is this the last LED? + if(ws2812b.repeatCounter != (WS2812B_NUMBER_OF_LEDS / 2 - 1)) + { + uint32_t i; + + for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) + { + loadNextFramebufferData(&ws2812b.item[i], 0); + } + + } else { + // If this is the last pixel, set the next pixel value to zeros, because + // the DMA would not stop exactly at the last bit. + ws2812b_set_pixel(0, 0, 0, 0, 0); + } + + #if defined(LED4_PORT) + LED4_PORT->BRR = LED4_PIN; + #endif +} + +void DMA_TransferCompleteHandler(DMA_HandleTypeDef *DmaHandle) +{ + #if defined(LED5_PORT) + LED5_PORT->BSRR = LED5_PIN; + #endif + + ws2812b.repeatCounter++; + + if(ws2812b.repeatCounter == WS2812B_NUMBER_OF_LEDS / 2) + { + // Transfer of all LEDs is done, disable DMA but enable tiemr update IRQ to stop the 50us pulse + ws2812b.repeatCounter = 0; + + // Enable TIM2 Update interrupt for 50us Treset signal + __HAL_TIM_ENABLE_IT(&Tim2Handle, TIM_IT_UPDATE); + // Disable DMA + __HAL_DMA_DISABLE(&dmaUpdate); + __HAL_DMA_DISABLE(&dmaCC1); + __HAL_DMA_DISABLE(&dmaCC2); + + // Disable the DMA requests + __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_UPDATE); + __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_CC1); + __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_CC2); + + // Manually set outputs to low to generate 50us reset impulse + WS2812B_PORT->BSRR = WS2812_IO_Low[0]; + } else { + + // Load bitbuffer with next RGB LED values + uint32_t i; + for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) + { + loadNextFramebufferData(&ws2812b.item[i], 1); + } + + } + + #if defined(LED5_PORT) + LED5_PORT->BRR = LED5_PIN; + #endif +} + + +void TIM2_IRQHandler(void) +{ + HAL_TIM_IRQHandler(&Tim2Handle); +} + +// TIM2 Interrupt Handler gets executed on every TIM2 Update if enabled +void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) +{ + // I have to wait 50us to generate Treset signal + if (ws2812b.timerPeriodCounter < (uint8_t)WS2812_RESET_PERIOD) + { + // count the number of timer periods + ws2812b.timerPeriodCounter++; + } + else + { + ws2812b.timerPeriodCounter = 0; + __HAL_TIM_DISABLE(&Tim2Handle); + TIM2->CR1 = 0; // disable timer + + // disable the TIM2 Update + __HAL_TIM_DISABLE_IT(&Tim2Handle, TIM_IT_UPDATE); + // set TransferComplete flag + ws2812b.transferComplete = 1; + } + +} + + + +static void ws2812b_set_pixel(uint8_t row, uint16_t column, uint8_t red, uint8_t green, uint8_t blue) +{ + + // Apply gamma + red = gammaTable[red]; + green = gammaTable[green]; + blue = gammaTable[blue]; + + + uint32_t calcCol = (column*24); + uint32_t invRed = ~red; + uint32_t invGreen = ~green; + uint32_t invBlue = ~blue; + + +#if defined(SETPIX_1) + uint8_t i; + uint32_t calcClearRow = ~(0x01<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<> 7); + bitBand+=16; + + *bitBand = (invGreen >> 6); + bitBand+=16; + + *bitBand = (invGreen >> 5); + bitBand+=16; + + *bitBand = (invGreen >> 4); + bitBand+=16; + + *bitBand = (invGreen >> 3); + bitBand+=16; + + *bitBand = (invGreen >> 2); + bitBand+=16; + + *bitBand = (invGreen >> 1); + bitBand+=16; + + *bitBand = (invGreen >> 0); + bitBand+=16; + + // RED + *bitBand = (invRed >> 7); + bitBand+=16; + + *bitBand = (invRed >> 6); + bitBand+=16; + + *bitBand = (invRed >> 5); + bitBand+=16; + + *bitBand = (invRed >> 4); + bitBand+=16; + + *bitBand = (invRed >> 3); + bitBand+=16; + + *bitBand = (invRed >> 2); + bitBand+=16; + + *bitBand = (invRed >> 1); + bitBand+=16; + + *bitBand = (invRed >> 0); + bitBand+=16; + + // BLUE + *bitBand = (invBlue >> 7); + bitBand+=16; + + *bitBand = (invBlue >> 6); + bitBand+=16; + + *bitBand = (invBlue >> 5); + bitBand+=16; + + *bitBand = (invBlue >> 4); + bitBand+=16; + + *bitBand = (invBlue >> 3); + bitBand+=16; + + *bitBand = (invBlue >> 2); + bitBand+=16; + + *bitBand = (invBlue >> 1); + bitBand+=16; + + *bitBand = (invBlue >> 0); + bitBand+=16; + +#endif +} + + +void ws2812b_init() +{ + ws2812b_gpio_init(); + DMA_init(); + TIM2_init(); + + // Need to start the first transfer + ws2812b.transferComplete = 1; +} + + +void ws2812b_handle() +{ + if(ws2812b.startTransfer) { + ws2812b.startTransfer = 0; + WS2812_sendbuf(); + } + +} \ No newline at end of file diff --git a/drivers/arm/ws2812.h b/drivers/arm/ws2812.h new file mode 100644 index 0000000000..53a1787374 --- /dev/null +++ b/drivers/arm/ws2812.h @@ -0,0 +1,94 @@ +/* + + WS2812B CPU and memory efficient library + + Date: 28.9.2016 + + Author: Martin Hubacek + http://www.martinhubacek.cz + @hubmartin + + Licence: MIT License + +*/ + +#ifndef WS2812B_H_ +#define WS2812B_H_ +#include "ws2812.h" + +// GPIO enable command +#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() +// LED output port +#define WS2812B_PORT GPIOC +// LED output pins +#define WS2812B_PINS (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3) +// How many LEDs are in the series +#define WS2812B_NUMBER_OF_LEDS 60 + +// Number of output LED strips. Each has its own buffer. +#define WS2812_BUFFER_COUNT 2 + +// Choose one of the bit-juggling setpixel implementation +// ******************************************************* +//#define SETPIX_1 // For loop, works everywhere, slow +//#define SETPIX_2 // Bit band in a loop +//#define SETPIX_3 // Like SETPIX_1 but with unrolled loop +#define SETPIX_4 // Fastest copying using bit-banding + + +// DEBUG OUTPUT +// ******************** +#define LED4_PORT GPIOC +#define LED4_PIN GPIO_PIN_10 + +#define LED5_PORT GPIOC +#define LED5_PIN GPIO_PIN_10 + + +// Public functions +// **************** +void ws2812b_init(); +void ws2812b_handle(); + +// Library structures +// ****************** +// This value sets number of periods to generate 50uS Treset signal +#define WS2812_RESET_PERIOD 12 + +typedef struct WS2812_BufferItem { + uint8_t* frameBufferPointer; + uint32_t frameBufferSize; + uint32_t frameBufferCounter; + uint8_t channel; // digital output pin/channel +} WS2812_BufferItem; + + + +typedef struct WS2812_Struct +{ + WS2812_BufferItem item[WS2812_BUFFER_COUNT]; + uint8_t transferComplete; + uint8_t startTransfer; + uint32_t timerPeriodCounter; + uint32_t repeatCounter; +} WS2812_Struct; + +WS2812_Struct ws2812b; + +// Bit band stuff +#define RAM_BASE 0x20000000 +#define RAM_BB_BASE 0x22000000 +#define Var_ResetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2)) = 0) +#define Var_SetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2)) = 1) +#define Var_GetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2))) +#define BITBAND_SRAM(address, bit) ( (__IO uint32_t *) (RAM_BB_BASE + (((uint32_t)address) - RAM_BASE) * 32 + (bit) * 4)) + +#define varSetBit(var,bit) (Var_SetBit_BB((uint32_t)&var,bit)) +#define varResetBit(var,bit) (Var_ResetBit_BB((uint32_t)&var,bit)) +#define varGetBit(var,bit) (Var_GetBit_BB((uint32_t)&var,bit)) + +static void ws2812b_set_pixel(uint8_t row, uint16_t column, uint8_t red, uint8_t green, uint8_t blue); +void DMA_TransferCompleteHandler(DMA_HandleTypeDef *DmaHandle); +void DMA_TransferHalfHandler(DMA_HandleTypeDef *DmaHandle); + +#endif /* WS2812B_H_ */ \ No newline at end of file diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index 36e4c9904c..c8856586dc 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -317,7 +317,7 @@ void audio_init() dacStart(&DACD2, &dac1cfg2); /* - * Starting GPT6 driver, it is used for triggering the DAC. + * Starting GPT6/7 driver, it is used for triggering the DAC. */ START_CHANNEL_1(); START_CHANNEL_2(); @@ -325,12 +325,8 @@ void audio_init() /* * Starting a continuous conversion. */ - dacStartConversion(&DACD1, &dacgrpcfg1, - (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); - dacStartConversion(&DACD2, &dacgrpcfg2, - (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); - // gptStartContinuous(&GPTD6, 2U); - + dacStartConversion(&DACD1, &dacgrpcfg1, (dacsample_t *)dac_buffer, DAC_BUFFER_SIZE); + dacStartConversion(&DACD2, &dacgrpcfg2, (dacsample_t *)dac_buffer_2, DAC_BUFFER_SIZE); audio_initialized = true; @@ -469,6 +465,8 @@ static void gpt_cb8(GPTDriver *gptp) { if (GET_CHANNEL_2_FREQ != (uint16_t)freq_alt) { UPDATE_CHANNEL_2_FREQ(freq_alt); + } else { + RESTART_CHANNEL_2(); } //note_timbre; } @@ -528,6 +526,8 @@ static void gpt_cb8(GPTDriver *gptp) { if (GET_CHANNEL_1_FREQ != (uint16_t)freq) { UPDATE_CHANNEL_1_FREQ(freq); + } else { + RESTART_CHANNEL_1(); } //note_timbre; } @@ -622,6 +622,7 @@ void play_note(float freq, int vol) { if (audio_config.enable && voices < 8) { + // Cancel notes if notes are playing if (playing_notes) stop_all_notes(); From bb71a988c2d45f5d2515fc9186f15a81affd8c0f Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 3 Apr 2018 20:57:11 -0400 Subject: [PATCH 20/59] flesh out dip and encoder support --- keyboards/planck/keymaps/default/config.h | 8 ++++-- keyboards/planck/keymaps/default/keymap.c | 30 ++++++++++++++++++++++- keyboards/planck/planck.h | 20 +++++++-------- keyboards/planck/rev6/matrix.c | 30 ++++++++++++++++------- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/keyboards/planck/keymaps/default/config.h b/keyboards/planck/keymaps/default/config.h index a1635f2bab..8b0abf976a 100644 --- a/keyboards/planck/keymaps/default/config.h +++ b/keyboards/planck/keymaps/default/config.h @@ -25,7 +25,7 @@ /* enable basic MIDI features: - MIDI notes can be sent when in Music mode is on */ - + #define MIDI_BASIC /* enable advanced MIDI features: @@ -39,4 +39,8 @@ /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 2 -#endif \ No newline at end of file + +// Most tactile encoders have detents every 4 stages +#define ENCODER_RESOLUTION 4 + +#endif diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 0bb70ca7b1..40ae7777ee 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -75,7 +75,7 @@ const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT , - KC_SPC, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC, KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT ), /* Dvorak @@ -266,3 +266,31 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { } return true; } + +void encoder_update(bool direction) { + if (direction) { + register_code(KC_PGUP); + unregister_code(KC_PGUP); + } else { + register_code(KC_PGDN); + unregister_code(KC_PGDN); + } +} + +void dip_update(uint8_t index, bool value) { + switch (index) { + case 0: + if (value) { + #ifdef AUDIO_ENABLE + PLAY_SONG(plover_song); + #endif + layer_on(_ADJUST); + } else { + #ifdef AUDIO_ENABLE + PLAY_SONG(plover_gb_song); + #endif + layer_off(_ADJUST); + } + break; + } +} diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h index 626798912b..f0a12d9335 100644 --- a/keyboards/planck/planck.h +++ b/keyboards/planck/planck.h @@ -60,11 +60,11 @@ { k00, k01, k02, k03, k04, k05 }, \ { k10, k11, k12, k13, k14, k15 }, \ { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ + { k30, k31, k32, k39, k3a, k3b }, \ { k06, k07, k08, k09, k0a, k0b }, \ { k16, k17, k18, k19, k1a, k1b }, \ { k26, k27, k28, k29, k2a, k2b }, \ - { k36, k37, k38, k39, k3a, k3b } \ + { k36, k37, k38, k33, k34, k35 } \ } #define LAYOUT_planck_1x2uR( \ @@ -77,11 +77,11 @@ { k00, k01, k02, k03, k04, k05 }, \ { k10, k11, k12, k13, k14, k15 }, \ { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ + { k30, k31, k32, k39, k3a, k3b }, \ { k06, k07, k08, k09, k0a, k0b }, \ { k16, k17, k18, k19, k1a, k1b }, \ { k26, k27, k28, k29, k2a, k2b }, \ - { k36, k37, k38, k39, k3a, k3b } \ + { k36, k37, k38, k33, k34, k35 } \ } #define LAYOUT_planck_1x2uL( \ @@ -94,11 +94,11 @@ { k00, k01, k02, k03, k04, k05 }, \ { k10, k11, k12, k13, k14, k15 }, \ { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ + { k30, k31, k32, k39, k3a, k3b }, \ { k06, k07, k08, k09, k0a, k0b }, \ { k16, k17, k18, k19, k1a, k1b }, \ { k26, k27, k28, k29, k2a, k2b }, \ - { k36, k37, k38, k39, k3a, k3b } \ + { k36, k37, k38, k33, k34, k35 } \ } #define LAYOUT_planck_2x2u( \ @@ -111,11 +111,11 @@ { k00, k01, k02, k03, k04, k05 }, \ { k10, k11, k12, k13, k14, k15 }, \ { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ + { k30, k31, k32, k39, k3a, k3b }, \ { k06, k07, k08, k09, k0a, k0b }, \ { k16, k17, k18, k19, k1a, k1b }, \ { k26, k27, k28, k29, k2a, k2b }, \ - { k36, k37, k38, k39, k3a, k3b } \ + { k36, k37, k38, k33, k34, k35 } \ } #define LAYOUT_planck_grid( \ @@ -128,11 +128,11 @@ { k00, k01, k02, k03, k04, k05 }, \ { k10, k11, k12, k13, k14, k15 }, \ { k20, k21, k22, k23, k24, k25 }, \ - { k30, k31, k32, k33, k34, k35 }, \ + { k30, k31, k32, k39, k3a, k3b }, \ { k06, k07, k08, k09, k0a, k0b }, \ { k16, k17, k18, k19, k1a, k1b }, \ { k26, k27, k28, k29, k2a, k2b }, \ - { k36, k37, k38, k39, k3a, k3b } \ + { k36, k37, k38, k33, k34, k35 } \ } #define KEYMAP LAYOUT_planck_grid diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index 007c42f0a8..cd025ea49e 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -9,6 +9,7 @@ #include "matrix.h" #include "action.h" #include "keycode.h" +#include /* * col: { B11, B10, B2, B1, A7, B0 } @@ -22,7 +23,7 @@ static uint16_t debouncing_time = 0; static uint8_t encoder_state = 0; static int8_t encoder_value = 0; -static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; +static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; static bool dip_switch[4] = {0, 0, 0, 0}; @@ -83,26 +84,37 @@ void matrix_init(void) { matrix_init_quantum(); } +__attribute__ ((weak)) +void dip_update(uint8_t index, bool value) { } + +__attribute__ ((weak)) +void encoder_update(bool direction) { } + +bool last_dip_switch[4] = {0}; + uint8_t matrix_scan(void) { // dip switch dip_switch[0] = palReadPad(GPIOB, 14); dip_switch[1] = palReadPad(GPIOA, 15); dip_switch[2] = palReadPad(GPIOA, 10); dip_switch[3] = palReadPad(GPIOB, 9); + for (uint8_t i = 0; i < 4; i++) { + if (last_dip_switch[i] ^ dip_switch[i]) + dip_update(i, dip_switch[i]); + } + memcpy(last_dip_switch, dip_switch, sizeof(&dip_switch)); // encoder on B12 and B13 encoder_state <<= 2; encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); encoder_value += encoder_LUT[encoder_state & 0xF]; - if (encoder_value >= 4) { - register_code(KC_MS_WH_UP); - unregister_code(KC_MS_WH_UP); + if (encoder_value >= ENCODER_RESOLUTION) { + encoder_update(1); } - if (encoder_value <= -4) { - register_code(KC_MS_WH_DOWN); - unregister_code(KC_MS_WH_DOWN); + if (encoder_value <= -ENCODER_RESOLUTION) { + encoder_update(0); } - encoder_value %= 4; + encoder_value %= ENCODER_RESOLUTION; // actual matrix for (int col = 0; col < MATRIX_COLS; col++) { @@ -186,4 +198,4 @@ void matrix_print(void) { } printf("\n"); } -} \ No newline at end of file +} From 25642c884018fd09313d4f78773ccd587c857f9d Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 3 Apr 2018 21:07:18 -0400 Subject: [PATCH 21/59] adds default encoder res --- keyboards/planck/rev6/matrix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index cd025ea49e..62d34dd24a 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -92,6 +92,10 @@ void encoder_update(bool direction) { } bool last_dip_switch[4] = {0}; +#ifndef ENCODER_RESOLUTION + #define ENCODER_RESOLUTION 4 +#undef ENCODER_RESOLUTION + uint8_t matrix_scan(void) { // dip switch dip_switch[0] = palReadPad(GPIOB, 14); From fe72bfa07022db86a0c336d61c63c2660073a61f Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 3 Apr 2018 21:10:57 -0400 Subject: [PATCH 22/59] adds default encoder res --- keyboards/planck/rev6/matrix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index 62d34dd24a..36d9259eeb 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -94,7 +94,7 @@ bool last_dip_switch[4] = {0}; #ifndef ENCODER_RESOLUTION #define ENCODER_RESOLUTION 4 -#undef ENCODER_RESOLUTION +#endif uint8_t matrix_scan(void) { // dip switch From edb4460e64fdadf2adaeee703f77728b237ebadd Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 4 Apr 2018 02:29:52 -0400 Subject: [PATCH 23/59] start muse implementation --- quantum/audio/muse.c | 110 +++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 quantum/audio/muse.c diff --git a/quantum/audio/muse.c b/quantum/audio/muse.c new file mode 100644 index 0000000000..88dc31af8d --- /dev/null +++ b/quantum/audio/muse.c @@ -0,0 +1,110 @@ + +enum { + MUSE_OFF, + MUSE_ON, + MUSE_C_1_2, + MUSE_C1, + MUSE_C2, + MUSE_C4, + MUSE_C8, + MUSE_C3, + MUSE_C6, + MUSE_B1, + MUSE_B2, + MUSE_B3, + MUSE_B4, + MUSE_B5, + MUSE_B6, + MUSE_B7, + MUSE_B8, + MUSE_B9, + MUSE_B10, + MUSE_B11, + MUSE_B12, + MUSE_B13, + MUSE_B14, + MUSE_B15, + MUSE_B16, + MUSE_B17, + MUSE_B18, + MUSE_B19, + MUSE_B20, + MUSE_B21, + MUSE_B22, + MUSE_B23, + MUSE_B24, + MUSE_B25, + MUSE_B26, + MUSE_B27, + MUSE_B28, + MUSE_B29, + MUSE_B30, + MUSE_B31 +}; + +bool number_of_ones_to_bool[16] = { + 1, 0, 0, 1, 0, 1, 1, 0, + 0, 1, 1, 0, 1, 0, 0, 1 +}; + +uint8_t muse_interval[4] = {0}; +uint8_t muse_theme[4] = {0}; + +bool timer_1bit = 0; +uint8_t timer_2bit = 0; +uint8_t timer_2bit_counter = 0; +uint8_t timer_4bit = 0; +uint32_t timer_31bit = 0; + +bool bit_for_value(uint8_t value) { + switch (value) { + case MUSE_OFF: + return 0; + case MUSE_ON: + return 1; + case MUSE_C_1_2: + return timer_1bit; + case MUSE_C1: + return (timer_4bit & 1); + case MUSE_C2: + return (timer_4bit & 2); + case MUSE_C4: + return (timer_4bit & 4); + case MUSE_C8: + return (timer_4bit & 8); + case MUSE_C3: + return (timer_2bit & 1); + case MUSE_C6: + return (timer_2bit & 2); + default: + return timer_31bit & (1UL << (value - MUSE_B1)); + } +} + +uint8_t clock_pulse() { + + bool top = number_of_ones_to_bool[ + bit_for_value(muse_theme[0]) + + bit_for_value(muse_theme[1]) << 1 + + bit_for_value(muse_theme[2]) << 2 + + bit_for_value(muse_theme[3]) << 3 + ]; + + if (timer_1bit == 0) { + if (timer_2bit_counter == 0) { + timer_2bit = (timer_2bit + 1) % 4; + timer_2bit_counter = (timer_2bit_counter + 1) % 3; + } + timer_4bit = (timer_4bit + 1) % 16; + timer_31bit = (timer_31bit << 1) + top; + } + + timer_1bit = (timer_1bit + 1) % 2; + + return + bit_for_value(muse_interval[0]) + + bit_for_value(muse_interval[1]) << 1 + + bit_for_value(muse_interval[2]) << 2 + + bit_for_value(muse_interval[3]) << 3; + +} From e0e5efbead6ea125f3223508886dd443be3c39a9 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 4 Apr 2018 16:49:39 -0400 Subject: [PATCH 24/59] muse working with encoder as control --- keyboards/planck/keymaps/default/keymap.c | 69 ++++++++++++++-- keyboards/planck/keymaps/default/rules.mk | 1 + keyboards/planck/rev6/matrix.c | 18 ++--- quantum/audio/audio_arm.c | 97 ++++++++++++++++++++++- quantum/audio/muse.c | 59 +++++++------- quantum/audio/muse.h | 9 +++ quantum/process_keycode/process_audio.c | 4 +- quantum/process_keycode/process_audio.h | 4 +- 8 files changed, 210 insertions(+), 51 deletions(-) create mode 100644 quantum/audio/muse.h diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 40ae7777ee..c1a7e0fe15 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -16,6 +16,7 @@ #include "planck.h" #include "action_layer.h" +#include "muse.h" extern keymap_config_t keymap_config; @@ -267,20 +268,42 @@ bool process_record_user(uint16_t keycode, keyrecord_t *record) { return true; } -void encoder_update(bool direction) { - if (direction) { - register_code(KC_PGUP); - unregister_code(KC_PGUP); +bool muse_mode = false; +uint8_t last_muse_note = 0; +uint16_t muse_counter = 0; +uint8_t muse_offset = 70; +uint16_t muse_tempo = 50; + +void encoder_update(bool clockwise) { + if (muse_mode) { + if (IS_LAYER_ON(_RAISE)) { + if (clockwise) { + muse_offset++; + } else { + muse_offset--; + } + } else { + if (clockwise) { + muse_tempo+=1; + } else { + muse_tempo-=1; + } + } } else { - register_code(KC_PGDN); - unregister_code(KC_PGDN); + if (clockwise) { + register_code(KC_PGUP); + unregister_code(KC_PGUP); + } else { + register_code(KC_PGDN); + unregister_code(KC_PGDN); + } } } -void dip_update(uint8_t index, bool value) { +void dip_update(uint8_t index, bool active) { switch (index) { case 0: - if (value) { + if (active) { #ifdef AUDIO_ENABLE PLAY_SONG(plover_song); #endif @@ -292,5 +315,35 @@ void dip_update(uint8_t index, bool value) { layer_off(_ADJUST); } break; + case 1: + if (active) { + muse_mode = true; + } else { + muse_mode = false; + stop_all_notes(); + } + } +} + +void matrix_init_user(void) { + palSetPadMode(GPIOB, 5, PAL_MODE_OUTPUT_PUSHPULL); +} + +void matrix_scan_user(void) { + if (muse_mode) { + if (muse_counter == 0) { + uint8_t muse_note = muse_offset + SCALE[muse_clock_pulse()]; + if (muse_note != last_muse_note) { + stop_note(compute_freq_for_midi_note(last_muse_note)); + play_note(compute_freq_for_midi_note(muse_note), 0xF); + last_muse_note = muse_note; + } + } + if (muse_counter > (muse_tempo / 2)) { + palSetPad(GPIOB, 5); + } else { + palClearPad(GPIOB, 5); + } + muse_counter = (muse_counter + 1) % muse_tempo; } } diff --git a/keyboards/planck/keymaps/default/rules.mk b/keyboards/planck/keymaps/default/rules.mk index e69de29bb2..dcf16bef39 100644 --- a/keyboards/planck/keymaps/default/rules.mk +++ b/keyboards/planck/keymaps/default/rules.mk @@ -0,0 +1 @@ +SRC += muse.c diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index 36d9259eeb..e4ebe48acc 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -85,10 +85,10 @@ void matrix_init(void) { } __attribute__ ((weak)) -void dip_update(uint8_t index, bool value) { } +void dip_update(uint8_t index, bool active) { } __attribute__ ((weak)) -void encoder_update(bool direction) { } +void encoder_update(bool clockwise) { } bool last_dip_switch[4] = {0}; @@ -98,10 +98,10 @@ bool last_dip_switch[4] = {0}; uint8_t matrix_scan(void) { // dip switch - dip_switch[0] = palReadPad(GPIOB, 14); - dip_switch[1] = palReadPad(GPIOA, 15); - dip_switch[2] = palReadPad(GPIOA, 10); - dip_switch[3] = palReadPad(GPIOB, 9); + dip_switch[0] = !palReadPad(GPIOB, 14); + dip_switch[1] = !palReadPad(GPIOA, 15); + dip_switch[2] = !palReadPad(GPIOA, 10); + dip_switch[3] = !palReadPad(GPIOB, 9); for (uint8_t i = 0; i < 4; i++) { if (last_dip_switch[i] ^ dip_switch[i]) dip_update(i, dip_switch[i]); @@ -113,11 +113,11 @@ uint8_t matrix_scan(void) { encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); encoder_value += encoder_LUT[encoder_state & 0xF]; if (encoder_value >= ENCODER_RESOLUTION) { - encoder_update(1); - } - if (encoder_value <= -ENCODER_RESOLUTION) { encoder_update(0); } + if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + encoder_update(1); + } encoder_value %= ENCODER_RESOLUTION; // actual matrix diff --git a/quantum/audio/audio_arm.c b/quantum/audio/audio_arm.c index c8856586dc..d38184f323 100644 --- a/quantum/audio/audio_arm.c +++ b/quantum/audio/audio_arm.c @@ -79,7 +79,7 @@ float startup_song[][2] = STARTUP_SONG; static void gpt_cb8(GPTDriver *gptp); -#define DAC_BUFFER_SIZE 360 +#define DAC_BUFFER_SIZE 720 #define START_CHANNEL_1() gptStart(&GPTD6, &gpt6cfg1); \ gptStartContinuous(&GPTD6, 2U) @@ -167,6 +167,39 @@ GPTConfig gpt8cfg1 = { // 1622, 1657, 1692, 1727, 1763, 1798, 1834, 1869, 1905, 1940, 1976, 2012 // }; +// static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { +// 12, 8, 5, 3, 2, 1, 0, 1, 2, 3, 5, 8, +// 12, 16, 20, 26, 32, 38, 45, 53, 61, 70, 80, 90, +// 101, 112, 124, 136, 150, 163, 177, 192, 208, 224, 240, 257, +// 275, 293, 312, 331, 350, 371, 391, 413, 434, 457, 479, 503, +// 526, 550, 575, 600, 626, 651, 678, 705, 732, 759, 787, 816, +// 844, 873, 903, 933, 963, 993, 1024, 1055, 1086, 1118, 1150, 1182, +// 1215, 1248, 1281, 1314, 1347, 1381, 1415, 1449, 1483, 1518, 1552, 1587, +// 1622, 1657, 1692, 1727, 1763, 1798, 1834, 1869, 1905, 1940, 1976, 2012, +// 2047, 2082, 2118, 2154, 2189, 2225, 2260, 2296, 2331, 2367, 2402, 2437, +// 2472, 2507, 2542, 2576, 2611, 2645, 2679, 2713, 2747, 2780, 2813, 2846, +// 2879, 2912, 2944, 2976, 3008, 3039, 3070, 3101, 3131, 3161, 3191, 3221, +// 3250, 3278, 3307, 3335, 3362, 3389, 3416, 3443, 3468, 3494, 3519, 3544, +// 3568, 3591, 3615, 3637, 3660, 3681, 3703, 3723, 3744, 3763, 3782, 3801, +// 3819, 3837, 3854, 3870, 3886, 3902, 3917, 3931, 3944, 3958, 3970, 3982, +// 3993, 4004, 4014, 4024, 4033, 4041, 4049, 4056, 4062, 4068, 4074, 4078, +// 4082, 4086, 4089, 4091, 4092, 4093, 4094, 4093, 4092, 4091, 4089, 4086, +// 4082, 4078, 4074, 4068, 4062, 4056, 4049, 4041, 4033, 4024, 4014, 4004, +// 3993, 3982, 3970, 3958, 3944, 3931, 3917, 3902, 3886, 3870, 3854, 3837, +// 3819, 3801, 3782, 3763, 3744, 3723, 3703, 3681, 3660, 3637, 3615, 3591, +// 3568, 3544, 3519, 3494, 3468, 3443, 3416, 3389, 3362, 3335, 3307, 3278, +// 3250, 3221, 3191, 3161, 3131, 3101, 3070, 3039, 3008, 2976, 2944, 2912, +// 2879, 2846, 2813, 2780, 2747, 2713, 2679, 2645, 2611, 2576, 2542, 2507, +// 2472, 2437, 2402, 2367, 2331, 2296, 2260, 2225, 2189, 2154, 2118, 2082, +// 2047, 2012, 1976, 1940, 1905, 1869, 1834, 1798, 1763, 1727, 1692, 1657, +// 1622, 1587, 1552, 1518, 1483, 1449, 1415, 1381, 1347, 1314, 1281, 1248, +// 1215, 1182, 1150, 1118, 1086, 1055, 1024, 993, 963, 933, 903, 873, +// 844, 816, 787, 759, 732, 705, 678, 651, 626, 600, 575, 550, +// 526, 503, 479, 457, 434, 413, 391, 371, 350, 331, 312, 293, +// 275, 257, 240, 224, 208, 192, 177, 163, 150, 136, 124, 112, +// 101, 90, 80, 70, 61, 53, 45, 38, 32, 26, 20, 16 +// }; + // squarewave static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, @@ -184,7 +217,37 @@ static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -204,6 +267,22 @@ static const dacsample_t dac_buffer[DAC_BUFFER_SIZE] = { // squarewave static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { + + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, @@ -233,8 +312,22 @@ static const dacsample_t dac_buffer_2[DAC_BUFFER_SIZE] = { 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, + 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047, 2047 - }; /* diff --git a/quantum/audio/muse.c b/quantum/audio/muse.c index 88dc31af8d..f3cb592d81 100644 --- a/quantum/audio/muse.c +++ b/quantum/audio/muse.c @@ -1,3 +1,4 @@ +#include "muse.h" enum { MUSE_OFF, @@ -47,14 +48,14 @@ bool number_of_ones_to_bool[16] = { 0, 1, 1, 0, 1, 0, 0, 1 }; -uint8_t muse_interval[4] = {0}; -uint8_t muse_theme[4] = {0}; +uint8_t muse_interval[4] = {MUSE_B7, MUSE_B19, MUSE_B3, MUSE_B28}; +uint8_t muse_theme[4] = {MUSE_B8, MUSE_B23, MUSE_B18, MUSE_B17}; -bool timer_1bit = 0; -uint8_t timer_2bit = 0; -uint8_t timer_2bit_counter = 0; -uint8_t timer_4bit = 0; -uint32_t timer_31bit = 0; +bool muse_timer_1bit = 0; +uint8_t muse_timer_2bit = 0; +uint8_t muse_timer_2bit_counter = 0; +uint8_t muse_timer_4bit = 0; +uint32_t muse_timer_31bit = 0; bool bit_for_value(uint8_t value) { switch (value) { @@ -63,48 +64,48 @@ bool bit_for_value(uint8_t value) { case MUSE_ON: return 1; case MUSE_C_1_2: - return timer_1bit; + return muse_timer_1bit; case MUSE_C1: - return (timer_4bit & 1); + return (muse_timer_4bit & 1); case MUSE_C2: - return (timer_4bit & 2); + return (muse_timer_4bit & 2); case MUSE_C4: - return (timer_4bit & 4); + return (muse_timer_4bit & 4); case MUSE_C8: - return (timer_4bit & 8); + return (muse_timer_4bit & 8); case MUSE_C3: - return (timer_2bit & 1); + return (muse_timer_2bit & 1); case MUSE_C6: - return (timer_2bit & 2); + return (muse_timer_2bit & 2); default: - return timer_31bit & (1UL << (value - MUSE_B1)); + return muse_timer_31bit & (1UL << (value - MUSE_B1)); } } -uint8_t clock_pulse() { +uint8_t muse_clock_pulse(void) { bool top = number_of_ones_to_bool[ bit_for_value(muse_theme[0]) + - bit_for_value(muse_theme[1]) << 1 + - bit_for_value(muse_theme[2]) << 2 + - bit_for_value(muse_theme[3]) << 3 + (bit_for_value(muse_theme[1]) << 1) + + (bit_for_value(muse_theme[2]) << 2) + + (bit_for_value(muse_theme[3]) << 3) ]; - if (timer_1bit == 0) { - if (timer_2bit_counter == 0) { - timer_2bit = (timer_2bit + 1) % 4; - timer_2bit_counter = (timer_2bit_counter + 1) % 3; + if (muse_timer_1bit == 0) { + if (muse_timer_2bit_counter == 0) { + muse_timer_2bit = (muse_timer_2bit + 1) % 4; } - timer_4bit = (timer_4bit + 1) % 16; - timer_31bit = (timer_31bit << 1) + top; + muse_timer_2bit_counter = (muse_timer_2bit_counter + 1) % 3; + muse_timer_4bit = (muse_timer_4bit + 1) % 16; + muse_timer_31bit = (muse_timer_31bit << 1) + top; } - timer_1bit = (timer_1bit + 1) % 2; + muse_timer_1bit = (muse_timer_1bit + 1) % 2; return bit_for_value(muse_interval[0]) + - bit_for_value(muse_interval[1]) << 1 + - bit_for_value(muse_interval[2]) << 2 + - bit_for_value(muse_interval[3]) << 3; + (bit_for_value(muse_interval[1]) << 1) + + (bit_for_value(muse_interval[2]) << 2) + + (bit_for_value(muse_interval[3]) << 3); } diff --git a/quantum/audio/muse.h b/quantum/audio/muse.h new file mode 100644 index 0000000000..6f382a7fee --- /dev/null +++ b/quantum/audio/muse.h @@ -0,0 +1,9 @@ +#ifndef MUSE_H +#define MUSE_H + +#include "quantum.h" +#include "process_audio.h" + +uint8_t muse_clock_pulse(void); + +#endif diff --git a/quantum/process_keycode/process_audio.c b/quantum/process_keycode/process_audio.c index 32057ae8dc..0a25aa5354 100644 --- a/quantum/process_keycode/process_audio.c +++ b/quantum/process_keycode/process_audio.c @@ -10,7 +10,7 @@ float voice_change_song[][2] = VOICE_CHANGE_SONG; #define PITCH_STANDARD_A 440.0f #endif -static float compute_freq_for_midi_note(uint8_t note) +float compute_freq_for_midi_note(uint8_t note) { // https://en.wikipedia.org/wiki/MIDI_tuning_standard return pow(2.0, (note - 69) / 12.0) * PITCH_STANDARD_A; @@ -65,4 +65,4 @@ void process_audio_all_notes_off(void) { } __attribute__ ((weak)) -void audio_on_user() {} \ No newline at end of file +void audio_on_user() {} diff --git a/quantum/process_keycode/process_audio.h b/quantum/process_keycode/process_audio.h index 7ac15b7330..3a84c3d869 100644 --- a/quantum/process_keycode/process_audio.h +++ b/quantum/process_keycode/process_audio.h @@ -1,6 +1,8 @@ #ifndef PROCESS_AUDIO_H #define PROCESS_AUDIO_H +float compute_freq_for_midi_note(uint8_t note); + bool process_audio(uint16_t keycode, keyrecord_t *record); void process_audio_noteon(uint8_t note); void process_audio_noteoff(uint8_t note); @@ -8,4 +10,4 @@ void process_audio_all_notes_off(void); void audio_on_user(void); -#endif \ No newline at end of file +#endif From df371458b3979ec3439ba1ea7a098506a11df906 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 6 Apr 2018 12:36:20 -0400 Subject: [PATCH 25/59] flip direction --- keyboards/planck/keymaps/default/keymap.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index c1a7e0fe15..77f847f4c0 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -291,11 +291,11 @@ void encoder_update(bool clockwise) { } } else { if (clockwise) { - register_code(KC_PGUP); - unregister_code(KC_PGUP); - } else { register_code(KC_PGDN); unregister_code(KC_PGDN); + } else { + register_code(KC_PGUP); + unregister_code(KC_PGUP); } } } From 676080372c8218f7f6c23edd35dd8c2f51884d51 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 24 Apr 2018 11:58:36 -0400 Subject: [PATCH 26/59] try mouse wheel again --- keyboards/planck/keymaps/default/keymap.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 77f847f4c0..b523c184ed 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -291,11 +291,11 @@ void encoder_update(bool clockwise) { } } else { if (clockwise) { - register_code(KC_PGDN); - unregister_code(KC_PGDN); + register_code(KC_MS_WH_DOWN); + unregister_code(KC_MS_WH_DOWN); } else { - register_code(KC_PGUP); - unregister_code(KC_PGUP); + register_code(KC_MS_WH_UP); + unregister_code(KC_MS_WH_UP); } } } From 82146ecfc0080a3add32bf16268383a43f93cc20 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 10 May 2018 15:54:33 -0400 Subject: [PATCH 27/59] dont break other revs --- keyboards/planck/config.h | 2 - keyboards/planck/keymaps/default/keymap.c | 5 -- quantum/config_common.h | 102 +++++++++++----------- 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h index 097bacd715..452a99d746 100644 --- a/keyboards/planck/config.h +++ b/keyboards/planck/config.h @@ -18,9 +18,7 @@ along with this program. If not, see . #ifndef CONFIG_H #define CONFIG_H -#ifdef __AVR__ #include "config_common.h" -#endif /* USB Device descriptor parameter */ #define VENDOR_ID 0xFEED diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index e6ab69d43e..81bd9d7b7d 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -324,11 +324,6 @@ void matrix_scan_user(void) { last_muse_note = muse_note; } } - if (muse_counter > (muse_tempo / 2)) { - palSetPad(GPIOB, 5); - } else { - palClearPad(GPIOB, 5); - } muse_counter = (muse_counter + 1) % muse_tempo; } } diff --git a/quantum/config_common.h b/quantum/config_common.h index 4c6a702af4..f6f51b367d 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -22,56 +22,58 @@ #define ROW2COL 1 #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ -/* I/O pins */ -#ifndef F0 - #define B0 0x30 - #define B1 0x31 - #define B2 0x32 - #define B3 0x33 - #define B4 0x34 - #define B5 0x35 - #define B6 0x36 - #define B7 0x37 - #define C0 0x60 - #define C1 0x61 - #define C2 0x62 - #define C3 0x63 - #define C4 0x64 - #define C5 0x65 - #define C6 0x66 - #define C7 0x67 - #define D0 0x90 - #define D1 0x91 - #define D2 0x92 - #define D3 0x93 - #define D4 0x94 - #define D5 0x95 - #define D6 0x96 - #define D7 0x97 - #define E0 0xC0 - #define E1 0xC1 - #define E2 0xC2 - #define E3 0xC3 - #define E4 0xC4 - #define E5 0xC5 - #define E6 0xC6 - #define E7 0xC7 - #define F0 0xF0 - #define F1 0xF1 - #define F2 0xF2 - #define F3 0xF3 - #define F4 0xF4 - #define F5 0xF5 - #define F6 0xF6 - #define F7 0xF7 - #define A0 0x00 - #define A1 0x01 - #define A2 0x02 - #define A3 0x03 - #define A4 0x04 - #define A5 0x05 - #define A6 0x06 - #define A7 0x07 +#ifdef __AVR__ + /* I/O pins */ + #ifndef F0 + #define B0 0x30 + #define B1 0x31 + #define B2 0x32 + #define B3 0x33 + #define B4 0x34 + #define B5 0x35 + #define B6 0x36 + #define B7 0x37 + #define C0 0x60 + #define C1 0x61 + #define C2 0x62 + #define C3 0x63 + #define C4 0x64 + #define C5 0x65 + #define C6 0x66 + #define C7 0x67 + #define D0 0x90 + #define D1 0x91 + #define D2 0x92 + #define D3 0x93 + #define D4 0x94 + #define D5 0x95 + #define D6 0x96 + #define D7 0x97 + #define E0 0xC0 + #define E1 0xC1 + #define E2 0xC2 + #define E3 0xC3 + #define E4 0xC4 + #define E5 0xC5 + #define E6 0xC6 + #define E7 0xC7 + #define F0 0xF0 + #define F1 0xF1 + #define F2 0xF2 + #define F3 0xF3 + #define F4 0xF4 + #define F5 0xF5 + #define F6 0xF6 + #define F7 0xF7 + #define A0 0x00 + #define A1 0x01 + #define A2 0x02 + #define A3 0x03 + #define A4 0x04 + #define A5 0x05 + #define A6 0x06 + #define A7 0x07 + #endif #endif /* USART configuration */ From 1cb72a9c59c8b424e949f52308c48aa83f3ce43c Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 10 May 2018 16:17:50 -0400 Subject: [PATCH 28/59] dont break other revs --- keyboards/planck/keymaps/default/keymap.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 81bd9d7b7d..dc431983e3 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -310,10 +310,6 @@ void dip_update(uint8_t index, bool active) { } } -void matrix_init_user(void) { - palSetPadMode(GPIOB, 5, PAL_MODE_OUTPUT_PUSHPULL); -} - void matrix_scan_user(void) { if (muse_mode) { if (muse_counter == 0) { From 9fccfc8dd5a21923ada3b2539a9eb30f8a4d1d9c Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 15 May 2018 11:36:19 -0400 Subject: [PATCH 29/59] conditional autio --- keyboards/planck/keymaps/default/keymap.c | 24 +++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index dc431983e3..545ca42299 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -305,23 +305,27 @@ void dip_update(uint8_t index, bool active) { muse_mode = true; } else { muse_mode = false; - stop_all_notes(); + #ifdef AUDIO_ENABLE + stop_all_notes(); + #endif } } } void matrix_scan_user(void) { - if (muse_mode) { - if (muse_counter == 0) { - uint8_t muse_note = muse_offset + SCALE[muse_clock_pulse()]; - if (muse_note != last_muse_note) { - stop_note(compute_freq_for_midi_note(last_muse_note)); - play_note(compute_freq_for_midi_note(muse_note), 0xF); - last_muse_note = muse_note; + #ifdef AUDIO_ENABLE + if (muse_mode) { + if (muse_counter == 0) { + uint8_t muse_note = muse_offset + SCALE[muse_clock_pulse()]; + if (muse_note != last_muse_note) { + stop_note(compute_freq_for_midi_note(last_muse_note)); + play_note(compute_freq_for_midi_note(muse_note), 0xF); + last_muse_note = muse_note; + } } + muse_counter = (muse_counter + 1) % muse_tempo; } - muse_counter = (muse_counter + 1) % muse_tempo; - } + #endif } bool music_mask_user(uint16_t keycode) { From 7c19e9fa04ac467cdb7b58e9ebb45cc34ba88423 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 18 May 2018 01:32:24 -0400 Subject: [PATCH 30/59] pwm ws driver (not working) --- drivers/arm/ws2812.c | 773 ++++++++++---------------------- drivers/arm/ws2812.h | 168 +++---- keyboards/planck/config.h | 2 + keyboards/planck/rev6/config.h | 5 + keyboards/planck/rev6/halconf.h | 2 +- keyboards/planck/rev6/mcuconf.h | 2 +- keyboards/planck/rev6/rev6.c | 4 + keyboards/planck/rev6/rules.mk | 1 + quantum/rgblight.c | 20 +- quantum/rgblight_types.h | 4 +- tmk_core/chibios.mk | 2 + 11 files changed, 352 insertions(+), 631 deletions(-) diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c index e39c2554e5..bab52e7531 100644 --- a/drivers/arm/ws2812.c +++ b/drivers/arm/ws2812.c @@ -1,556 +1,245 @@ -/* +/** + * @file ws2812.c + * @author Austin Glaser + * @brief WS2812 LED driver + * + * Copyright (C) 2016 Austin Glaser + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + * + * @todo Put in names and descriptions of variables which need to be defined to use this file + * + * @addtogroup WS2812 + * @{ + */ - WS2812B CPU and memory efficient library +/* --- PRIVATE DEPENDENCIES ------------------------------------------------- */ - Date: 28.9.2016 - - Author: Martin Hubacek - http://www.martinhubacek.cz - @hubmartin - - Licence: MIT License - -*/ - -#include - -#include "stm32f3xx_hal.h" +// This Driver #include "ws2812.h" -extern WS2812_Struct ws2812b; +// Standard +#include -// Define source arrays for my DMAs -uint32_t WS2812_IO_High[] = { WS2812B_PINS }; -uint32_t WS2812_IO_Low[] = {WS2812B_PINS << 16}; +// ChibiOS +#include "ch.h" +#include "hal.h" -// WS2812 framebuffer - buffer for 2 LEDs - two times 24 bits -uint16_t ws2812bDmaBitBuffer[24 * 2]; +// Application +#include "board.h" +#include "util.h" -// Gamma correction table -const uint8_t gammaTable[] = { - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 2, 2, - 2, 3, 3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 4, 5, 5, 5, - 5, 6, 6, 6, 6, 7, 7, 7, 7, 8, 8, 8, 9, 9, 9, 10, - 10, 10, 11, 11, 11, 12, 12, 13, 13, 13, 14, 14, 15, 15, 16, 16, - 17, 17, 18, 18, 19, 19, 20, 20, 21, 21, 22, 22, 23, 24, 24, 25, - 25, 26, 27, 27, 28, 29, 29, 30, 31, 32, 32, 33, 34, 35, 35, 36, - 37, 38, 39, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 50, - 51, 52, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 66, 67, 68, - 69, 70, 72, 73, 74, 75, 77, 78, 79, 81, 82, 83, 85, 86, 87, 89, - 90, 92, 93, 95, 96, 98, 99,101,102,104,105,107,109,110,112,114, - 115,117,119,120,122,124,126,127,129,131,133,135,137,138,140,142, - 144,146,148,150,152,154,156,158,160,162,164,167,169,171,173,175, - 177,180,182,184,186,189,191,193,196,198,200,203,205,208,210,213, - 215,218,220,223,225,228,231,233,236,239,241,244,247,249,252,255 }; - -static void ws2812b_gpio_init(void) -{ - // WS2812B outputs - WS2812B_GPIO_CLK_ENABLE(); - GPIO_InitTypeDef GPIO_InitStruct; - GPIO_InitStruct.Pin = WS2812B_PINS; - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; - HAL_GPIO_Init(WS2812B_PORT, &GPIO_InitStruct); - - // Enable output pins for debuging to see DMA Full and Half transfer interrupts - #if defined(LED4_PORT) && defined(LED5_PORT) - GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; - GPIO_InitStruct.Pull = GPIO_NOPULL; - GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_HIGH; - - GPIO_InitStruct.Pin = LED4_PIN; - HAL_GPIO_Init(LED4_PORT, &GPIO_InitStruct); - GPIO_InitStruct.Pin = LED5_PIN; - HAL_GPIO_Init(LED5_PORT, &GPIO_InitStruct); - #endif -} - -TIM_HandleTypeDef Tim2Handle; -TIM_OC_InitTypeDef tim2OC1; -TIM_OC_InitTypeDef tim2OC2; - -uint32_t tim_period; -static void TIM2_init(void) -{ - // TIM2 Periph clock enable - __HAL_RCC_TIM2_CLK_ENABLE(); - - // This computation of pulse length should work ok, - // at some slower core speeds it needs some tuning. - tim_period = SystemCoreClock / 800000; // 0,125us period (10 times lower the 1,25us period to have fixed math below) - uint32_t cc1 = (10 * tim_period) / 36; - uint32_t cc2 = (10 * tim_period) / 15; - - Tim2Handle.Instance = TIM2; - - Tim2Handle.Init.Period = tim_period; - Tim2Handle.Init.RepetitionCounter = 0; - Tim2Handle.Init.Prescaler = 0; - Tim2Handle.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1; - Tim2Handle.Init.CounterMode = TIM_COUNTERMODE_UP; - HAL_TIM_PWM_Init(&Tim2Handle); - - HAL_NVIC_SetPriority(TIM2_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(TIM2_IRQn); - - tim2OC1.OCMode = TIM_OCMODE_PWM1; - tim2OC1.OCPolarity = TIM_OCPOLARITY_HIGH; - tim2OC1.Pulse = cc1; - tim2OC1.OCNPolarity = TIM_OCNPOLARITY_HIGH; - tim2OC1.OCFastMode = TIM_OCFAST_DISABLE; - HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC1, TIM_CHANNEL_1); - - tim2OC2.OCMode = TIM_OCMODE_PWM1; - tim2OC2.OCPolarity = TIM_OCPOLARITY_HIGH; - tim2OC2.Pulse = cc2; - tim2OC2.OCNPolarity = TIM_OCNPOLARITY_HIGH; - tim2OC2.OCFastMode = TIM_OCFAST_DISABLE; - tim2OC2.OCIdleState = TIM_OCIDLESTATE_RESET; - tim2OC2.OCNIdleState = TIM_OCNIDLESTATE_RESET; - HAL_TIM_PWM_ConfigChannel(&Tim2Handle, &tim2OC2, TIM_CHANNEL_2); - - HAL_TIM_Base_Start(&Tim2Handle); - HAL_TIM_PWM_Start(&Tim2Handle, TIM_CHANNEL_1); - -} - - -DMA_HandleTypeDef dmaUpdate; -DMA_HandleTypeDef dmaCC1; -DMA_HandleTypeDef dmaCC2; -#define BUFFER_SIZE (sizeof(ws2812bDmaBitBuffer)/sizeof(uint16_t)) - -static void DMA_init(void) -{ - - // TIM2 Update event - __HAL_RCC_DMA1_CLK_ENABLE(); - dmaUpdate.Init.Direction = DMA_MEMORY_TO_PERIPH; - dmaUpdate.Init.PeriphInc = DMA_PINC_DISABLE; - dmaUpdate.Init.MemInc = DMA_MINC_DISABLE; - dmaUpdate.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dmaUpdate.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dmaUpdate.Init.Mode = DMA_CIRCULAR; - dmaUpdate.Init.Priority = DMA_PRIORITY_VERY_HIGH; - dmaUpdate.Instance = DMA1_Channel2; - //dmaUpdate.XferCpltCallback = TransferComplete; - //dmaUpdate.XferErrorCallback = TransferError; - HAL_DMA_Init(&dmaUpdate); - //HAL_NVIC_SetPriority(DMA1_Channel2_IRQn, 0, 0); - //HAL_NVIC_EnableIRQ(DMA1_Channel2_IRQn); - HAL_DMA_Start(&dmaUpdate, (uint32_t)WS2812_IO_High, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE); - - - // TIM2 CC1 event - dmaCC1.Init.Direction = DMA_MEMORY_TO_PERIPH; - dmaCC1.Init.PeriphInc = DMA_PINC_DISABLE; - dmaCC1.Init.MemInc = DMA_MINC_ENABLE; - dmaCC1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dmaCC1.Init.MemDataAlignment = DMA_MDATAALIGN_HALFWORD; - dmaCC1.Init.Mode = DMA_CIRCULAR; - dmaCC1.Init.Priority = DMA_PRIORITY_VERY_HIGH; - dmaCC1.Instance = DMA1_Channel5; - //dmaUpdate.XferCpltCallback = TransferComplete; - //dmaUpdate.XferErrorCallback = TransferError; - //dmaUpdate.XferHalfCpltCallback = TransferHalf; - //HAL_NVIC_SetPriority(DMA1_Channel5_IRQn, 0, 0); - //HAL_NVIC_EnableIRQ(DMA1_Channel5_IRQn); - HAL_DMA_Init(&dmaCC1); - HAL_DMA_Start(&dmaCC1, (uint32_t)ws2812bDmaBitBuffer, (uint32_t)&WS2812B_PORT->BRR, BUFFER_SIZE); - - - // TIM2 CC2 event - dmaCC2.Init.Direction = DMA_MEMORY_TO_PERIPH; - dmaCC2.Init.PeriphInc = DMA_PINC_DISABLE; - dmaCC2.Init.MemInc = DMA_MINC_DISABLE; - dmaCC2.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; - dmaCC2.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; - dmaCC2.Init.Mode = DMA_CIRCULAR; - dmaCC2.Init.Priority = DMA_PRIORITY_VERY_HIGH; - dmaCC2.Instance = DMA1_Channel7; - dmaCC2.XferCpltCallback = DMA_TransferCompleteHandler; - dmaCC2.XferHalfCpltCallback = DMA_TransferHalfHandler; - //dmaUpdate.XferErrorCallback = TransferError; - HAL_DMA_Init(&dmaCC2); - HAL_NVIC_SetPriority(DMA1_Channel7_IRQn, 0, 0); - HAL_NVIC_EnableIRQ(DMA1_Channel7_IRQn); - HAL_DMA_Start_IT(&dmaCC2, (uint32_t)WS2812_IO_Low, (uint32_t)&WS2812B_PORT->BSRR, BUFFER_SIZE); - -} - -/* -void DMA1_Channel2_IRQHandler(void) -{ - // Check the interrupt and clear flag - HAL_DMA_IRQHandler(&dmaUpdate); -} - -void DMA1_Channel5_IRQHandler(void) -{ - // Check the interrupt and clear flag - HAL_DMA_IRQHandler(&dmaCC1); -}*/ - -void DMA1_Channel7_IRQHandler(void) -{ - // Check the interrupt and clear flag - HAL_DMA_IRQHandler(&dmaCC2); -} - - - -static void loadNextFramebufferData(WS2812_BufferItem *bItem, uint32_t row) -{ - - uint32_t r = bItem->frameBufferPointer[bItem->frameBufferCounter++]; - uint32_t g = bItem->frameBufferPointer[bItem->frameBufferCounter++]; - uint32_t b = bItem->frameBufferPointer[bItem->frameBufferCounter++]; - - if(bItem->frameBufferCounter == bItem->frameBufferSize) - bItem->frameBufferCounter = 0; - - ws2812b_set_pixel(bItem->channel, row, r, g, b); -} - - -// Transmit the framebuffer -static void WS2812_sendbuf() -{ - // transmission complete flag - ws2812b.transferComplete = 0; - - uint32_t i; - - for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) - { - ws2812b.item[i].frameBufferCounter = 0; - - loadNextFramebufferData(&ws2812b.item[i], 0); // ROW 0 - loadNextFramebufferData(&ws2812b.item[i], 1); // ROW 0 - } - - // clear all DMA flags - __HAL_DMA_CLEAR_FLAG(&dmaUpdate, DMA_FLAG_TC2 | DMA_FLAG_HT2 | DMA_FLAG_TE2); - __HAL_DMA_CLEAR_FLAG(&dmaCC1, DMA_FLAG_TC5 | DMA_FLAG_HT5 | DMA_FLAG_TE5); - __HAL_DMA_CLEAR_FLAG(&dmaCC2, DMA_FLAG_TC7 | DMA_FLAG_HT7 | DMA_FLAG_TE7); - - // configure the number of bytes to be transferred by the DMA controller - dmaUpdate.Instance->CNDTR = BUFFER_SIZE; - dmaCC1.Instance->CNDTR = BUFFER_SIZE; - dmaCC2.Instance->CNDTR = BUFFER_SIZE; - - // clear all TIM2 flags - __HAL_TIM_CLEAR_FLAG(&Tim2Handle, TIM_FLAG_UPDATE | TIM_FLAG_CC1 | TIM_FLAG_CC2 | TIM_FLAG_CC3 | TIM_FLAG_CC4); - - // enable DMA channels - __HAL_DMA_ENABLE(&dmaUpdate); - __HAL_DMA_ENABLE(&dmaCC1); - __HAL_DMA_ENABLE(&dmaCC2); - - // IMPORTANT: enable the TIM2 DMA requests AFTER enabling the DMA channels! - __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_UPDATE); - __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_CC1); - __HAL_TIM_ENABLE_DMA(&Tim2Handle, TIM_DMA_CC2); - - TIM2->CNT = tim_period-1; - - // start TIM2 - __HAL_TIM_ENABLE(&Tim2Handle); -} - - - - - -void DMA_TransferHalfHandler(DMA_HandleTypeDef *DmaHandle) -{ - #if defined(LED4_PORT) - LED4_PORT->BSRR = LED4_PIN; - #endif - - // Is this the last LED? - if(ws2812b.repeatCounter != (WS2812B_NUMBER_OF_LEDS / 2 - 1)) - { - uint32_t i; - - for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) - { - loadNextFramebufferData(&ws2812b.item[i], 0); - } - - } else { - // If this is the last pixel, set the next pixel value to zeros, because - // the DMA would not stop exactly at the last bit. - ws2812b_set_pixel(0, 0, 0, 0, 0); - } - - #if defined(LED4_PORT) - LED4_PORT->BRR = LED4_PIN; - #endif -} - -void DMA_TransferCompleteHandler(DMA_HandleTypeDef *DmaHandle) -{ - #if defined(LED5_PORT) - LED5_PORT->BSRR = LED5_PIN; - #endif - - ws2812b.repeatCounter++; - - if(ws2812b.repeatCounter == WS2812B_NUMBER_OF_LEDS / 2) - { - // Transfer of all LEDs is done, disable DMA but enable tiemr update IRQ to stop the 50us pulse - ws2812b.repeatCounter = 0; - - // Enable TIM2 Update interrupt for 50us Treset signal - __HAL_TIM_ENABLE_IT(&Tim2Handle, TIM_IT_UPDATE); - // Disable DMA - __HAL_DMA_DISABLE(&dmaUpdate); - __HAL_DMA_DISABLE(&dmaCC1); - __HAL_DMA_DISABLE(&dmaCC2); - - // Disable the DMA requests - __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_UPDATE); - __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_CC1); - __HAL_TIM_DISABLE_DMA(&Tim2Handle, TIM_DMA_CC2); - - // Manually set outputs to low to generate 50us reset impulse - WS2812B_PORT->BSRR = WS2812_IO_Low[0]; - } else { - - // Load bitbuffer with next RGB LED values - uint32_t i; - for( i = 0; i < WS2812_BUFFER_COUNT; i++ ) - { - loadNextFramebufferData(&ws2812b.item[i], 1); - } - - } - - #if defined(LED5_PORT) - LED5_PORT->BRR = LED5_PIN; - #endif -} - - -void TIM2_IRQHandler(void) -{ - HAL_TIM_IRQHandler(&Tim2Handle); -} - -// TIM2 Interrupt Handler gets executed on every TIM2 Update if enabled -void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) -{ - // I have to wait 50us to generate Treset signal - if (ws2812b.timerPeriodCounter < (uint8_t)WS2812_RESET_PERIOD) - { - // count the number of timer periods - ws2812b.timerPeriodCounter++; - } - else - { - ws2812b.timerPeriodCounter = 0; - __HAL_TIM_DISABLE(&Tim2Handle); - TIM2->CR1 = 0; // disable timer - - // disable the TIM2 Update - __HAL_TIM_DISABLE_IT(&Tim2Handle, TIM_IT_UPDATE); - // set TransferComplete flag - ws2812b.transferComplete = 1; - } - -} - - - -static void ws2812b_set_pixel(uint8_t row, uint16_t column, uint8_t red, uint8_t green, uint8_t blue) -{ - - // Apply gamma - red = gammaTable[red]; - green = gammaTable[green]; - blue = gammaTable[blue]; - - - uint32_t calcCol = (column*24); - uint32_t invRed = ~red; - uint32_t invGreen = ~green; - uint32_t invBlue = ~blue; - - -#if defined(SETPIX_1) - uint8_t i; - uint32_t calcClearRow = ~(0x01<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<>7)<> 7); - bitBand+=16; - - *bitBand = (invGreen >> 6); - bitBand+=16; - - *bitBand = (invGreen >> 5); - bitBand+=16; - - *bitBand = (invGreen >> 4); - bitBand+=16; - - *bitBand = (invGreen >> 3); - bitBand+=16; - - *bitBand = (invGreen >> 2); - bitBand+=16; - - *bitBand = (invGreen >> 1); - bitBand+=16; - - *bitBand = (invGreen >> 0); - bitBand+=16; - - // RED - *bitBand = (invRed >> 7); - bitBand+=16; - - *bitBand = (invRed >> 6); - bitBand+=16; - - *bitBand = (invRed >> 5); - bitBand+=16; - - *bitBand = (invRed >> 4); - bitBand+=16; - - *bitBand = (invRed >> 3); - bitBand+=16; - - *bitBand = (invRed >> 2); - bitBand+=16; - - *bitBand = (invRed >> 1); - bitBand+=16; - - *bitBand = (invRed >> 0); - bitBand+=16; - - // BLUE - *bitBand = (invBlue >> 7); - bitBand+=16; - - *bitBand = (invBlue >> 6); - bitBand+=16; - - *bitBand = (invBlue >> 5); - bitBand+=16; - - *bitBand = (invBlue >> 4); - bitBand+=16; - - *bitBand = (invBlue >> 3); - bitBand+=16; - - *bitBand = (invBlue >> 2); - bitBand+=16; - - *bitBand = (invBlue >> 1); - bitBand+=16; - - *bitBand = (invBlue >> 0); - bitBand+=16; +/* --- CONFIGURATION CHECK -------------------------------------------------- */ +#if !defined(WS2812_LED_N) + #error WS2812 LED chain length not specified +#elif WS2812_LED_N <= 0 + #error WS2812 LED chain length set to invalid value #endif + +#if !defined(WS2812_TIM_N) + #error WS2812 timer not specified +#elif WS2812_TIM_N == 1 + #define WS2812_DMA_STREAM STM32_DMA1_STREAM5 +#elif WS2812_TIM_N == 2 + #define WS2812_DMA_STREAM STM32_DMA1_STREAM2 +#elif WS2812_TIM_N == 3 + #define WS2812_DMA_STREAM STM32_DMA1_STREAM3 +#elif WS2812_TIM_N == 4 + #define WS2812_DMA_STREAM STM32_DMA1_STREAM7 +#else + #error WS2812 timer set to invalid value +#endif + +#if !defined(WS2812_TIM_CH) + #error WS2812 timer channel not specified +#elif WS2812_TIM_CH >= 4 + #error WS2812 timer channel set to invalid value +#endif + +/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ + +#define WS2812_PWM_FREQUENCY (72000000) /**< Clock frequency of PWM */ +#define WS2812_PWM_PERIOD (90) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ + +/** + * @brief Number of bit-periods to hold the data line low at the end of a frame + * + * The reset period for each frame must be at least 50 uS; so we add in 50 bit-times + * of zeroes at the end. (50 bits)*(1.25 uS/bit) = 62.5 uS, which gives us some + * slack in the timing requirements + */ +#define WS2812_RESET_BIT_N (50) +#define WS2812_COLOR_BIT_N (WS2812_LED_N*24) /**< Number of data bits */ +#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ + +/** + * @brief High period for a zero, in ticks + * + * Per the datasheet: + * - T0H: 0.200 uS to 0.500 uS, inclusive + * - T0L: 0.650 uS to 0.950 uS, inclusive + * + * With a duty cycle of 22 ticks, we have a high period of 22/(72 MHz) = 3.06 uS, and + * a low period of (90 - 22)/(72 MHz) = 9.44 uS. These values are within the allowable + * bounds, and intentionally skewed as far to the low duty-cycle side as possible + */ +#define WS2812_DUTYCYCLE_0 (22) + +/** + * @brief High period for a one, in ticks + * + * Per the datasheet: + * - T0H: 0.550 uS to 0.850 uS, inclusive + * - T0L: 0.450 uS to 0.750 uS, inclusive + * + * With a duty cycle of 56 ticks, we have a high period of 56/(72 MHz) = 7.68 uS, and + * a low period of (90 - 56)/(72 MHz) = 4.72 uS. These values are within the allowable + * bounds, and intentionally skewed as far to the high duty-cycle side as possible + */ +#define WS2812_DUTYCYCLE_1 (56) + +/* --- PRIVATE MACROS ------------------------------------------------------- */ + +/** + * @brief Generates a reference to a numbered PWM driver + * + * @param[in] n: The driver (timer) number + * + * @return A reference to the driver + */ +#define PWMD(n) CONCAT_EXPANDED_SYMBOLS(PWMD, n) + +#define WS2812_PWMD PWMD(WS2812_TIM_N) /**< The PWM driver to use for the LED chain */ + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit + * + * @param[in] led: The led index [0, @ref WS2812_LED_N) + * @param[in] byte: The byte number [0, 2] + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +#define WS2812_BIT(led, byte, bit) (24*(led) + 8*(byte) + (7 - (bit))) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit + * + * @note The red byte is the middle byte in the color packet + * + * @param[in] led: The led index [0, @ref WS2812_LED_N) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +#define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit + * + * @note The red byte is the first byte in the color packet + * + * @param[in] led: The led index [0, @ref WS2812_LED_N) + * @param[in] bit: The bit number [0, 7] + * + * @return The bit index + */ +#define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit)) + +/** + * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit + * + * @note The red byte is the last byte in the color packet + * + * @param[in] led: The led index [0, @ref WS2812_LED_N) + * @param[in] bit: The bit index [0, 7] + * + * @return The bit index + */ +#define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) + +/* --- PRIVATE VARIABLES ---------------------------------------------------- */ + +static uint8_t ws2812_frame_buffer[WS2812_BIT_N]; /**< Buffer for a frame */ + +/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ + +void ws2812_init(void) +{ + // Initialize led frame buffer + uint32_t i; + for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle + for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero + + // Configure PA0 as AF output + palSetPadMode(GPIOA, 1, PAL_MODE_ALTERNATE(1)); + + // PWM Configuration + #pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config + static const PWMConfig ws2812_pwm_config = { + .frequency = WS2812_PWM_FREQUENCY, + .period = WS2812_PWM_PERIOD, + .callback = NULL, + .channels = { + [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled + [WS2812_TIM_CH] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}, // Turn on the channel we care about + }, + .cr2 = 0, + .dier = TIM_DIER_UDE, // DMA on update event for next period + }; + #pragma GCC diagnostic pop // Restore command-line warning options + + // Configure DMA + dmaStreamAllocate(WS2812_DMA_STREAM, 10, NULL, NULL); + dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWMD.tim->CCR[WS2812_TIM_CH])); + dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer); + dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N); + dmaStreamSetMode(WS2812_DMA_STREAM, + STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); + + // Start DMA + dmaStreamEnable(WS2812_DMA_STREAM); + + // Configure PWM + // NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the + // ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer, + // disable counting, enable the channel, and then make whatever configuration changes we need. + pwmStart(&WS2812_PWMD, &ws2812_pwm_config); + pwmEnableChannel(&WS2812_PWMD, WS2812_TIM_CH, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in +} + +ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b) +{ + // Check for valid LED + if (led_number >= WS2812_LED_N) return WS2812_LED_INVALID; + + // Write color to frame buffer + uint32_t bit; + for (bit = 0; bit < 8; bit++) { + ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; + } + + // Success + return WS2812_SUCCESS; +} + +/** @} addtogroup WS2812 */ + +void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { + ws2812_init(); + uint8_t i = 0; + while (i < number_of_leds) { + ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); + i++; + } } -void ws2812b_init() -{ - ws2812b_gpio_init(); - DMA_init(); - TIM2_init(); +void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds) { - // Need to start the first transfer - ws2812b.transferComplete = 1; } - - -void ws2812b_handle() -{ - if(ws2812b.startTransfer) { - ws2812b.startTransfer = 0; - WS2812_sendbuf(); - } - -} \ No newline at end of file diff --git a/drivers/arm/ws2812.h b/drivers/arm/ws2812.h index 53a1787374..47e166e779 100644 --- a/drivers/arm/ws2812.h +++ b/drivers/arm/ws2812.h @@ -1,94 +1,102 @@ -/* +/** + * @file ws2812.h + * @author Austin Glaser + * @brief Interface to WS2812 LED driver + * + * Copyright (C) 2016 Austin Glaser + * + * This software may be modified and distributed under the terms + * of the MIT license. See the LICENSE file for details. + * + * @todo Put in names and descriptions of variables which need to be defined to use this file + */ - WS2812B CPU and memory efficient library +#ifndef WS2812_H_ +#define WS2812_H_ - Date: 28.9.2016 +/** + * @defgroup WS2812 WS2812 Driver + * @{ + * + * @brief DMA-based WS2812 LED driver + * + * A driver for WS2812 LEDs + */ - Author: Martin Hubacek - http://www.martinhubacek.cz - @hubmartin +/* --- PUBLIC DEPENDENCIES -------------------------------------------------- */ - Licence: MIT License +// Standard +#include +#include "rgblight_types.h" -*/ +/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ -#ifndef WS2812B_H_ -#define WS2812B_H_ -#include "ws2812.h" +/** + * @brief Return codes from ws2812 interface functions + */ +typedef enum { + WS2812_SUCCESS = 0x00, /**< Operation completeed successfully */ + WS2812_LED_INVALID, /**< Attempted to index an invalid LED (@ref WS2812_N_LEDS) */ + MAX_WS2812_ERR, /**< Total number of possible error codes */ + WS2812_ERR_INVALID /**< Invalid error value */ +} ws2812_err_t; -// GPIO enable command -#define WS2812B_GPIO_CLK_ENABLE() __HAL_RCC_GPIOC_CLK_ENABLE() -// LED output port -#define WS2812B_PORT GPIOC -// LED output pins -#define WS2812B_PINS (GPIO_PIN_0 | GPIO_PIN_1 | GPIO_PIN_2 | GPIO_PIN_3) -// How many LEDs are in the series -#define WS2812B_NUMBER_OF_LEDS 60 +/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ -// Number of output LED strips. Each has its own buffer. -#define WS2812_BUFFER_COUNT 2 +/** + * @brief Initialize the driver + * + * After this function is called, all necessary background tasks will be started. + * The frame is initially dark. + */ +void ws2812_init(void); -// Choose one of the bit-juggling setpixel implementation -// ******************************************************* -//#define SETPIX_1 // For loop, works everywhere, slow -//#define SETPIX_2 // Bit band in a loop -//#define SETPIX_3 // Like SETPIX_1 but with unrolled loop -#define SETPIX_4 // Fastest copying using bit-banding +/** + * @brief Write the value of a single LED in the chain + * + * The color value is written to a frame buffer, and will not + * be updated until the next frame is written. Frames are written + * at the maximum possible speed -- the longest latency between a + * call to this function and the value being displayed is + * 1.25uS*(24*@ref WS2812_LED_N + 50) + * + * @param[in] led_number: The index of the LED to be written. Must be strictly less than + * @ref WS2812_N_LEDS + * @param[in] r: The red level of the LED + * @param[in] g: The green level of the LED + * @param[in] b: The blue level of the LED + * + * @retval WS2812_SUCCESS: The write was successful + * @retval WS2812_LED_INVALID: The write was to an invalid LED index + */ +ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b); +/** @} defgroup WS2812 */ -// DEBUG OUTPUT -// ******************** -#define LED4_PORT GPIOC -#define LED4_PIN GPIO_PIN_10 +void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); +void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); -#define LED5_PORT GPIOC -#define LED5_PIN GPIO_PIN_10 +/** + * @brief Concatenates two symbols s1 and s2 exactly, without expanding either + * + * @param[in] s1: The first symbol to concatenate + * @param[in] s2: The second symbol to concatenate + * + * @return A single symbol containing s1 and s2 concatenated without expansion + */ +#define CONCAT_SYMBOLS(s1, s2) s1##s2 +/** + * @brief Concatenate the symbols s1 and s2, expanding both of them + * + * This is important because simply applying s1##s2 doesn't expand them if they're + * preprocessor tokens themselves + * + * @param[in] s1: The first symbol to concatenate + * @param[in] s2: The second symbol to concatenate + * + * @return A single symbol containing s1 expanded followed by s2 expanded + */ +#define CONCAT_EXPANDED_SYMBOLS(s1, s2) CONCAT_SYMBOLS(s1, s2) -// Public functions -// **************** -void ws2812b_init(); -void ws2812b_handle(); - -// Library structures -// ****************** -// This value sets number of periods to generate 50uS Treset signal -#define WS2812_RESET_PERIOD 12 - -typedef struct WS2812_BufferItem { - uint8_t* frameBufferPointer; - uint32_t frameBufferSize; - uint32_t frameBufferCounter; - uint8_t channel; // digital output pin/channel -} WS2812_BufferItem; - - - -typedef struct WS2812_Struct -{ - WS2812_BufferItem item[WS2812_BUFFER_COUNT]; - uint8_t transferComplete; - uint8_t startTransfer; - uint32_t timerPeriodCounter; - uint32_t repeatCounter; -} WS2812_Struct; - -WS2812_Struct ws2812b; - -// Bit band stuff -#define RAM_BASE 0x20000000 -#define RAM_BB_BASE 0x22000000 -#define Var_ResetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2)) = 0) -#define Var_SetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2)) = 1) -#define Var_GetBit_BB(VarAddr, BitNumber) (*(volatile uint32_t *) (RAM_BB_BASE | ((VarAddr - RAM_BASE) << 5) | ((BitNumber) << 2))) -#define BITBAND_SRAM(address, bit) ( (__IO uint32_t *) (RAM_BB_BASE + (((uint32_t)address) - RAM_BASE) * 32 + (bit) * 4)) - -#define varSetBit(var,bit) (Var_SetBit_BB((uint32_t)&var,bit)) -#define varResetBit(var,bit) (Var_ResetBit_BB((uint32_t)&var,bit)) -#define varGetBit(var,bit) (Var_GetBit_BB((uint32_t)&var,bit)) - -static void ws2812b_set_pixel(uint8_t row, uint16_t column, uint8_t red, uint8_t green, uint8_t blue); -void DMA_TransferCompleteHandler(DMA_HandleTypeDef *DmaHandle); -void DMA_TransferHalfHandler(DMA_HandleTypeDef *DmaHandle); - -#endif /* WS2812B_H_ */ \ No newline at end of file +#endif /* WS2812_H_ */ diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h index 452a99d746..097bacd715 100644 --- a/keyboards/planck/config.h +++ b/keyboards/planck/config.h @@ -18,7 +18,9 @@ along with this program. If not, see . #ifndef CONFIG_H #define CONFIG_H +#ifdef __AVR__ #include "config_common.h" +#endif /* USB Device descriptor parameter */ #define VENDOR_ID 0xFEED diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h index 831dabe62c..4fe91d963a 100644 --- a/keyboards/planck/rev6/config.h +++ b/keyboards/planck/rev6/config.h @@ -125,4 +125,9 @@ /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 1 +#define WS2812_LED_N 1 +#define RGBLED_NUM WS2812_LED_N +#define WS2812_TIM_N 1 +#define WS2812_TIM_CH 1 + #endif diff --git a/keyboards/planck/rev6/halconf.h b/keyboards/planck/rev6/halconf.h index 8fe8e0c6f5..5e5d70219e 100644 --- a/keyboards/planck/rev6/halconf.h +++ b/keyboards/planck/rev6/halconf.h @@ -111,7 +111,7 @@ * @brief Enables the PWM subsystem. */ #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) -#define HAL_USE_PWM FALSE +#define HAL_USE_PWM TRUE #endif /** diff --git a/keyboards/planck/rev6/mcuconf.h b/keyboards/planck/rev6/mcuconf.h index 00179f69f1..b101957034 100644 --- a/keyboards/planck/rev6/mcuconf.h +++ b/keyboards/planck/rev6/mcuconf.h @@ -182,7 +182,7 @@ * PWM driver system settings. */ #define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM1 TRUE #define STM32_PWM_USE_TIM2 FALSE #define STM32_PWM_USE_TIM3 FALSE #define STM32_PWM_USE_TIM4 FALSE diff --git a/keyboards/planck/rev6/rev6.c b/keyboards/planck/rev6/rev6.c index 650e1a194d..45bd12d606 100644 --- a/keyboards/planck/rev6/rev6.c +++ b/keyboards/planck/rev6/rev6.c @@ -14,8 +14,12 @@ * along with this program. If not, see . */ #include "rev6.h" +#include "rgblight.h" void matrix_init_kb(void) { + rgblight_enable(); + rgblight_mode(1); + rgblight_setrgb(0xFF, 0xFF, 0xFF); matrix_init_user(); } diff --git a/keyboards/planck/rev6/rules.mk b/keyboards/planck/rev6/rules.mk index c49b528e3c..5d339fc88e 100644 --- a/keyboards/planck/rev6/rules.mk +++ b/keyboards/planck/rev6/rules.mk @@ -52,4 +52,5 @@ COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes +RGBLIGHT_ENABLE = yes # SERIAL_LINK_ENABLE = yes diff --git a/quantum/rgblight.c b/quantum/rgblight.c index 75512e97a7..5cfbf307c6 100644 --- a/quantum/rgblight.c +++ b/quantum/rgblight.c @@ -14,9 +14,11 @@ * along with this program. If not, see . */ #include -#include -#include -#include +#ifdef __AVR__ + #include + #include +#endif +#include "wait.h" #include "progmem.h" #include "timer.h" #include "rgblight.h" @@ -113,10 +115,16 @@ void setrgb(uint8_t r, uint8_t g, uint8_t b, LED_TYPE *led1) { uint32_t eeconfig_read_rgblight(void) { - return eeprom_read_dword(EECONFIG_RGBLIGHT); + #ifdef __AVR__ + return eeprom_read_dword(EECONFIG_RGBLIGHT); + #else + return 0; + #endif } void eeconfig_update_rgblight(uint32_t val) { - eeprom_update_dword(EECONFIG_RGBLIGHT, val); + #ifdef __AVR__ + eeprom_update_dword(EECONFIG_RGBLIGHT, val); + #endif } void eeconfig_update_rgblight_default(void) { dprintf("eeconfig_update_rgblight_default\n"); @@ -281,7 +289,7 @@ void rgblight_disable(void) { #ifdef RGBLIGHT_ANIMATIONS rgblight_timer_disable(); #endif - _delay_ms(50); + wait_ms(50); rgblight_set(); } diff --git a/quantum/rgblight_types.h b/quantum/rgblight_types.h index b1aa7026c4..49ef5c8ea7 100644 --- a/quantum/rgblight_types.h +++ b/quantum/rgblight_types.h @@ -23,7 +23,9 @@ #ifndef RGBLIGHT_TYPES #define RGBLIGHT_TYPES -#include +#ifdef __AVR__ + #include +#endif #ifdef RGBW #define LED_TYPE struct cRGBW diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index e53204905f..9febf6f6db 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -145,6 +145,8 @@ HEX = $(OBJCOPY) -O $(FORMAT) EEP = BIN = $(OBJCOPY) -O binary +COMMON_VPATH += $(DRIVER_PATH)/arm + THUMBFLAGS = -DTHUMB_PRESENT -mno-thumb-interwork -DTHUMB_NO_INTERWORKING -mthumb -DTHUMB COMPILEFLAGS += -fomit-frame-pointer From 1c0d85c1431e8cbd5129988f68ee7e56b999bbc8 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 22 May 2018 21:40:38 -0400 Subject: [PATCH 31/59] update build includes for chibios --- common.mk | 12 ++++++------ tmk_core/chibios.mk | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/common.mk b/common.mk index 5b49680ea1..aea29a7a20 100644 --- a/common.mk +++ b/common.mk @@ -3,16 +3,16 @@ include message.mk # Directory common source files exist TOP_DIR = . TMK_DIR = tmk_core -TMK_PATH = $(TOP_DIR)/$(TMK_DIR) -LIB_PATH = $(TOP_DIR)/lib +TMK_PATH = $(TMK_DIR) +LIB_PATH = lib QUANTUM_DIR = quantum -QUANTUM_PATH = $(TOP_DIR)/$(QUANTUM_DIR) +QUANTUM_PATH = $(QUANTUM_DIR) DRIVER_DIR = drivers -DRIVER_PATH = $(TOP_DIR)/$(DRIVER_DIR) +DRIVER_PATH = $(DRIVER_DIR) -BUILD_DIR := $(TOP_DIR)/.build +BUILD_DIR := .build COMMON_VPATH := $(TOP_DIR) COMMON_VPATH += $(TMK_PATH) @@ -21,4 +21,4 @@ COMMON_VPATH += $(QUANTUM_PATH)/keymap_extras COMMON_VPATH += $(QUANTUM_PATH)/audio COMMON_VPATH += $(QUANTUM_PATH)/process_keycode COMMON_VPATH += $(QUANTUM_PATH)/api -COMMON_VPATH += $(DRIVER_PATH) \ No newline at end of file +COMMON_VPATH += $(DRIVER_PATH) diff --git a/tmk_core/chibios.mk b/tmk_core/chibios.mk index 9febf6f6db..25c49204bc 100644 --- a/tmk_core/chibios.mk +++ b/tmk_core/chibios.mk @@ -125,7 +125,7 @@ CHIBISRC := $(patsubst $(TOP_DIR)/%,%,$(CHIBISRC)) EXTRAINCDIRS += $(CHIBIOS)/os/license \ $(STARTUPINC) $(KERNINC) $(PORTINC) $(OSALINC) \ $(HALINC) $(PLATFORMINC) $(BOARDINC) $(TESTINC) \ - $(STREAMSINC) $(CHIBIOS)/os/various + $(STREAMSINC) $(CHIBIOS)/os/various $(COMMON_VPATH) # # Project, sources and paths From 3e282ab203bfa657bba85dd71bd2008062c3cff7 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Tue, 22 May 2018 21:41:10 -0400 Subject: [PATCH 32/59] update ws2812 driver/config --- drivers/arm/ws2812.c | 40 +++++++++++-------- keyboards/planck/config.h | 2 - .../rev6/boards/GENERIC_STM32_F303XC/board.h | 2 +- keyboards/planck/rev6/config.h | 5 +++ keyboards/planck/rev6/mcuconf.h | 1 - keyboards/planck/rev6/rev6.c | 1 + 6 files changed, 30 insertions(+), 21 deletions(-) diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c index bab52e7531..f8730c6e1c 100644 --- a/drivers/arm/ws2812.c +++ b/drivers/arm/ws2812.c @@ -40,16 +40,17 @@ #if !defined(WS2812_TIM_N) #error WS2812 timer not specified -#elif WS2812_TIM_N == 1 - #define WS2812_DMA_STREAM STM32_DMA1_STREAM5 -#elif WS2812_TIM_N == 2 - #define WS2812_DMA_STREAM STM32_DMA1_STREAM2 -#elif WS2812_TIM_N == 3 - #define WS2812_DMA_STREAM STM32_DMA1_STREAM3 -#elif WS2812_TIM_N == 4 - #define WS2812_DMA_STREAM STM32_DMA1_STREAM7 -#else - #error WS2812 timer set to invalid value +#endif +#if defined(STM32F2XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32F7XX) + #if WS2812_TIM_N <= 2 + #define WS2812_AF 1 + #elif WS2812_TIM_N <= 5 + #define WS2812_AF 2 + #elif WS2812_TIM_N <= 11 + #define WS2812_AF 3 + #endif +#elif !defined(WS2812_AF) + #error WS2812_AF timer alternate function not specified #endif #if !defined(WS2812_TIM_CH) @@ -60,8 +61,8 @@ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ -#define WS2812_PWM_FREQUENCY (72000000) /**< Clock frequency of PWM */ -#define WS2812_PWM_PERIOD (90) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ +#define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2) /**< Clock frequency of PWM */ +#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY/800000) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ /** * @brief Number of bit-periods to hold the data line low at the end of a frame @@ -85,7 +86,7 @@ * a low period of (90 - 22)/(72 MHz) = 9.44 uS. These values are within the allowable * bounds, and intentionally skewed as far to the low duty-cycle side as possible */ -#define WS2812_DUTYCYCLE_0 (22) +#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350)) /** * @brief High period for a one, in ticks @@ -98,7 +99,7 @@ * a low period of (90 - 56)/(72 MHz) = 4.72 uS. These values are within the allowable * bounds, and intentionally skewed as far to the high duty-cycle side as possible */ -#define WS2812_DUTYCYCLE_1 (56) +#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800)) /* --- PRIVATE MACROS ------------------------------------------------------- */ @@ -173,8 +174,12 @@ void ws2812_init(void) for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero - // Configure PA0 as AF output - palSetPadMode(GPIOA, 1, PAL_MODE_ALTERNATE(1)); + // Configure PA1 as AF output +#ifdef WS2812_EXTERNAL_PULLUP + palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF) | PAL_STM32_OTYPE_OPENDRAIN); +#else + palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF)); +#endif // PWM Configuration #pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config @@ -199,6 +204,8 @@ void ws2812_init(void) dmaStreamSetMode(WS2812_DMA_STREAM, STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); + //STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | + //STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); // Start DMA dmaStreamEnable(WS2812_DMA_STREAM); @@ -231,7 +238,6 @@ ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t /** @} addtogroup WS2812 */ void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds) { - ws2812_init(); uint8_t i = 0; while (i < number_of_leds) { ws2812_write_led(i, ledarray[i].r, ledarray[i].g, ledarray[i].b); diff --git a/keyboards/planck/config.h b/keyboards/planck/config.h index 097bacd715..452a99d746 100644 --- a/keyboards/planck/config.h +++ b/keyboards/planck/config.h @@ -18,9 +18,7 @@ along with this program. If not, see . #ifndef CONFIG_H #define CONFIG_H -#ifdef __AVR__ #include "config_common.h" -#endif /* USB Device descriptor parameter */ #define VENDOR_ID 0xFEED diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h index 7b8b826f68..77c1ee951d 100644 --- a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h @@ -25,7 +25,7 @@ * Board identifier. */ #define BOARD_GENERIC_STM32_F303XC -#define BOARD_NAME "Clueboard 60 PCB" +#define BOARD_NAME "Planck PCB" /* * Board oscillators-related settings. diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h index 4fe91d963a..aaa49710c1 100644 --- a/keyboards/planck/rev6/config.h +++ b/keyboards/planck/rev6/config.h @@ -129,5 +129,10 @@ #define RGBLED_NUM WS2812_LED_N #define WS2812_TIM_N 1 #define WS2812_TIM_CH 1 +#define PORT_WS2812 GPIOA +#define PIN_WS2812 1 +#define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA stream for TIMx_UP (look up in reference manual under DMA Channel selection) +//#define WS2812_DMA_CHANNEL 7 // DMA channel for TIMx_UP +//#define WS2812_EXTERNAL_PULLUP #endif diff --git a/keyboards/planck/rev6/mcuconf.h b/keyboards/planck/rev6/mcuconf.h index b101957034..d30f08563e 100644 --- a/keyboards/planck/rev6/mcuconf.h +++ b/keyboards/planck/rev6/mcuconf.h @@ -184,7 +184,6 @@ #define STM32_PWM_USE_ADVANCED FALSE #define STM32_PWM_USE_TIM1 TRUE #define STM32_PWM_USE_TIM2 FALSE -#define STM32_PWM_USE_TIM3 FALSE #define STM32_PWM_USE_TIM4 FALSE #define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_TIM1_IRQ_PRIORITY 7 diff --git a/keyboards/planck/rev6/rev6.c b/keyboards/planck/rev6/rev6.c index 45bd12d606..6789ff5c05 100644 --- a/keyboards/planck/rev6/rev6.c +++ b/keyboards/planck/rev6/rev6.c @@ -17,6 +17,7 @@ #include "rgblight.h" void matrix_init_kb(void) { + ws2812_init(); rgblight_enable(); rgblight_mode(1); rgblight_setrgb(0xFF, 0xFF, 0xFF); From d233737c95534dc42eee13d28bb98a0b8cca0e48 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 23 May 2018 00:50:58 -0400 Subject: [PATCH 33/59] last commit for glasser code --- drivers/arm/ws2812.c | 23 +++++++++++-------- .../rev6/boards/GENERIC_STM32_F303XC/board.h | 4 ++-- keyboards/planck/rev6/chconf.h | 2 +- keyboards/planck/rev6/config.h | 6 ++--- keyboards/planck/rev6/mcuconf.h | 6 ++--- keyboards/planck/rev6/rev6.c | 13 ++++++++--- 6 files changed, 33 insertions(+), 21 deletions(-) diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c index f8730c6e1c..91eb3a7c03 100644 --- a/drivers/arm/ws2812.c +++ b/drivers/arm/ws2812.c @@ -41,6 +41,7 @@ #if !defined(WS2812_TIM_N) #error WS2812 timer not specified #endif +// values for these might be found in table 14 in DM00058181 (STM32F303) #if defined(STM32F2XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32F7XX) #if WS2812_TIM_N <= 2 #define WS2812_AF 1 @@ -61,8 +62,10 @@ /* --- PRIVATE CONSTANTS ---------------------------------------------------- */ -#define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2) /**< Clock frequency of PWM */ -#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY/800000) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ +//#define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2) /**< Clock frequency of PWM */ +#define WS2812_PWM_FREQUENCY (72000000) /**< Clock frequency of PWM */ +//#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY/800000) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ +#define WS2812_PWM_PERIOD (90) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ /** * @brief Number of bit-periods to hold the data line low at the end of a frame @@ -86,7 +89,8 @@ * a low period of (90 - 22)/(72 MHz) = 9.44 uS. These values are within the allowable * bounds, and intentionally skewed as far to the low duty-cycle side as possible */ -#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350)) +//#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350)) +#define WS2812_DUTYCYCLE_0 (22) /** * @brief High period for a one, in ticks @@ -99,7 +103,8 @@ * a low period of (90 - 56)/(72 MHz) = 4.72 uS. These values are within the allowable * bounds, and intentionally skewed as far to the high duty-cycle side as possible */ -#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800)) +//#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800)) +#define WS2812_DUTYCYCLE_1 (56) /* --- PRIVATE MACROS ------------------------------------------------------- */ @@ -175,11 +180,11 @@ void ws2812_init(void) for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero // Configure PA1 as AF output -#ifdef WS2812_EXTERNAL_PULLUP - palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF) | PAL_STM32_OTYPE_OPENDRAIN); -#else - palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF)); -#endif +//#ifdef WS2812_EXTERNAL_PULLUP +// palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF) | PAL_STM32_OTYPE_OPENDRAIN); +//#else + palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(1)); +//#endif // PWM Configuration #pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h index 77c1ee951d..a748628abe 100644 --- a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h @@ -245,7 +245,7 @@ * PA15 - ROW4 */ #define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ - PIN_MODE_INPUT(GPIOA_PIN1) | \ + PIN_MODE_ALTERNATE(GPIOA_PIN1) | \ PIN_MODE_INPUT(GPIOA_PIN2) | \ PIN_MODE_INPUT(GPIOA_PIN3) | \ PIN_MODE_INPUT(GPIOA_PIN4) | \ @@ -325,7 +325,7 @@ PIN_ODR_HIGH(GPIOA_SWCLK) | \ PIN_ODR_HIGH(GPIOA_PIN15)) #define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \ - PIN_AFIO_AF(GPIOA_PIN1, 0) | \ + PIN_AFIO_AF(GPIOA_PIN1, 1) | \ PIN_AFIO_AF(GPIOA_PIN2, 0) | \ PIN_AFIO_AF(GPIOA_PIN3, 0) | \ PIN_AFIO_AF(GPIOA_PIN4, 0) | \ diff --git a/keyboards/planck/rev6/chconf.h b/keyboards/planck/rev6/chconf.h index 5a9b833107..b52ca7d2c8 100644 --- a/keyboards/planck/rev6/chconf.h +++ b/keyboards/planck/rev6/chconf.h @@ -41,7 +41,7 @@ * @brief System time counter resolution. * @note Allowed values are 16 or 32 bits. */ -#define CH_CFG_ST_RESOLUTION 32 +#define CH_CFG_ST_RESOLUTION 16 /** * @brief System tick frequency. diff --git a/keyboards/planck/rev6/config.h b/keyboards/planck/rev6/config.h index aaa49710c1..0e462180bd 100644 --- a/keyboards/planck/rev6/config.h +++ b/keyboards/planck/rev6/config.h @@ -125,10 +125,10 @@ /* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ //#define MIDI_TONE_KEYCODE_OCTAVES 1 -#define WS2812_LED_N 1 +#define WS2812_LED_N 2 #define RGBLED_NUM WS2812_LED_N -#define WS2812_TIM_N 1 -#define WS2812_TIM_CH 1 +#define WS2812_TIM_N 2 +#define WS2812_TIM_CH 2 #define PORT_WS2812 GPIOA #define PIN_WS2812 1 #define WS2812_DMA_STREAM STM32_DMA1_STREAM2 // DMA stream for TIMx_UP (look up in reference manual under DMA Channel selection) diff --git a/keyboards/planck/rev6/mcuconf.h b/keyboards/planck/rev6/mcuconf.h index d30f08563e..e2be2a62ac 100644 --- a/keyboards/planck/rev6/mcuconf.h +++ b/keyboards/planck/rev6/mcuconf.h @@ -182,8 +182,8 @@ * PWM driver system settings. */ #define STM32_PWM_USE_ADVANCED FALSE -#define STM32_PWM_USE_TIM1 TRUE -#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM1 FALSE +#define STM32_PWM_USE_TIM2 TRUE #define STM32_PWM_USE_TIM4 FALSE #define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_TIM1_IRQ_PRIORITY 7 @@ -224,7 +224,7 @@ * ST driver system settings. */ #define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 2 +#define STM32_ST_USE_TIMER 3 /* * UART driver system settings. diff --git a/keyboards/planck/rev6/rev6.c b/keyboards/planck/rev6/rev6.c index 6789ff5c05..d53b2224a7 100644 --- a/keyboards/planck/rev6/rev6.c +++ b/keyboards/planck/rev6/rev6.c @@ -17,13 +17,20 @@ #include "rgblight.h" void matrix_init_kb(void) { + // rgblight_enable(); + // rgblight_mode(1); + // rgblight_setrgb(0xFF, 0xFF, 0xFF); ws2812_init(); - rgblight_enable(); - rgblight_mode(1); - rgblight_setrgb(0xFF, 0xFF, 0xFF); matrix_init_user(); } void matrix_scan_kb(void) { matrix_scan_user(); + + int s = 0; + for (int n = 0; n < WS2812_LED_N; n++) { + int s0 = s + 10*n; + ws2812_write_led(n, s0%255, (s0+85)%255, (s0+170)%255); + } + s += 10; } From af6107bee8b238f477e8c50b470c834a6b3a165a Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 23 May 2018 01:54:43 -0400 Subject: [PATCH 34/59] working example --- drivers/arm/ws2812.c | 379 +++++++----------- drivers/arm/ws2812.h | 105 +---- .../rev6/boards/GENERIC_STM32_F303XC/board.h | 4 +- keyboards/planck/rev6/mcuconf.h | 3 +- keyboards/planck/rev6/rev6.c | 15 +- 5 files changed, 169 insertions(+), 337 deletions(-) diff --git a/drivers/arm/ws2812.c b/drivers/arm/ws2812.c index 91eb3a7c03..d55e2c2f47 100644 --- a/drivers/arm/ws2812.c +++ b/drivers/arm/ws2812.c @@ -1,253 +1,156 @@ -/** - * @file ws2812.c - * @author Austin Glaser - * @brief WS2812 LED driver +/* + * LEDDriver.c * - * Copyright (C) 2016 Austin Glaser - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - * - * @todo Put in names and descriptions of variables which need to be defined to use this file - * - * @addtogroup WS2812 - * @{ + * Created on: Aug 26, 2013 + * Author: Omri Iluz */ -/* --- PRIVATE DEPENDENCIES ------------------------------------------------- */ - -// This Driver #include "ws2812.h" +#include "stdlib.h" -// Standard -#include +static uint8_t *fb; +static int sLeds; +static stm32_gpio_t *sPort; +static uint32_t sMask; +uint8_t* dma_source; -// ChibiOS -#include "ch.h" -#include "hal.h" - -// Application -#include "board.h" -#include "util.h" - -/* --- CONFIGURATION CHECK -------------------------------------------------- */ - -#if !defined(WS2812_LED_N) - #error WS2812 LED chain length not specified -#elif WS2812_LED_N <= 0 - #error WS2812 LED chain length set to invalid value -#endif - -#if !defined(WS2812_TIM_N) - #error WS2812 timer not specified -#endif -// values for these might be found in table 14 in DM00058181 (STM32F303) -#if defined(STM32F2XX) || defined(STM32F3XX) || defined(STM32F4XX) || defined(STM32F7XX) - #if WS2812_TIM_N <= 2 - #define WS2812_AF 1 - #elif WS2812_TIM_N <= 5 - #define WS2812_AF 2 - #elif WS2812_TIM_N <= 11 - #define WS2812_AF 3 - #endif -#elif !defined(WS2812_AF) - #error WS2812_AF timer alternate function not specified -#endif - -#if !defined(WS2812_TIM_CH) - #error WS2812 timer channel not specified -#elif WS2812_TIM_CH >= 4 - #error WS2812 timer channel set to invalid value -#endif - -/* --- PRIVATE CONSTANTS ---------------------------------------------------- */ - -//#define WS2812_PWM_FREQUENCY (STM32_SYSCLK/2) /**< Clock frequency of PWM */ -#define WS2812_PWM_FREQUENCY (72000000) /**< Clock frequency of PWM */ -//#define WS2812_PWM_PERIOD (WS2812_PWM_FREQUENCY/800000) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ -#define WS2812_PWM_PERIOD (90) /**< Clock period in ticks. 90/(72 MHz) = 1.25 uS (as per datasheet) */ - -/** - * @brief Number of bit-periods to hold the data line low at the end of a frame - * - * The reset period for each frame must be at least 50 uS; so we add in 50 bit-times - * of zeroes at the end. (50 bits)*(1.25 uS/bit) = 62.5 uS, which gives us some - * slack in the timing requirements - */ -#define WS2812_RESET_BIT_N (50) -#define WS2812_COLOR_BIT_N (WS2812_LED_N*24) /**< Number of data bits */ -#define WS2812_BIT_N (WS2812_COLOR_BIT_N + WS2812_RESET_BIT_N) /**< Total number of bits in a frame */ - -/** - * @brief High period for a zero, in ticks - * - * Per the datasheet: - * - T0H: 0.200 uS to 0.500 uS, inclusive - * - T0L: 0.650 uS to 0.950 uS, inclusive - * - * With a duty cycle of 22 ticks, we have a high period of 22/(72 MHz) = 3.06 uS, and - * a low period of (90 - 22)/(72 MHz) = 9.44 uS. These values are within the allowable - * bounds, and intentionally skewed as far to the low duty-cycle side as possible - */ -//#define WS2812_DUTYCYCLE_0 (WS2812_PWM_FREQUENCY/(1000000000/350)) -#define WS2812_DUTYCYCLE_0 (22) - -/** - * @brief High period for a one, in ticks - * - * Per the datasheet: - * - T0H: 0.550 uS to 0.850 uS, inclusive - * - T0L: 0.450 uS to 0.750 uS, inclusive - * - * With a duty cycle of 56 ticks, we have a high period of 56/(72 MHz) = 7.68 uS, and - * a low period of (90 - 56)/(72 MHz) = 4.72 uS. These values are within the allowable - * bounds, and intentionally skewed as far to the high duty-cycle side as possible - */ -//#define WS2812_DUTYCYCLE_1 (WS2812_PWM_FREQUENCY/(1000000000/800)) -#define WS2812_DUTYCYCLE_1 (56) - -/* --- PRIVATE MACROS ------------------------------------------------------- */ - -/** - * @brief Generates a reference to a numbered PWM driver - * - * @param[in] n: The driver (timer) number - * - * @return A reference to the driver - */ -#define PWMD(n) CONCAT_EXPANDED_SYMBOLS(PWMD, n) - -#define WS2812_PWMD PWMD(WS2812_TIM_N) /**< The PWM driver to use for the LED chain */ - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given bit - * - * @param[in] led: The led index [0, @ref WS2812_LED_N) - * @param[in] byte: The byte number [0, 2] - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -#define WS2812_BIT(led, byte, bit) (24*(led) + 8*(byte) + (7 - (bit))) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given red bit - * - * @note The red byte is the middle byte in the color packet - * - * @param[in] led: The led index [0, @ref WS2812_LED_N) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -#define WS2812_RED_BIT(led, bit) WS2812_BIT((led), 1, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given green bit - * - * @note The red byte is the first byte in the color packet - * - * @param[in] led: The led index [0, @ref WS2812_LED_N) - * @param[in] bit: The bit number [0, 7] - * - * @return The bit index - */ -#define WS2812_GREEN_BIT(led, bit) WS2812_BIT((led), 0, (bit)) - -/** - * @brief Determine the index in @ref ws2812_frame_buffer "the frame buffer" of a given blue bit - * - * @note The red byte is the last byte in the color packet - * - * @param[in] led: The led index [0, @ref WS2812_LED_N) - * @param[in] bit: The bit index [0, 7] - * - * @return The bit index - */ -#define WS2812_BLUE_BIT(led, bit) WS2812_BIT((led), 2, (bit)) - -/* --- PRIVATE VARIABLES ---------------------------------------------------- */ - -static uint8_t ws2812_frame_buffer[WS2812_BIT_N]; /**< Buffer for a frame */ - -/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ - -void ws2812_init(void) -{ - // Initialize led frame buffer - uint32_t i; - for (i = 0; i < WS2812_COLOR_BIT_N; i++) ws2812_frame_buffer[i] = WS2812_DUTYCYCLE_0; // All color bits are zero duty cycle - for (i = 0; i < WS2812_RESET_BIT_N; i++) ws2812_frame_buffer[i + WS2812_COLOR_BIT_N] = 0; // All reset bits are zero - - // Configure PA1 as AF output -//#ifdef WS2812_EXTERNAL_PULLUP -// palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(WS2812_AF) | PAL_STM32_OTYPE_OPENDRAIN); -//#else - palSetPadMode(PORT_WS2812, PIN_WS2812, PAL_MODE_ALTERNATE(1)); -//#endif - - // PWM Configuration - #pragma GCC diagnostic ignored "-Woverride-init" // Turn off override-init warning for this struct. We use the overriding ability to set a "default" channel config - static const PWMConfig ws2812_pwm_config = { - .frequency = WS2812_PWM_FREQUENCY, - .period = WS2812_PWM_PERIOD, - .callback = NULL, - .channels = { - [0 ... 3] = {.mode = PWM_OUTPUT_DISABLED, .callback = NULL}, // Channels default to disabled - [WS2812_TIM_CH] = {.mode = PWM_OUTPUT_ACTIVE_HIGH, .callback = NULL}, // Turn on the channel we care about - }, - .cr2 = 0, - .dier = TIM_DIER_UDE, // DMA on update event for next period - }; - #pragma GCC diagnostic pop // Restore command-line warning options - - // Configure DMA - dmaStreamAllocate(WS2812_DMA_STREAM, 10, NULL, NULL); - dmaStreamSetPeripheral(WS2812_DMA_STREAM, &(WS2812_PWMD.tim->CCR[WS2812_TIM_CH])); - dmaStreamSetMemory0(WS2812_DMA_STREAM, ws2812_frame_buffer); - dmaStreamSetTransactionSize(WS2812_DMA_STREAM, WS2812_BIT_N); - dmaStreamSetMode(WS2812_DMA_STREAM, - STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); - //STM32_DMA_CR_CHSEL(WS2812_DMA_CHANNEL) | STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_WORD | STM32_DMA_CR_MSIZE_WORD | - //STM32_DMA_CR_MINC | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); - - // Start DMA - dmaStreamEnable(WS2812_DMA_STREAM); - - // Configure PWM - // NOTE: It's required that preload be enabled on the timer channel CCR register. This is currently enabled in the - // ChibiOS driver code, so we don't have to do anything special to the timer. If we did, we'd have to start the timer, - // disable counting, enable the channel, and then make whatever configuration changes we need. - pwmStart(&WS2812_PWMD, &ws2812_pwm_config); - pwmEnableChannel(&WS2812_PWMD, WS2812_TIM_CH, 0); // Initial period is 0; output will be low until first duty cycle is DMA'd in +void setColor(uint8_t color, uint8_t *buf,uint32_t mask){ + int i; + for (i=0;i<8;i++){ + buf[i]=((color<= WS2812_LED_N) return WS2812_LED_INVALID; - - // Write color to frame buffer - uint32_t bit; - for (bit = 0; bit < 8; bit++) { - ws2812_frame_buffer[WS2812_RED_BIT(led_number, bit)] = ((r >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - ws2812_frame_buffer[WS2812_GREEN_BIT(led_number, bit)] = ((g >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - ws2812_frame_buffer[WS2812_BLUE_BIT(led_number, bit)] = ((b >> bit) & 0x01) ? WS2812_DUTYCYCLE_1 : WS2812_DUTYCYCLE_0; - } - - // Success - return WS2812_SUCCESS; +void setColorRGB(Color c, uint8_t *buf, uint32_t mask){ + setColor(c.G,buf, mask); + setColor(c.R,buf+8, mask); + setColor(c.B,buf+16, mask); } -/** @} addtogroup WS2812 */ +/** + * @brief Initialize Led Driver + * @details Initialize the Led Driver based on parameters. + * Following initialization, the frame buffer would automatically be + * exported to the supplied port and pins in the right timing to drive + * a chain of WS2812B controllers + * @note The function assumes the controller is running at 72Mhz + * @note Timing is critical for WS2812. While all timing is done in hardware + * need to verify memory bandwidth is not exhausted to avoid DMA delays + * + * @param[in] leds length of the LED chain controlled by each pin + * @param[in] port which port would be used for output + * @param[in] mask Which pins would be used for output, each pin is a full chain + * @param[out] o_fb initialized frame buffer + * + */ +void ledDriverInit(int leds, stm32_gpio_t *port, uint32_t mask, uint8_t **o_fb) { + sLeds=leds; + sPort=port; + sMask=mask; + palSetGroupMode(port, sMask, 0, PAL_MODE_OUTPUT_PUSHPULL|PAL_STM32_OSPEED_HIGHEST|PAL_STM32_PUPDR_FLOATING); + + // configure pwm timers - + // timer 2 as master, active for data transmission and inactive to disable transmission during reset period (50uS) + // timer 3 as slave, during active time creates a 1.25 uS signal, with duty cycle controlled by frame buffer values + static PWMConfig pwmc2 = {72000000 / 90, /* 800Khz PWM clock frequency. 1/90 of PWMC3 */ + (72000000 / 90) * 0.05, /*Total period is 50ms (20FPS), including sLeds cycles + reset length for ws2812b and FB writes */ + NULL, + { {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL}, + {PWM_OUTPUT_DISABLED, NULL}}, + TIM_CR2_MMS_2, /* master mode selection */ + 0, }; + /* master mode selection */ + static PWMConfig pwmc3 = {72000000,/* 72Mhz PWM clock frequency. */ + 90, /* 90 cycles period (1.25 uS per period @72Mhz */ + NULL, + { {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL}, + {PWM_OUTPUT_ACTIVE_HIGH, NULL}}, + 0, + 0, + }; + dma_source = chHeapAlloc(NULL, 1); + fb = chHeapAlloc(NULL, ((sLeds) * 24)+10); + *o_fb=fb; + int j; + for (j = 0; j < (sLeds) * 24; j++) fb[j] = 0; + dma_source[0] = sMask; + // DMA stream 2, triggered by channel3 pwm signal. if FB indicates, reset output value early to indicate "0" bit to ws2812 + dmaStreamAllocate(STM32_DMA1_STREAM2, 10, NULL, NULL); + dmaStreamSetPeripheral(STM32_DMA1_STREAM2, &(sPort->BSRR.H.clear)); + dmaStreamSetMemory0(STM32_DMA1_STREAM2, fb); + dmaStreamSetTransactionSize(STM32_DMA1_STREAM2, (sLeds) * 24); + dmaStreamSetMode( + STM32_DMA1_STREAM2, + STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_MINC | STM32_DMA_CR_PSIZE_BYTE + | STM32_DMA_CR_MSIZE_BYTE | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(2)); + // DMA stream 3, triggered by pwm update event. output high at beginning of signal + dmaStreamAllocate(STM32_DMA1_STREAM3, 10, NULL, NULL); + dmaStreamSetPeripheral(STM32_DMA1_STREAM3, &(sPort->BSRR.H.set)); + dmaStreamSetMemory0(STM32_DMA1_STREAM3, dma_source); + dmaStreamSetTransactionSize(STM32_DMA1_STREAM3, 1); + dmaStreamSetMode( + STM32_DMA1_STREAM3, STM32_DMA_CR_TEIE | + STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE + | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); + // DMA stream 6, triggered by channel1 update event. reset output value late to indicate "1" bit to ws2812. + // always triggers but no affect if dma stream 2 already change output value to 0 + dmaStreamAllocate(STM32_DMA1_STREAM6, 10, NULL, NULL); + dmaStreamSetPeripheral(STM32_DMA1_STREAM6, &(sPort->BSRR.H.clear)); + dmaStreamSetMemory0(STM32_DMA1_STREAM6, dma_source); + dmaStreamSetTransactionSize(STM32_DMA1_STREAM6, 1); + dmaStreamSetMode( + STM32_DMA1_STREAM6, + STM32_DMA_CR_DIR_M2P | STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE + | STM32_DMA_CR_CIRC | STM32_DMA_CR_PL(3)); + pwmStart(&PWMD2, &pwmc2); + pwmStart(&PWMD3, &pwmc3); + // set pwm3 as slave, triggerd by pwm2 oc1 event. disables pwmd2 for synchronization. + PWMD3.tim->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2 | TIM_SMCR_TS_0; + PWMD2.tim->CR1 &= ~TIM_CR1_CEN; + // set pwm values. + // 28 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.39 uS + pwmEnableChannel(&PWMD3, 2, 28); + // 58 (duty in ticks) / 90 (period in ticks) * 1.25uS (period in S) = 0.806 uS + pwmEnableChannel(&PWMD3, 0, 58); + // active during transfer of 90 cycles * sLeds * 24 bytes * 1/90 multiplier + pwmEnableChannel(&PWMD2, 0, 90 * sLeds * 24 / 90); + // stop and reset counters for synchronization + PWMD2.tim->CNT = 0; + // Slave (TIM3) needs to "update" immediately after master (TIM2) start in order to start in sync. + // this initial sync is crucial for the stability of the run + PWMD3.tim->CNT = 89; + PWMD3.tim->DIER |= TIM_DIER_CC3DE | TIM_DIER_CC1DE | TIM_DIER_UDE; + dmaStreamEnable(STM32_DMA1_STREAM3); + dmaStreamEnable(STM32_DMA1_STREAM6); + dmaStreamEnable(STM32_DMA1_STREAM2); + // all systems go! both timers and all channels are configured to resonate + // in complete sync without any need for CPU cycles (only DMA and timers) + // start pwm2 for system to start resonating + PWMD2.tim->CR1 |= TIM_CR1_CEN; +} + +void ledDriverWaitCycle(void){ + while (PWMD2.tim->CNT < 90 * sLeds * 24 / 90){chThdSleepMicroseconds(1);}; +} + +void testPatternFB(uint8_t *fb){ + int i; + Color tmpC = {rand()%256, rand()%256, rand()%256}; + for (i=0;i - * @brief Interface to WS2812 LED driver +/* + * LEDDriver.h * - * Copyright (C) 2016 Austin Glaser - * - * This software may be modified and distributed under the terms - * of the MIT license. See the LICENSE file for details. - * - * @todo Put in names and descriptions of variables which need to be defined to use this file + * Created on: Aug 26, 2013 + * Author: Omri Iluz */ #ifndef WS2812_H_ #define WS2812_H_ -/** - * @defgroup WS2812 WS2812 Driver - * @{ - * - * @brief DMA-based WS2812 LED driver - * - * A driver for WS2812 LEDs - */ - -/* --- PUBLIC DEPENDENCIES -------------------------------------------------- */ - -// Standard -#include +#include "hal.h" #include "rgblight_types.h" -/* --- PUBLIC CONSTANTS ----------------------------------------------------- */ +#define sign(x) (( x > 0 ) - ( x < 0 )) -/** - * @brief Return codes from ws2812 interface functions - */ -typedef enum { - WS2812_SUCCESS = 0x00, /**< Operation completeed successfully */ - WS2812_LED_INVALID, /**< Attempted to index an invalid LED (@ref WS2812_N_LEDS) */ - MAX_WS2812_ERR, /**< Total number of possible error codes */ - WS2812_ERR_INVALID /**< Invalid error value */ -} ws2812_err_t; +typedef struct Color Color; +struct Color { + uint8_t R; + uint8_t G; + uint8_t B; +}; -/* --- PUBLIC FUNCTIONS ----------------------------------------------------- */ - -/** - * @brief Initialize the driver - * - * After this function is called, all necessary background tasks will be started. - * The frame is initially dark. - */ -void ws2812_init(void); - -/** - * @brief Write the value of a single LED in the chain - * - * The color value is written to a frame buffer, and will not - * be updated until the next frame is written. Frames are written - * at the maximum possible speed -- the longest latency between a - * call to this function and the value being displayed is - * 1.25uS*(24*@ref WS2812_LED_N + 50) - * - * @param[in] led_number: The index of the LED to be written. Must be strictly less than - * @ref WS2812_N_LEDS - * @param[in] r: The red level of the LED - * @param[in] g: The green level of the LED - * @param[in] b: The blue level of the LED - * - * @retval WS2812_SUCCESS: The write was successful - * @retval WS2812_LED_INVALID: The write was to an invalid LED index - */ -ws2812_err_t ws2812_write_led(uint32_t led_number, uint8_t r, uint8_t g, uint8_t b); - -/** @} defgroup WS2812 */ +void ledDriverInit(int leds, stm32_gpio_t *port, uint32_t mask, uint8_t **o_fb); +void setColorRGB(Color c, uint8_t *buf, uint32_t mask); +void testPatternFB(uint8_t *fb); +void ledDriverWaitCycle(void); void ws2812_setleds(LED_TYPE *ledarray, uint16_t number_of_leds); void ws2812_setleds_rgbw(LED_TYPE *ledarray, uint16_t number_of_leds); -/** - * @brief Concatenates two symbols s1 and s2 exactly, without expanding either - * - * @param[in] s1: The first symbol to concatenate - * @param[in] s2: The second symbol to concatenate - * - * @return A single symbol containing s1 and s2 concatenated without expansion - */ -#define CONCAT_SYMBOLS(s1, s2) s1##s2 - -/** - * @brief Concatenate the symbols s1 and s2, expanding both of them - * - * This is important because simply applying s1##s2 doesn't expand them if they're - * preprocessor tokens themselves - * - * @param[in] s1: The first symbol to concatenate - * @param[in] s2: The second symbol to concatenate - * - * @return A single symbol containing s1 expanded followed by s2 expanded - */ -#define CONCAT_EXPANDED_SYMBOLS(s1, s2) CONCAT_SYMBOLS(s1, s2) - -#endif /* WS2812_H_ */ +#endif /* LEDDRIVER_H_ */ diff --git a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h index a748628abe..ec26557f3a 100644 --- a/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h +++ b/keyboards/planck/rev6/boards/GENERIC_STM32_F303XC/board.h @@ -277,7 +277,7 @@ PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) #define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ - PIN_OSPEED_VERYLOW(GPIOA_PIN1) | \ + PIN_OSPEED_HIGH(GPIOA_PIN1) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ @@ -293,7 +293,7 @@ PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ PIN_OSPEED_VERYLOW(GPIOA_PIN15)) #define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ - PIN_PUPDR_PULLUP(GPIOA_PIN1) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN1) | \ PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ diff --git a/keyboards/planck/rev6/mcuconf.h b/keyboards/planck/rev6/mcuconf.h index e2be2a62ac..2d27bee4e6 100644 --- a/keyboards/planck/rev6/mcuconf.h +++ b/keyboards/planck/rev6/mcuconf.h @@ -184,6 +184,7 @@ #define STM32_PWM_USE_ADVANCED FALSE #define STM32_PWM_USE_TIM1 FALSE #define STM32_PWM_USE_TIM2 TRUE +#define STM32_PWM_USE_TIM3 TRUE #define STM32_PWM_USE_TIM4 FALSE #define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_TIM1_IRQ_PRIORITY 7 @@ -224,7 +225,7 @@ * ST driver system settings. */ #define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 3 +#define STM32_ST_USE_TIMER 4 /* * UART driver system settings. diff --git a/keyboards/planck/rev6/rev6.c b/keyboards/planck/rev6/rev6.c index d53b2224a7..0011d3e789 100644 --- a/keyboards/planck/rev6/rev6.c +++ b/keyboards/planck/rev6/rev6.c @@ -16,21 +16,20 @@ #include "rev6.h" #include "rgblight.h" + uint8_t *o_fb; + void matrix_init_kb(void) { // rgblight_enable(); // rgblight_mode(1); // rgblight_setrgb(0xFF, 0xFF, 0xFF); - ws2812_init(); + + ledDriverInit(2, GPIOA, 0b00000010, &o_fb); + testPatternFB(o_fb); + matrix_init_user(); } void matrix_scan_kb(void) { matrix_scan_user(); - - int s = 0; - for (int n = 0; n < WS2812_LED_N; n++) { - int s0 = s + 10*n; - ws2812_write_led(n, s0%255, (s0+85)%255, (s0+170)%255); - } - s += 10; + testPatternFB(o_fb); } From 161c68b48ace5ca0bba5cc24f647a14e77800bd8 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 31 May 2018 00:27:55 -0400 Subject: [PATCH 35/59] update twi2c to do standard master stuff --- drivers/arm/is31fl3731.c | 242 +++++++++++++++++++++++++++++++ drivers/arm/is31fl3731.h | 214 +++++++++++++++++++++++++++ drivers/arm/twi2c.c | 33 +++-- drivers/arm/twi2c.h | 11 +- keyboards/_qmk_handwire/matrix.c | 2 +- lib/chibios | 2 +- 6 files changed, 489 insertions(+), 15 deletions(-) create mode 100644 drivers/arm/is31fl3731.c create mode 100644 drivers/arm/is31fl3731.h diff --git a/drivers/arm/is31fl3731.c b/drivers/arm/is31fl3731.c new file mode 100644 index 0000000000..f815ef94c5 --- /dev/null +++ b/drivers/arm/is31fl3731.c @@ -0,0 +1,242 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "is31fl3731.h" +#include +#include +#include "twi2c.h" +#include "progmem.h" + +// This is a 7-bit address, that gets left-shifted and bit 0 +// set to 0 for write, 1 for read (as per I2C protocol) +// The address will vary depending on your wiring: +// 0b1110100 AD <-> GND +// 0b1110111 AD <-> VCC +// 0b1110101 AD <-> SCL +// 0b1110110 AD <-> SDA +#define ISSI_ADDR_DEFAULT 0x74 + +#define ISSI_REG_CONFIG 0x00 +#define ISSI_REG_CONFIG_PICTUREMODE 0x00 +#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08 +#define ISSI_REG_CONFIG_AUDIOPLAYMODE 0x18 + +#define ISSI_CONF_PICTUREMODE 0x00 +#define ISSI_CONF_AUTOFRAMEMODE 0x04 +#define ISSI_CONF_AUDIOMODE 0x08 + +#define ISSI_REG_PICTUREFRAME 0x01 + +#define ISSI_REG_SHUTDOWN 0x0A +#define ISSI_REG_AUDIOSYNC 0x06 + +#define ISSI_COMMANDREGISTER 0xFD +#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' + +// Transfer buffer for TWITransmitData() +uint8_t g_twi_transfer_buffer[20]; + +// These buffers match the IS31FL3731 PWM registers 0x24-0xB3. +// Storing them like this is optimal for I2C transfers to the registers. +// We could optimize this and take out the unused registers from these +// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's +// probably not worth the extra complexity. +uint8_t g_pwm_buffer[DRIVER_COUNT][144]; +bool g_pwm_buffer_update_required = false; + +uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } }; +bool g_led_control_registers_update_required = false; + +// This is the bit pattern in the LED control registers +// (for matrix A, add one to register for matrix B) +// +// reg - b7 b6 b5 b4 b3 b2 b1 b0 +// 0x00 - R08,R07,R06,R05,R04,R03,R02,R01 +// 0x02 - G08,G07,G06,G05,G04,G03,G02,R00 +// 0x04 - B08,B07,B06,B05,B04,B03,G01,G00 +// 0x06 - - , - , - , - , - ,B02,B01,B00 +// 0x08 - - , - , - , - , - , - , - , - +// 0x0A - B17,B16,B15, - , - , - , - , - +// 0x0C - G17,G16,B14,B13,B12,B11,B10,B09 +// 0x0E - R17,G15,G14,G13,G12,G11,G10,G09 +// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09 + + +void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) +{ + g_twi_transfer_buffer[0] = reg; + g_twi_transfer_buffer[1] = data; + + //Transmit data until succesful + while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0); +} + +void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) +{ + // assumes bank is already selected + + // transmit PWM registers in 9 transfers of 16 bytes + // g_twi_transfer_buffer[] is 20 bytes + + // iterate over the pwm_buffer contents at 16 byte intervals + for ( int i = 0; i < 144; i += 16 ) + { + // set the first register, e.g. 0x24, 0x34, 0x44, etc. + g_twi_transfer_buffer[0] = 0x24 + i; + // copy the data from i to i+15 + // device will auto-increment register for data after the first byte + // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer + for ( int j = 0; j < 16; j++ ) + { + g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; + } + + //Transmit buffer until succesful + while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); + } +} + +void IS31FL3731_init( uint8_t addr ) +{ + // In order to avoid the LEDs being driven with garbage data + // in the LED driver's PWM registers, first enable software shutdown, + // then set up the mode and other settings, clear the PWM registers, + // then disable software shutdown. + + // select "function register" bank + IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG ); + + // enable software shutdown + IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 ); + // this delay was copied from other drivers, might not be needed + _delay_ms( 10 ); + + // picture mode + IS31FL3731_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE ); + // display frame 0 + IS31FL3731_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 ); + // audio sync off + IS31FL3731_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 ); + + // select bank 0 + IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 ); + + // turn off all LEDs in the LED control register + for ( int i = 0x00; i <= 0x11; i++ ) + { + IS31FL3731_write_register( addr, i, 0x00 ); + } + + // turn off all LEDs in the blink control register (not really needed) + for ( int i = 0x12; i <= 0x23; i++ ) + { + IS31FL3731_write_register( addr, i, 0x00 ); + } + + // set PWM on all LEDs to 0 + for ( int i = 0x24; i <= 0xB3; i++ ) + { + IS31FL3731_write_register( addr, i, 0x00 ); + } + + // select "function register" bank + IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG ); + + // disable software shutdown + IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 ); + + // select bank 0 and leave it selected. + // most usage after initialization is just writing PWM buffers in bank 0 + // as there's not much point in double-buffering + IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 ); +} + +void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) +{ + if ( index >= 0 && index < DRIVER_LED_TOTAL ) { + is31_led led = g_is31_leds[index]; + + // Subtract 0x24 to get the second index of g_pwm_buffer + g_pwm_buffer[led.driver][led.r - 0x24] = red; + g_pwm_buffer[led.driver][led.g - 0x24] = green; + g_pwm_buffer[led.driver][led.b - 0x24] = blue; + g_pwm_buffer_update_required = true; + } +} + +void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) +{ + for ( int i = 0; i < DRIVER_LED_TOTAL; i++ ) + { + IS31FL3731_set_color( i, red, green, blue ); + } +} + +void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue ) +{ + is31_led led = g_is31_leds[index]; + + uint8_t control_register_r = (led.r - 0x24) / 8; + uint8_t control_register_g = (led.g - 0x24) / 8; + uint8_t control_register_b = (led.b - 0x24) / 8; + uint8_t bit_r = (led.r - 0x24) % 8; + uint8_t bit_g = (led.g - 0x24) % 8; + uint8_t bit_b = (led.b - 0x24) % 8; + + if ( red ) { + g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); + } else { + g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); + } + if ( green ) { + g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); + } else { + g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); + } + if ( blue ) { + g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); + } else { + g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); + } + + g_led_control_registers_update_required = true; + + +} + +void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ) +{ + if ( g_pwm_buffer_update_required ) + { + IS31FL3731_write_pwm_buffer( addr1, g_pwm_buffer[0] ); + IS31FL3731_write_pwm_buffer( addr2, g_pwm_buffer[1] ); + } + g_pwm_buffer_update_required = false; +} + +void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 ) +{ + if ( g_led_control_registers_update_required ) + { + for ( int i=0; i<18; i++ ) + { + IS31FL3731_write_register(addr1, i, g_led_control_registers[0][i] ); + IS31FL3731_write_register(addr2, i, g_led_control_registers[1][i] ); + } + } +} + diff --git a/drivers/arm/is31fl3731.h b/drivers/arm/is31fl3731.h new file mode 100644 index 0000000000..f354a12db2 --- /dev/null +++ b/drivers/arm/is31fl3731.h @@ -0,0 +1,214 @@ +/* Copyright 2017 Jason Williams + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + + +#ifndef IS31FL3731_DRIVER_H +#define IS31FL3731_DRIVER_H + +#include +#include + +typedef struct is31_led { + uint8_t driver:2; + uint8_t r; + uint8_t g; + uint8_t b; +} __attribute__((packed)) is31_led; + +extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; + +void IS31FL3731_init( uint8_t addr ); +void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ); +void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ); + +void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ); +void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue ); + +void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue ); + +// This should not be called from an interrupt +// (eg. from a timer interrupt). +// Call this while idle (in between matrix scans). +// If the buffer is dirty, it will update the driver with the buffer. +void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ); +void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 ); + +#define C1_1 0x24 +#define C1_2 0x25 +#define C1_3 0x26 +#define C1_4 0x27 +#define C1_5 0x28 +#define C1_6 0x29 +#define C1_7 0x2A +#define C1_8 0x2B + +#define C1_9 0x2C +#define C1_10 0x2D +#define C1_11 0x2E +#define C1_12 0x2F +#define C1_13 0x30 +#define C1_14 0x31 +#define C1_15 0x32 +#define C1_16 0x33 + +#define C2_1 0x34 +#define C2_2 0x35 +#define C2_3 0x36 +#define C2_4 0x37 +#define C2_5 0x38 +#define C2_6 0x39 +#define C2_7 0x3A +#define C2_8 0x3B + +#define C2_9 0x3C +#define C2_10 0x3D +#define C2_11 0x3E +#define C2_12 0x3F +#define C2_13 0x40 +#define C2_14 0x41 +#define C2_15 0x42 +#define C2_16 0x43 + +#define C3_1 0x44 +#define C3_2 0x45 +#define C3_3 0x46 +#define C3_4 0x47 +#define C3_5 0x48 +#define C3_6 0x49 +#define C3_7 0x4A +#define C3_8 0x4B + +#define C3_9 0x4C +#define C3_10 0x4D +#define C3_11 0x4E +#define C3_12 0x4F +#define C3_13 0x50 +#define C3_14 0x51 +#define C3_15 0x52 +#define C3_16 0x53 + +#define C4_1 0x54 +#define C4_2 0x55 +#define C4_3 0x56 +#define C4_4 0x57 +#define C4_5 0x58 +#define C4_6 0x59 +#define C4_7 0x5A +#define C4_8 0x5B + +#define C4_9 0x5C +#define C4_10 0x5D +#define C4_11 0x5E +#define C4_12 0x5F +#define C4_13 0x60 +#define C4_14 0x61 +#define C4_15 0x62 +#define C4_16 0x63 + +#define C5_1 0x64 +#define C5_2 0x65 +#define C5_3 0x66 +#define C5_4 0x67 +#define C5_5 0x68 +#define C5_6 0x69 +#define C5_7 0x6A +#define C5_8 0x6B + +#define C5_9 0x6C +#define C5_10 0x6D +#define C5_11 0x6E +#define C5_12 0x6F +#define C5_13 0x70 +#define C5_14 0x71 +#define C5_15 0x72 +#define C5_16 0x73 + +#define C6_1 0x74 +#define C6_2 0x75 +#define C6_3 0x76 +#define C6_4 0x77 +#define C6_5 0x78 +#define C6_6 0x79 +#define C6_7 0x7A +#define C6_8 0x7B + +#define C6_9 0x7C +#define C6_10 0x7D +#define C6_11 0x7E +#define C6_12 0x7F +#define C6_13 0x80 +#define C6_14 0x81 +#define C6_15 0x82 +#define C6_16 0x83 + +#define C7_1 0x84 +#define C7_2 0x85 +#define C7_3 0x86 +#define C7_4 0x87 +#define C7_5 0x88 +#define C7_6 0x89 +#define C7_7 0x8A +#define C7_8 0x8B + +#define C7_9 0x8C +#define C7_10 0x8D +#define C7_11 0x8E +#define C7_12 0x8F +#define C7_13 0x90 +#define C7_14 0x91 +#define C7_15 0x92 +#define C7_16 0x93 + +#define C8_1 0x94 +#define C8_2 0x95 +#define C8_3 0x96 +#define C8_4 0x97 +#define C8_5 0x98 +#define C8_6 0x99 +#define C8_7 0x9A +#define C8_8 0x9B + +#define C8_9 0x9C +#define C8_10 0x9D +#define C8_11 0x9E +#define C8_12 0x9F +#define C8_13 0xA0 +#define C8_14 0xA1 +#define C8_15 0xA2 +#define C8_16 0xA3 + +#define C9_1 0xA4 +#define C9_2 0xA5 +#define C9_3 0xA6 +#define C9_4 0xA7 +#define C9_5 0xA8 +#define C9_6 0xA9 +#define C9_7 0xAA +#define C9_8 0xAB + +#define C9_9 0xAC +#define C9_10 0xAD +#define C9_11 0xAE +#define C9_12 0xAF +#define C9_13 0xB0 +#define C9_14 0xB1 +#define C9_15 0xB2 +#define C9_16 0xB3 + + + +#endif // IS31FL3731_DRIVER_H diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 7200d2db95..08d23b6160 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -39,7 +39,9 @@ I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; -static const I2CConfig slaveI2CConfig = { +static uint8_t twi2c_address; + +static const I2CConfig I2CConfig = { STM32_TIMINGR_PRESC(15U) | STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), @@ -166,15 +168,10 @@ void clearAfterSend(I2CDriver *i2cp) void twi2c_slave_init(void) { - palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time - chThdSleepMilliseconds(10); - - /* I2C1 SCL on PF1, SDA on PF0 */ - palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); - palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + twi2c_init(); - i2cStart(&I2C_DRIVER, &slaveI2CConfig); + i2cStart(&I2C_DRIVER, &I2CConfig); #if HAL_USE_I2C_SLAVE I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif @@ -201,19 +198,31 @@ void twi2c_slave_task(void) { } } -void twi2c_master_init(void) { +uint8_t twi2c_start(uint8_t address) { + twi2c_address = address; + i2cStart(&I2C_DRIVER, &I2CConfig); +} +void twi2c_init(void) { palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time chThdSleepMilliseconds(10); palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); - i2cStart(&I2C_DRIVER, &slaveI2CConfig); - // try high drive (from kiibohd) // I2C_DRIVER.i2c->C2 |= I2Cx_C2_HDRS; // try glitch fixing (from kiibohd) // I2C_DRIVER.i2c->FLT = 4; - +} + +uint8_t twi2c_write(uint8_t data) { + uint8_t buffer[1] = {0}; + return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, &data, 1, buffer, 1, MS2ST(100)); +} + +uint8_t twi2c_transmit(uint8_t address, uint8_t* data, uint16_t length) { + twi2c_address = address; + i2cStart(&I2C_DRIVER, &I2CConfig); + return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, data, length, buffer, 1, MS2ST(100)); } diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index bc7a064a58..0f46cf6e28 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -28,4 +28,13 @@ I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; void twi2c_slave_init(void); -void twi2c_master_init(void); +void twi2c_init(void); +uint8_t twi2c_start(uint8_t address); +uint8_t twi2c_write(uint8_t data); +uint8_t twi2c_read_ack(void); +uint8_t twi2c_read_nack(void); +uint8_t twi2c_transmit(uint8_t address, uint8_t* data, uint16_t length); +uint8_t twi2c_receive(uint8_t address, uint8_t* data, uint16_t length); +uint8_t twi2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); +uint8_t twi2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); +void twi2c_stop(void); diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/_qmk_handwire/matrix.c index 499c92f8ca..8999c1ee56 100644 --- a/keyboards/_qmk_handwire/matrix.c +++ b/keyboards/_qmk_handwire/matrix.c @@ -59,7 +59,7 @@ void matrix_init(void) { master = right_hand; if (master) { - twi2c_master_init(); + twi2c_init(); } else { twi2c_slave_init(); } diff --git a/lib/chibios b/lib/chibios index f9643c88ad..587968d6cb 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit f9643c88ad5cd0704d57bed83fe64f45b3e6be4e +Subproject commit 587968d6cbc2b0e1c7147540872f2a67e59ca18b From 874f5a5c076bd96fa97d7169187c50e13c065876 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 1 Jun 2018 11:31:29 -0400 Subject: [PATCH 36/59] mostly compiling --- common_features.mk | 2 +- drivers/arm/is31fl3731.c | 4 +- drivers/arm/twi2c.c | 18 +- drivers/arm/twi2c.h | 4 + keyboards/planck/light/light.c | 2 + keyboards/planck/light/{ => rev1}/config.h | 0 keyboards/planck/light/{ => rev1}/rules.mk | 0 .../rev2/boards/GENERIC_STM32_F303XC/board.c | 126 ++ .../rev2/boards/GENERIC_STM32_F303XC/board.h | 1187 +++++++++++++++++ .../rev2/boards/GENERIC_STM32_F303XC/board.mk | 5 + keyboards/planck/light/rev2/bootloader_defs.h | 7 + keyboards/planck/light/rev2/chconf.h | 520 ++++++++ keyboards/planck/light/rev2/config.h | 143 ++ keyboards/planck/light/rev2/halconf.h | 388 ++++++ keyboards/planck/light/rev2/matrix.c | 191 +++ keyboards/planck/light/rev2/mcuconf.h | 257 ++++ keyboards/planck/light/rev2/rev2.c | 24 + keyboards/planck/light/rev2/rev2.h | 21 + keyboards/planck/light/rev2/rules.mk | 56 + keyboards/planck/rev6/matrix.c | 7 +- 20 files changed, 2955 insertions(+), 7 deletions(-) rename keyboards/planck/light/{ => rev1}/config.h (100%) rename keyboards/planck/light/{ => rev1}/rules.mk (100%) create mode 100644 keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.c create mode 100644 keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.h create mode 100644 keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.mk create mode 100644 keyboards/planck/light/rev2/bootloader_defs.h create mode 100644 keyboards/planck/light/rev2/chconf.h create mode 100644 keyboards/planck/light/rev2/config.h create mode 100644 keyboards/planck/light/rev2/halconf.h create mode 100644 keyboards/planck/light/rev2/matrix.c create mode 100644 keyboards/planck/light/rev2/mcuconf.h create mode 100644 keyboards/planck/light/rev2/rev2.c create mode 100644 keyboards/planck/light/rev2/rev2.h create mode 100644 keyboards/planck/light/rev2/rules.mk diff --git a/common_features.mk b/common_features.mk index 6a09008ff2..c1f8421c88 100644 --- a/common_features.mk +++ b/common_features.mk @@ -123,7 +123,7 @@ endif ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) OPT_DEFS += -DRGB_MATRIX_ENABLE SRC += is31fl3731.c - SRC += i2c_master.c + SRC += twi2c.c SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/rgb_matrix.c CIE1931_CURVE = yes diff --git a/drivers/arm/is31fl3731.c b/drivers/arm/is31fl3731.c index f815ef94c5..4cf0c09f67 100644 --- a/drivers/arm/is31fl3731.c +++ b/drivers/arm/is31fl3731.c @@ -16,7 +16,7 @@ */ #include "is31fl3731.h" -#include +#include "wait.h" #include #include "twi2c.h" #include "progmem.h" @@ -123,7 +123,7 @@ void IS31FL3731_init( uint8_t addr ) // enable software shutdown IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 ); // this delay was copied from other drivers, might not be needed - _delay_ms( 10 ); + wait_ms( 10 ); // picture mode IS31FL3731_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE ); diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 08d23b6160..9a08213833 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -17,12 +17,15 @@ #include "twi2c.h" #include #include -#include "hal_i2cslave.h" #include "chprintf.h" #include "memstreams.h" #include "printf.h" #include "matrix.h" +#ifdef I2C_SLAVE_ENABLE + +#include "hal_i2cslave.h" + /** * I2C slave test routine. * @@ -39,6 +42,8 @@ I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; +#endif + static uint8_t twi2c_address; static const I2CConfig I2CConfig = { @@ -60,6 +65,9 @@ uint8_t txBody[MATRIX_ROWS/2]; /* Return message buffer f BaseSequentialStream *chp = NULL; // Used for serial logging + +#ifdef I2C_SLAVE_ENABLE + // Handler when something sent to us const I2CSlaveMsg echoRx = { @@ -102,6 +110,7 @@ I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ }; + /** * Track I2C errors */ @@ -131,6 +140,8 @@ extern void matrix_copy(matrix_row_t * copy); const char hexString[16] = "0123456789abcdef"; + + /** * Message processor - looks at received message, determines reply as quickly as possible * @@ -198,6 +209,8 @@ void twi2c_slave_task(void) { } } +#endif + uint8_t twi2c_start(uint8_t address) { twi2c_address = address; i2cStart(&I2C_DRIVER, &I2CConfig); @@ -216,8 +229,9 @@ void twi2c_init(void) { // I2C_DRIVER.i2c->FLT = 4; } +uint8_t buffer[1] = {0}; + uint8_t twi2c_write(uint8_t data) { - uint8_t buffer[1] = {0}; return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, &data, 1, buffer, 1, MS2ST(100)); } diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index 0f46cf6e28..57cc54070e 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -24,10 +24,14 @@ #define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ //#define myOtherI2Caddress 0x19 +#ifdef I2C_SLAVE_ENABLE + I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; void twi2c_slave_init(void); +#endif + void twi2c_init(void); uint8_t twi2c_start(uint8_t address); uint8_t twi2c_write(uint8_t data); diff --git a/keyboards/planck/light/light.c b/keyboards/planck/light/light.c index cef57c5e69..ccf75d50f2 100644 --- a/keyboards/planck/light/light.c +++ b/keyboards/planck/light/light.c @@ -140,8 +140,10 @@ const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = { void matrix_init_kb(void) { // Turn status LED on + #ifdef KEYBOARD_planck_light_rev1 DDRD |= (1<<6); PORTD |= (1<<6); + #endif matrix_init_user(); } diff --git a/keyboards/planck/light/config.h b/keyboards/planck/light/rev1/config.h similarity index 100% rename from keyboards/planck/light/config.h rename to keyboards/planck/light/rev1/config.h diff --git a/keyboards/planck/light/rules.mk b/keyboards/planck/light/rev1/rules.mk similarity index 100% rename from keyboards/planck/light/rules.mk rename to keyboards/planck/light/rev1/rules.mk diff --git a/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.c b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.c new file mode 100644 index 0000000000..4331155df4 --- /dev/null +++ b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.c @@ -0,0 +1,126 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +const PALConfig pal_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} +#endif +}; +#endif + +void enter_bootloader_mode_if_requested(void); + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + enter_bootloader_mode_if_requested(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.h b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.h new file mode 100644 index 0000000000..ec26557f3a --- /dev/null +++ b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.h @@ -0,0 +1,1187 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for Clueboard 60% Keyboard + */ + +/* + * Board identifier. + */ +#define BOARD_GENERIC_STM32_F303XC +#define BOARD_NAME "Planck PCB" + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 0U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +// #define STM32_HSE_BYPASS + +/* + * MCU type as defined in the ST header. + */ +#define STM32F303xC + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_PIN1 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_PIN4 4U +#define GPIOA_PIN5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_PIN8 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_I2C2_SDA 0U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_PIN0 0U +#define GPIOH_PIN1 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_L3GD20_SDI PAL_LINE(GPIOA, 7U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_PIN6 PAL_LINE(GPIOF, 0U) +#define LINE_PIN7 PAL_LINE(GPIOF, 1U) + +#define LINE_CAPS_LOCK PAL_LINE(GPIOB, 7U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - NC + * PA1 - NC + * PA2 - COL1 + * PA3 - COL2 + * PA4 - SPEAKER1 + * PA5 - SPEAKER2 + * PA6 - COL3 + * PA7 - COL8 + * PA8 - COL6 + * PA9 - COL7 + * PA10 - ROW5 + * PA11 - USB_DM (alternate 14). + * PA12 - USB_DP (alternate 14). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ROW4 + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_ALTERNATE(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_PIN2) | \ + PIN_MODE_INPUT(GPIOA_PIN3) | \ + PIN_MODE_INPUT(GPIOA_PIN4) | \ + PIN_MODE_INPUT(GPIOA_PIN5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ + PIN_OSPEED_HIGH(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_PIN2) | \ + PIN_ODR_HIGH(GPIOA_PIN3) | \ + PIN_ODR_HIGH(GPIOA_PIN4) | \ + PIN_ODR_HIGH(GPIOA_PIN5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \ + PIN_AFIO_AF(GPIOA_PIN1, 1) | \ + PIN_AFIO_AF(GPIOA_PIN2, 0) | \ + PIN_AFIO_AF(GPIOA_PIN3, 0) | \ + PIN_AFIO_AF(GPIOA_PIN4, 0) | \ + PIN_AFIO_AF(GPIOA_PIN5, 5) | \ + PIN_AFIO_AF(GPIOA_PIN6, 5) | \ + PIN_AFIO_AF(GPIOA_PIN7, 5)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 14) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 14) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - PIN3 (alternate 0). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - PIN6 LSM303DLHC_SCL (alternate 4). + * PB7 - PIN7 LSM303DLHC_SDA (alternate 4). + * PB8 - PIN8 (input pullup). + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN6) | \ + PIN_MODE_OUTPUT(GPIOB_PIN7) | \ + PIN_MODE_INPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ + PIN_OSPEED_HIGH(GPIOB_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN6) | \ + PIN_PUPDR_PULLDOWN(GPIOB_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_PIN3) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_HIGH(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_PIN6) | \ + PIN_ODR_LOW(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0) | \ + PIN_AFIO_AF(GPIOB_PIN6, 4) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input floating). + * PC15 - PIN15 (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD11 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 L3GD20_CS (output pushpull maximum). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (output pushpull maximum). + * PE9 - PIN9 (output pushpull maximum). + * PE10 - PIN10 (output pushpull maximum). + * PE11 - PIN11 (output pushpull maximum). + * PE12 - PIN12 (output pushpull maximum). + * PE13 - PIN13 (output pushpull maximum). + * PE14 - PIN14 (output pushpull maximum). + * PE15 - PIN15 (output pushpull maximum). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) |\ + PIN_MODE_OUTPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) |\ + PIN_MODE_INPUT(GPIOE_PIN5) |\ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_OUTPUT(GPIOE_PIN8) | \ + PIN_MODE_OUTPUT(GPIOE_PIN9) | \ + PIN_MODE_OUTPUT(GPIOE_PIN10) | \ + PIN_MODE_OUTPUT(GPIOE_PIN11) | \ + PIN_MODE_OUTPUT(GPIOE_PIN12) | \ + PIN_MODE_OUTPUT(GPIOE_PIN13) | \ + PIN_MODE_OUTPUT(GPIOE_PIN14) | \ + PIN_MODE_OUTPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN5) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN14) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_LOW(GPIOE_PIN8) | \ + PIN_ODR_LOW(GPIOE_PIN9) | \ + PIN_ODR_LOW(GPIOE_PIN10) | \ + PIN_ODR_LOW(GPIOE_PIN11) | \ + PIN_ODR_LOW(GPIOE_PIN12) | \ + PIN_ODR_LOW(GPIOE_PIN13) | \ + PIN_ODR_LOW(GPIOE_PIN14) | \ + PIN_ODR_LOW(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0) |\ + PIN_AFIO_AF(GPIOE_PIN3, 0) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0) |\ + PIN_AFIO_AF(GPIOE_PIN5, 0) |\ + PIN_AFIO_AF(GPIOE_PIN6, 0) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0)) + +/* + * GPIOF setup: + * + * PF0 - I2C2_SDA (input floating). + * PF1 - I2C2_SCL (input floating). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_I2C2_SDA) | \ + PIN_MODE_INPUT(GPIOF_I2C2_SCL) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) | \ + PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) | \ + PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_I2C2_SDA) | \ + PIN_ODR_HIGH(GPIOF_I2C2_SCL) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) | \ + PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0)) + +/* + * GPIOH setup: + * + * PH0 - PIN0 (input pullup). + * PH1 - PIN1 (input pullup). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_PIN0) | \ + PIN_MODE_INPUT(GPIOH_PIN1) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOH_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_PULLUP(GPIOH_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_PIN0) | \ + PIN_ODR_HIGH(GPIOH_PIN1) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_PIN0, 0) | \ + PIN_AFIO_AF(GPIOH_PIN1, 0) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0)) + + +/* + * USB bus activation macro, required by the USB driver. + */ +// #define usb_lld_connect_bus(usbp) +#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14))) +// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT) +/* + * USB bus de-activation macro, required by the USB driver. + */ +// #define usb_lld_disconnect_bus(usbp) +#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP) +// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.mk b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.mk new file mode 100644 index 0000000000..43377629a3 --- /dev/null +++ b/keyboards/planck/light/rev2/boards/GENERIC_STM32_F303XC/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC diff --git a/keyboards/planck/light/rev2/bootloader_defs.h b/keyboards/planck/light/rev2/bootloader_defs.h new file mode 100644 index 0000000000..3b0e9d20a6 --- /dev/null +++ b/keyboards/planck/light/rev2/bootloader_defs.h @@ -0,0 +1,7 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/keyboards/planck/light/rev2/chconf.h b/keyboards/planck/light/rev2/chconf.h new file mode 100644 index 0000000000..b52ca7d2c8 --- /dev/null +++ b/keyboards/planck/light/rev2/chconf.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 16 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/keyboards/planck/light/rev2/config.h b/keyboards/planck/light/rev2/config.h new file mode 100644 index 0000000000..470aab1fae --- /dev/null +++ b/keyboards/planck/light/rev2/config.h @@ -0,0 +1,143 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef REV6_CONFIG_H +#define REV6_CONFIG_H + +/* USB Device descriptor parameter */ +#define DEVICE_VER 0x0006 + +#undef MATRIX_ROWS +#undef MATRIX_COLS +/* key matrix size */ +#define MATRIX_ROWS 8 +#define MATRIX_COLS 6 + +/* + * Keyboard Matrix Assignments + * + * Change this to how you wired your keyboard + * COLS: AVR pins used for columns, left to right + * ROWS: AVR pins used for rows, top to bottom + * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) + * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) + * +*/ +/* Note: These are not used for arm boards. They're here purely as documentation. + * #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 } + * #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 } + * #define UNUSED_PINS + */ + +#define MUSIC_MAP +#undef AUDIO_VOICES +#undef C6_AUDIO + +/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ +#define DEBOUNCE 6 + +/* Prevent modifiers from being stuck on after layer changes. */ +#define PREVENT_STUCK_MODIFIERS + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +//#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +//#define LOCKING_RESYNC_ENABLE + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +//#define FORCE_NKRO + +/* key combination for magic key command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +//#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 1 + +// This is a 7-bit address, that gets left-shifted and bit 0 +// set to 0 for write, 1 for read (as per I2C protocol) +// The address will vary depending on your wiring: +// 0b1110100 AD <-> GND +// 0b1110111 AD <-> VCC +// 0b1110101 AD <-> SCL +// 0b1110110 AD <-> SDA +#define DRIVER_ADDR_1 0b1110100 +#define DRIVER_ADDR_2 0b1110110 + +#define DRIVER_COUNT 2 +#define DRIVER_1_LED_TOTAL 25 +#define DRIVER_2_LED_TOTAL 24 +#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL + +#endif diff --git a/keyboards/planck/light/rev2/halconf.h b/keyboards/planck/light/rev2/halconf.h new file mode 100644 index 0000000000..a14ace02b4 --- /dev/null +++ b/keyboards/planck/light/rev2/halconf.h @@ -0,0 +1,388 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC TRUE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT TRUE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C TRUE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM TRUE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 1 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c new file mode 100644 index 0000000000..5b6b8ebe8a --- /dev/null +++ b/keyboards/planck/light/rev2/matrix.c @@ -0,0 +1,191 @@ +#include +#include +#include +#include "hal.h" +#include "timer.h" +#include "wait.h" +#include "printf.h" +#include "backlight.h" +#include "matrix.h" +#include "action.h" +#include "keycode.h" +#include + +/* + * col: { B11, B10, B2, B1, A7, B0 } + * row: { A10, A9, A8, B15, C13, C14, C15, A2 } + */ +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t matrix_debouncing[MATRIX_COLS]; +static bool debouncing = false; +static uint16_t debouncing_time = 0; + +static uint8_t encoder_state = 0; +static int8_t encoder_value = 0; +static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; + +__attribute__ ((weak)) +void matrix_init_user(void) {} + +__attribute__ ((weak)) +void matrix_scan_user(void) {} + +__attribute__ ((weak)) +void matrix_init_kb(void) { + matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void matrix_init(void) { + printf("matrix init\n"); + //debug_matrix = true; + + // dip switch setup + palSetPadMode(GPIOB, 14, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP); + + // encoder setup + palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); + palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); + + encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); + + // actual matrix setup + palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); + + palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN); + + + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); + + + matrix_init_quantum(); +} + +__attribute__ ((weak)) +void encoder_update(bool clockwise) { } + +#ifndef ENCODER_RESOLUTION + #define ENCODER_RESOLUTION 4 +#endif + +#define COUNTRECLOCKWISE 0 +#define CLOCKWISE 1 + +uint8_t matrix_scan(void) { + + // encoder on B12 and B13 + encoder_state <<= 2; + encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); + encoder_value += encoder_LUT[encoder_state & 0xF]; + if (encoder_value >= ENCODER_RESOLUTION) { + encoder_update(COUNTRECLOCKWISE); + } + if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + encoder_update(CLOCKWISE); + } + encoder_value %= ENCODER_RESOLUTION; + + // actual matrix + for (int col = 0; col < MATRIX_COLS; col++) { + matrix_row_t data = 0; + + // strobe col { B11, B10, B2, B1, A7, B0 } + switch (col) { + case 0: palSetPad(GPIOB, 11); break; + case 1: palSetPad(GPIOB, 10); break; + case 2: palSetPad(GPIOB, 2); break; + case 3: palSetPad(GPIOB, 1); break; + case 4: palSetPad(GPIOA, 7); break; + case 5: palSetPad(GPIOB, 0); break; + } + + // need wait to settle pin state + wait_us(20); + + // read row data { A10, A9, A8, B15, C13, C14, C15, A2 } + data = ( + (palReadPad(GPIOA, 10) << 0 ) | + (palReadPad(GPIOA, 9) << 1 ) | + (palReadPad(GPIOA, 8) << 2 ) | + (palReadPad(GPIOB, 15) << 3 ) | + (palReadPad(GPIOC, 13) << 4 ) | + (palReadPad(GPIOC, 14) << 5 ) | + (palReadPad(GPIOC, 15) << 6 ) | + (palReadPad(GPIOA, 2) << 7 ) + ); + + // unstrobe col { B11, B10, B2, B1, A7, B0 } + switch (col) { + case 0: palClearPad(GPIOB, 11); break; + case 1: palClearPad(GPIOB, 10); break; + case 2: palClearPad(GPIOB, 2); break; + case 3: palClearPad(GPIOB, 1); break; + case 4: palClearPad(GPIOA, 7); break; + case 5: palClearPad(GPIOB, 0); break; + } + + if (matrix_debouncing[col] != data) { + matrix_debouncing[col] = data; + debouncing = true; + debouncing_time = timer_read(); + } + } + + if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + for (int row = 0; row < MATRIX_ROWS; row++) { + matrix[row] = 0; + for (int col = 0; col < MATRIX_COLS; col++) { + matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); + } + } + debouncing = false; + } + + matrix_scan_quantum(); + + return 1; +} + +bool matrix_is_on(uint8_t row, uint8_t col) { + return (matrix[row] & (1< + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "rev2.h" + +void matrix_init_kb(void) { + matrix_init_user(); +} + +void matrix_scan_kb(void) { + matrix_scan_user(); +} diff --git a/keyboards/planck/light/rev2/rev2.h b/keyboards/planck/light/rev2/rev2.h new file mode 100644 index 0000000000..d9354d9755 --- /dev/null +++ b/keyboards/planck/light/rev2/rev2.h @@ -0,0 +1,21 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#ifndef REV2_H +#define REV2_H + +#include QMK_KEYBOARD_H + +#endif diff --git a/keyboards/planck/light/rev2/rules.mk b/keyboards/planck/light/rev2/rules.mk new file mode 100644 index 0000000000..f037375bc1 --- /dev/null +++ b/keyboards/planck/light/rev2/rules.mk @@ -0,0 +1,56 @@ +# project specific files +SRC = matrix.c +LAYOUTS += ortho_4x12 + +## chip/board settings +# - the next two should match the directories in +# /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F3xx + +# Linker script to use +# - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT = STM32F303xC + +# Startup code to use +# - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f3xx + +# Board: it should exist either in /os/hal/boards/ +# or /boards +BOARD = GENERIC_STM32_F303XC + +# Cortex version +MCU = cortex-m4 + +# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +ARMV = 7 + +USE_FPU = yes + +# Vector table for application +# 0x00000000-0x00001000 area is occupied by bootlaoder.*/ +# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB +# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000 +OPT_DEFS = + +# Options to pass to dfu-util when flashing +DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave + +# Build Options +# comment out to disable the options. +# +BACKLIGHT_ENABLE = no +BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration +## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.) +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +CONSOLE_ENABLE = yes # Console for debug +COMMAND_ENABLE = yes # Commands for debug and configuration +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover +CUSTOM_MATRIX = yes # Custom matrix file +AUDIO_ENABLE = yes +RGB_MATRIX_ENABLE = yes +# SERIAL_LINK_ENABLE = yes diff --git a/keyboards/planck/rev6/matrix.c b/keyboards/planck/rev6/matrix.c index e4ebe48acc..2c5f906ac5 100644 --- a/keyboards/planck/rev6/matrix.c +++ b/keyboards/planck/rev6/matrix.c @@ -96,6 +96,9 @@ bool last_dip_switch[4] = {0}; #define ENCODER_RESOLUTION 4 #endif +#define COUNTRECLOCKWISE 0 +#define CLOCKWISE 1 + uint8_t matrix_scan(void) { // dip switch dip_switch[0] = !palReadPad(GPIOB, 14); @@ -113,10 +116,10 @@ uint8_t matrix_scan(void) { encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); encoder_value += encoder_LUT[encoder_state & 0xF]; if (encoder_value >= ENCODER_RESOLUTION) { - encoder_update(0); + encoder_update(COUNTRECLOCKWISE); } if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise - encoder_update(1); + encoder_update(CLOCKWISE); } encoder_value %= ENCODER_RESOLUTION; From 274283420df035618cc2cb51118015778ac97944 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 1 Jun 2018 14:33:13 -0400 Subject: [PATCH 37/59] rev2 working --- drivers/arm/is31fl3731.c | 6 +- drivers/arm/twi2c.c | 24 ++++---- keyboards/planck/light/rev2/chconf.h | 2 +- keyboards/planck/light/rev2/config.h | 10 ++- keyboards/planck/light/rev2/halconf.h | 2 +- keyboards/planck/light/rev2/matrix.c | 88 ++++++++++++++------------- keyboards/planck/light/rev2/mcuconf.h | 6 +- keyboards/planck/light/rev2/rev2.c | 8 --- keyboards/planck/planck.h | 2 +- quantum/quantum.h | 7 ++- quantum/rgb_matrix.c | 16 ++--- 11 files changed, 88 insertions(+), 83 deletions(-) diff --git a/drivers/arm/is31fl3731.c b/drivers/arm/is31fl3731.c index 4cf0c09f67..a6e02db1b3 100644 --- a/drivers/arm/is31fl3731.c +++ b/drivers/arm/is31fl3731.c @@ -82,7 +82,8 @@ void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) g_twi_transfer_buffer[1] = data; //Transmit data until succesful - while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0); + //while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0); + twi2c_transmit(addr << 1, g_twi_transfer_buffer,2); } void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) @@ -106,7 +107,8 @@ void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) } //Transmit buffer until succesful - while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); + //while(twi2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); + twi2c_transmit(addr << 1, g_twi_transfer_buffer,17); } } diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 9a08213833..53af437bc2 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -46,13 +46,12 @@ I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; static uint8_t twi2c_address; -static const I2CConfig I2CConfig = { +static const I2CConfig i2cconfig = { STM32_TIMINGR_PRESC(15U) | STM32_TIMINGR_SCLDEL(4U) | STM32_TIMINGR_SDADEL(2U) | STM32_TIMINGR_SCLH(15U) | STM32_TIMINGR_SCLL(21U), 0, - 0, - NULL + 0 }; char initialReplyBody[50] = "Initial reply"; // 'Status' response if read without preceding write @@ -182,7 +181,7 @@ void twi2c_slave_init(void) { twi2c_init(); - i2cStart(&I2C_DRIVER, &I2CConfig); + i2cStart(&I2C_DRIVER, &i2cconfig); #if HAL_USE_I2C_SLAVE I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message #endif @@ -213,15 +212,16 @@ void twi2c_slave_task(void) { uint8_t twi2c_start(uint8_t address) { twi2c_address = address; - i2cStart(&I2C_DRIVER, &I2CConfig); + i2cStart(&I2C_DRIVER, &i2cconfig); + return 0; } void twi2c_init(void) { - palSetGroupMode(GPIOB,8,9, PAL_MODE_INPUT); // Try releasing special pins for a short time + palSetGroupMode(GPIOB,6,7, PAL_MODE_INPUT); // Try releasing special pins for a short time chThdSleepMilliseconds(10); - palSetPadMode(GPIOB, 9, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); - palSetPadMode(GPIOB, 8, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + palSetPadMode(GPIOB, 6, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); + palSetPadMode(GPIOB, 7, PAL_MODE_ALTERNATE(4) | PAL_STM32_OTYPE_OPENDRAIN | PAL_STM32_PUPDR_PULLUP); // try high drive (from kiibohd) // I2C_DRIVER.i2c->C2 |= I2Cx_C2_HDRS; @@ -229,14 +229,12 @@ void twi2c_init(void) { // I2C_DRIVER.i2c->FLT = 4; } -uint8_t buffer[1] = {0}; - uint8_t twi2c_write(uint8_t data) { - return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, &data, 1, buffer, 1, MS2ST(100)); + return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, &data, 1, 0, 0, MS2ST(100)); } uint8_t twi2c_transmit(uint8_t address, uint8_t* data, uint16_t length) { twi2c_address = address; - i2cStart(&I2C_DRIVER, &I2CConfig); - return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, data, length, buffer, 1, MS2ST(100)); + i2cStart(&I2C_DRIVER, &i2cconfig); + return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, data, length, 0, 0, MS2ST(100)); } diff --git a/keyboards/planck/light/rev2/chconf.h b/keyboards/planck/light/rev2/chconf.h index b52ca7d2c8..5a9b833107 100644 --- a/keyboards/planck/light/rev2/chconf.h +++ b/keyboards/planck/light/rev2/chconf.h @@ -41,7 +41,7 @@ * @brief System time counter resolution. * @note Allowed values are 16 or 32 bits. */ -#define CH_CFG_ST_RESOLUTION 16 +#define CH_CFG_ST_RESOLUTION 32 /** * @brief System tick frequency. diff --git a/keyboards/planck/light/rev2/config.h b/keyboards/planck/light/rev2/config.h index 470aab1fae..40cf3997d2 100644 --- a/keyboards/planck/light/rev2/config.h +++ b/keyboards/planck/light/rev2/config.h @@ -19,13 +19,17 @@ #define REV6_CONFIG_H /* USB Device descriptor parameter */ -#define DEVICE_VER 0x0006 +#undef PRODUCT +#define PRODUCT Planck Light +#undef PRODUCT_ID +#define PRODUCT_ID 0x6065 +#define DEVICE_VER 0x0002 #undef MATRIX_ROWS #undef MATRIX_COLS /* key matrix size */ -#define MATRIX_ROWS 8 -#define MATRIX_COLS 6 +#define MATRIX_ROWS 4 +#define MATRIX_COLS 12 /* * Keyboard Matrix Assignments diff --git a/keyboards/planck/light/rev2/halconf.h b/keyboards/planck/light/rev2/halconf.h index a14ace02b4..c3e0cbb728 100644 --- a/keyboards/planck/light/rev2/halconf.h +++ b/keyboards/planck/light/rev2/halconf.h @@ -111,7 +111,7 @@ * @brief Enables the PWM subsystem. */ #if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) -#define HAL_USE_PWM TRUE +#define HAL_USE_PWM FALSE #endif /** diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c index 5b6b8ebe8a..953c1c2b66 100644 --- a/keyboards/planck/light/rev2/matrix.c +++ b/keyboards/planck/light/rev2/matrix.c @@ -12,8 +12,8 @@ #include /* - * col: { B11, B10, B2, B1, A7, B0 } - * row: { A10, A9, A8, B15, C13, C14, C15, A2 } + * col: { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } + * row: { B5, B10, A9, A8 } */ /* matrix state(1:on, 0:off) */ static matrix_row_t matrix[MATRIX_ROWS]; @@ -45,12 +45,6 @@ void matrix_init(void) { printf("matrix init\n"); //debug_matrix = true; - // dip switch setup - palSetPadMode(GPIOB, 14, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOA, 15, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOB, 9, PAL_MODE_INPUT_PULLUP); - // encoder setup palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); @@ -58,21 +52,23 @@ void matrix_init(void) { encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); // actual matrix setup - palSetPadMode(GPIOB, 11, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 10, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 10, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 15, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 0, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 1, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 2, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOC, 13, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 6, PAL_MODE_OUTPUT_PUSHPULL); palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); + palSetPadMode(GPIOA, 3, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 10, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 5, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOB, 10, PAL_MODE_INPUT_PULLDOWN); palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOB, 15, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOC, 13, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOC, 14, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOC, 15, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOA, 2, PAL_MODE_INPUT_PULLDOWN); + palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); @@ -110,39 +106,47 @@ uint8_t matrix_scan(void) { for (int col = 0; col < MATRIX_COLS; col++) { matrix_row_t data = 0; - // strobe col { B11, B10, B2, B1, A7, B0 } + // strobe col { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } switch (col) { - case 0: palSetPad(GPIOB, 11); break; - case 1: palSetPad(GPIOB, 10); break; - case 2: palSetPad(GPIOB, 2); break; - case 3: palSetPad(GPIOB, 1); break; - case 4: palSetPad(GPIOA, 7); break; - case 5: palSetPad(GPIOB, 0); break; + case 0: palSetPad(GPIOA, 10); break; + case 1: palSetPad(GPIOB, 2); break; + case 2: palSetPad(GPIOA, 15); break; + case 3: palSetPad(GPIOA, 0); break; + case 4: palSetPad(GPIOA, 1); break; + case 5: palSetPad(GPIOA, 2); break; + case 6: palSetPad(GPIOB, 0); break; + case 7: palSetPad(GPIOB, 1); break; + case 8: palSetPad(GPIOC, 13); break; + case 9: palSetPad(GPIOA, 6); break; + case 10: palSetPad(GPIOA, 7); break; + case 11: palSetPad(GPIOA, 3); break; } // need wait to settle pin state wait_us(20); - // read row data { A10, A9, A8, B15, C13, C14, C15, A2 } + // read row data { B5, B10, A9, A8 } data = ( - (palReadPad(GPIOA, 10) << 0 ) | - (palReadPad(GPIOA, 9) << 1 ) | - (palReadPad(GPIOA, 8) << 2 ) | - (palReadPad(GPIOB, 15) << 3 ) | - (palReadPad(GPIOC, 13) << 4 ) | - (palReadPad(GPIOC, 14) << 5 ) | - (palReadPad(GPIOC, 15) << 6 ) | - (palReadPad(GPIOA, 2) << 7 ) + (palReadPad(GPIOB, 5) << 0 ) | + (palReadPad(GPIOB, 10) << 1 ) | + (palReadPad(GPIOA, 9) << 2 ) | + (palReadPad(GPIOA, 8) << 3 ) ); // unstrobe col { B11, B10, B2, B1, A7, B0 } switch (col) { - case 0: palClearPad(GPIOB, 11); break; - case 1: palClearPad(GPIOB, 10); break; - case 2: palClearPad(GPIOB, 2); break; - case 3: palClearPad(GPIOB, 1); break; - case 4: palClearPad(GPIOA, 7); break; - case 5: palClearPad(GPIOB, 0); break; + case 0: palClearPad(GPIOA, 10); break; + case 1: palClearPad(GPIOB, 2); break; + case 2: palClearPad(GPIOA, 15); break; + case 3: palClearPad(GPIOA, 0); break; + case 4: palClearPad(GPIOA, 1); break; + case 5: palClearPad(GPIOA, 2); break; + case 6: palClearPad(GPIOB, 0); break; + case 7: palClearPad(GPIOB, 1); break; + case 8: palClearPad(GPIOC, 13); break; + case 9: palClearPad(GPIOA, 6); break; + case 10: palClearPad(GPIOA, 7); break; + case 11: palClearPad(GPIOA, 3); break; } if (matrix_debouncing[col] != data) { diff --git a/keyboards/planck/light/rev2/mcuconf.h b/keyboards/planck/light/rev2/mcuconf.h index 867a7984d5..1ef0a0b9eb 100644 --- a/keyboards/planck/light/rev2/mcuconf.h +++ b/keyboards/planck/light/rev2/mcuconf.h @@ -183,8 +183,8 @@ */ #define STM32_PWM_USE_ADVANCED FALSE #define STM32_PWM_USE_TIM1 FALSE -#define STM32_PWM_USE_TIM2 TRUE -#define STM32_PWM_USE_TIM3 TRUE +#define STM32_PWM_USE_TIM2 FALSE +#define STM32_PWM_USE_TIM3 FALSE #define STM32_PWM_USE_TIM4 FALSE #define STM32_PWM_USE_TIM8 FALSE #define STM32_PWM_TIM1_IRQ_PRIORITY 7 @@ -225,7 +225,7 @@ * ST driver system settings. */ #define STM32_ST_IRQ_PRIORITY 8 -#define STM32_ST_USE_TIMER 4 +#define STM32_ST_USE_TIMER 2 /* * UART driver system settings. diff --git a/keyboards/planck/light/rev2/rev2.c b/keyboards/planck/light/rev2/rev2.c index f431f2fe6f..0754aabeb3 100644 --- a/keyboards/planck/light/rev2/rev2.c +++ b/keyboards/planck/light/rev2/rev2.c @@ -14,11 +14,3 @@ * along with this program. If not, see . */ #include "rev2.h" - -void matrix_init_kb(void) { - matrix_init_user(); -} - -void matrix_scan_kb(void) { - matrix_scan_user(); -} diff --git a/keyboards/planck/planck.h b/keyboards/planck/planck.h index f0a12d9335..b1b60ab89b 100644 --- a/keyboards/planck/planck.h +++ b/keyboards/planck/planck.h @@ -3,7 +3,7 @@ #include "quantum.h" -#ifdef __AVR__ +#if defined(__AVR__) || defined (KEYBOARD_planck_light_rev2) #define LAYOUT_planck_mit( \ k00, k01, k02, k03, k04, k05, k06, k07, k08, k09, k0a, k0b, \ k10, k11, k12, k13, k14, k15, k16, k17, k18, k19, k1a, k1b, \ diff --git a/quantum/quantum.h b/quantum/quantum.h index 2958a0abd0..36eeedd494 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -27,7 +27,7 @@ #ifdef BACKLIGHT_ENABLE #include "backlight.h" #endif -#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE) +#if !defined(RGBLIGHT_ENABLE) && !defined(RGB_MATRIX_ENABLE) #include "rgb.h" #endif #ifdef RGBLIGHT_ENABLE @@ -121,6 +121,11 @@ extern uint32_t default_layer_state; #include "process_terminal_nop.h" #endif +#ifndef MIN + #define MAX(x, y) (((x) > (y)) ? (x) : (y)) + #define MIN(x, y) (((x) < (y)) ? (x) : (y)) +#endif + #define STRINGIZE(z) #z #define ADD_SLASH_X(y) STRINGIZE(\x ## y) #define SYMBOL_STR(x) ADD_SLASH_X(x) diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index 992ce99de9..d29a65b907 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -17,14 +17,14 @@ #include "rgb_matrix.h" -#include -#include "i2c_master.h" -#include -#include +//#include +#include "twi2c.h" +#include "wait.h" +//#include #include "progmem.h" #include "config.h" #include "eeprom.h" -#include "lufa.h" +//#include "lufa.h" #include rgb_config_t rgb_matrix_config; @@ -217,7 +217,7 @@ void rgb_matrix_single_LED_test(void) { } // All LEDs off -void rgb_matrix_all_off(void) { +void rgb_matrix_all_off(void) { rgb_matrix_set_color_all( 0, 0, 0 ); } @@ -243,7 +243,7 @@ void rgb_matrix_solid_reactive(void) { // alphas = color1, mods = color2 void rgb_matrix_alphas_mods(void) { - + RGB rgb1 = hsv_to_rgb( (HSV){ .h = rgb_matrix_config.hue, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val } ); RGB rgb2 = hsv_to_rgb( (HSV){ .h = (rgb_matrix_config.hue + 180) % 360, .s = rgb_matrix_config.sat, .v = rgb_matrix_config.val } ); @@ -723,7 +723,7 @@ void rgb_matrix_indicators_user(void) {} void rgb_matrix_init_drivers(void) { // Initialize TWI - i2c_init(); + twi2c_init(); IS31FL3731_init( DRIVER_ADDR_1 ); IS31FL3731_init( DRIVER_ADDR_2 ); From c1f6f1308bbc3c405e654a1d3ac1f068488fbd71 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 1 Jun 2018 16:37:15 -0400 Subject: [PATCH 38/59] move drivers around --- common_features.mk | 1 + drivers/avr/i2c_master.h | 22 --- drivers/avr/is31fl3731.c | 244 -------------------------- drivers/avr/is31fl3731.h | 214 ---------------------- drivers/avr/{i2c_master.c => twi2c.c} | 122 ++++++------- drivers/avr/twi2c.h | 22 +++ drivers/{arm => }/is31fl3731.c | 0 drivers/{arm => }/is31fl3731.h | 0 8 files changed, 84 insertions(+), 541 deletions(-) delete mode 100755 drivers/avr/i2c_master.h delete mode 100644 drivers/avr/is31fl3731.c delete mode 100644 drivers/avr/is31fl3731.h rename drivers/avr/{i2c_master.c => twi2c.c} (62%) mode change 100755 => 100644 create mode 100644 drivers/avr/twi2c.h rename drivers/{arm => }/is31fl3731.c (100%) rename drivers/{arm => }/is31fl3731.h (100%) diff --git a/common_features.mk b/common_features.mk index c1f8421c88..a4e744bdb7 100644 --- a/common_features.mk +++ b/common_features.mk @@ -20,6 +20,7 @@ SERIAL_SRC += $(wildcard $(SERIAL_PATH)/system/*.c) SERIAL_DEFS += -DSERIAL_LINK_ENABLE COMMON_VPATH += $(SERIAL_PATH) +COMMON_VPATH += $(DRIVER_PATH) ifeq ($(PLATFORM),AVR) COMMON_VPATH += $(DRIVER_PATH)/avr else diff --git a/drivers/avr/i2c_master.h b/drivers/avr/i2c_master.h deleted file mode 100755 index 2479d28d52..0000000000 --- a/drivers/avr/i2c_master.h +++ /dev/null @@ -1,22 +0,0 @@ -/* Library made by: g4lvanix - * Github repository: https://github.com/g4lvanix/I2C-master-lib - */ - -#ifndef I2C_MASTER_H -#define I2C_MASTER_H - -#define I2C_READ 0x01 -#define I2C_WRITE 0x00 - -void i2c_init(void); -uint8_t i2c_start(uint8_t address); -uint8_t i2c_write(uint8_t data); -uint8_t i2c_read_ack(void); -uint8_t i2c_read_nack(void); -uint8_t i2c_transmit(uint8_t address, uint8_t* data, uint16_t length); -uint8_t i2c_receive(uint8_t address, uint8_t* data, uint16_t length); -uint8_t i2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); -uint8_t i2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); -void i2c_stop(void); - -#endif // I2C_MASTER_H diff --git a/drivers/avr/is31fl3731.c b/drivers/avr/is31fl3731.c deleted file mode 100644 index c7a99e3a3d..0000000000 --- a/drivers/avr/is31fl3731.c +++ /dev/null @@ -1,244 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include "is31fl3731.h" -#include -#include -#include -#include -#include "i2c_master.h" -#include "progmem.h" - -// This is a 7-bit address, that gets left-shifted and bit 0 -// set to 0 for write, 1 for read (as per I2C protocol) -// The address will vary depending on your wiring: -// 0b1110100 AD <-> GND -// 0b1110111 AD <-> VCC -// 0b1110101 AD <-> SCL -// 0b1110110 AD <-> SDA -#define ISSI_ADDR_DEFAULT 0x74 - -#define ISSI_REG_CONFIG 0x00 -#define ISSI_REG_CONFIG_PICTUREMODE 0x00 -#define ISSI_REG_CONFIG_AUTOPLAYMODE 0x08 -#define ISSI_REG_CONFIG_AUDIOPLAYMODE 0x18 - -#define ISSI_CONF_PICTUREMODE 0x00 -#define ISSI_CONF_AUTOFRAMEMODE 0x04 -#define ISSI_CONF_AUDIOMODE 0x08 - -#define ISSI_REG_PICTUREFRAME 0x01 - -#define ISSI_REG_SHUTDOWN 0x0A -#define ISSI_REG_AUDIOSYNC 0x06 - -#define ISSI_COMMANDREGISTER 0xFD -#define ISSI_BANK_FUNCTIONREG 0x0B // helpfully called 'page nine' - -// Transfer buffer for TWITransmitData() -uint8_t g_twi_transfer_buffer[20]; - -// These buffers match the IS31FL3731 PWM registers 0x24-0xB3. -// Storing them like this is optimal for I2C transfers to the registers. -// We could optimize this and take out the unused registers from these -// buffers and the transfers in IS31FL3731_write_pwm_buffer() but it's -// probably not worth the extra complexity. -uint8_t g_pwm_buffer[DRIVER_COUNT][144]; -bool g_pwm_buffer_update_required = false; - -uint8_t g_led_control_registers[DRIVER_COUNT][18] = { { 0 }, { 0 } }; -bool g_led_control_registers_update_required = false; - -// This is the bit pattern in the LED control registers -// (for matrix A, add one to register for matrix B) -// -// reg - b7 b6 b5 b4 b3 b2 b1 b0 -// 0x00 - R08,R07,R06,R05,R04,R03,R02,R01 -// 0x02 - G08,G07,G06,G05,G04,G03,G02,R00 -// 0x04 - B08,B07,B06,B05,B04,B03,G01,G00 -// 0x06 - - , - , - , - , - ,B02,B01,B00 -// 0x08 - - , - , - , - , - , - , - , - -// 0x0A - B17,B16,B15, - , - , - , - , - -// 0x0C - G17,G16,B14,B13,B12,B11,B10,B09 -// 0x0E - R17,G15,G14,G13,G12,G11,G10,G09 -// 0x10 - R16,R15,R14,R13,R12,R11,R10,R09 - - -void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ) -{ - g_twi_transfer_buffer[0] = reg; - g_twi_transfer_buffer[1] = data; - - //Transmit data until succesful - while(i2c_transmit(addr << 1, g_twi_transfer_buffer,2) != 0); -} - -void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ) -{ - // assumes bank is already selected - - // transmit PWM registers in 9 transfers of 16 bytes - // g_twi_transfer_buffer[] is 20 bytes - - // iterate over the pwm_buffer contents at 16 byte intervals - for ( int i = 0; i < 144; i += 16 ) - { - // set the first register, e.g. 0x24, 0x34, 0x44, etc. - g_twi_transfer_buffer[0] = 0x24 + i; - // copy the data from i to i+15 - // device will auto-increment register for data after the first byte - // thus this sets registers 0x24-0x33, 0x34-0x43, etc. in one transfer - for ( int j = 0; j < 16; j++ ) - { - g_twi_transfer_buffer[1 + j] = pwm_buffer[i + j]; - } - - //Transmit buffer until succesful - while(i2c_transmit(addr << 1, g_twi_transfer_buffer,17) != 0); - } -} - -void IS31FL3731_init( uint8_t addr ) -{ - // In order to avoid the LEDs being driven with garbage data - // in the LED driver's PWM registers, first enable software shutdown, - // then set up the mode and other settings, clear the PWM registers, - // then disable software shutdown. - - // select "function register" bank - IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG ); - - // enable software shutdown - IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x00 ); - // this delay was copied from other drivers, might not be needed - _delay_ms( 10 ); - - // picture mode - IS31FL3731_write_register( addr, ISSI_REG_CONFIG, ISSI_REG_CONFIG_PICTUREMODE ); - // display frame 0 - IS31FL3731_write_register( addr, ISSI_REG_PICTUREFRAME, 0x00 ); - // audio sync off - IS31FL3731_write_register( addr, ISSI_REG_AUDIOSYNC, 0x00 ); - - // select bank 0 - IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 ); - - // turn off all LEDs in the LED control register - for ( int i = 0x00; i <= 0x11; i++ ) - { - IS31FL3731_write_register( addr, i, 0x00 ); - } - - // turn off all LEDs in the blink control register (not really needed) - for ( int i = 0x12; i <= 0x23; i++ ) - { - IS31FL3731_write_register( addr, i, 0x00 ); - } - - // set PWM on all LEDs to 0 - for ( int i = 0x24; i <= 0xB3; i++ ) - { - IS31FL3731_write_register( addr, i, 0x00 ); - } - - // select "function register" bank - IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, ISSI_BANK_FUNCTIONREG ); - - // disable software shutdown - IS31FL3731_write_register( addr, ISSI_REG_SHUTDOWN, 0x01 ); - - // select bank 0 and leave it selected. - // most usage after initialization is just writing PWM buffers in bank 0 - // as there's not much point in double-buffering - IS31FL3731_write_register( addr, ISSI_COMMANDREGISTER, 0 ); -} - -void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ) -{ - if ( index >= 0 && index < DRIVER_LED_TOTAL ) { - is31_led led = g_is31_leds[index]; - - // Subtract 0x24 to get the second index of g_pwm_buffer - g_pwm_buffer[led.driver][led.r - 0x24] = red; - g_pwm_buffer[led.driver][led.g - 0x24] = green; - g_pwm_buffer[led.driver][led.b - 0x24] = blue; - g_pwm_buffer_update_required = true; - } -} - -void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) -{ - for ( int i = 0; i < DRIVER_LED_TOTAL; i++ ) - { - IS31FL3731_set_color( i, red, green, blue ); - } -} - -void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue ) -{ - is31_led led = g_is31_leds[index]; - - uint8_t control_register_r = (led.r - 0x24) / 8; - uint8_t control_register_g = (led.g - 0x24) / 8; - uint8_t control_register_b = (led.b - 0x24) / 8; - uint8_t bit_r = (led.r - 0x24) % 8; - uint8_t bit_g = (led.g - 0x24) % 8; - uint8_t bit_b = (led.b - 0x24) % 8; - - if ( red ) { - g_led_control_registers[led.driver][control_register_r] |= (1 << bit_r); - } else { - g_led_control_registers[led.driver][control_register_r] &= ~(1 << bit_r); - } - if ( green ) { - g_led_control_registers[led.driver][control_register_g] |= (1 << bit_g); - } else { - g_led_control_registers[led.driver][control_register_g] &= ~(1 << bit_g); - } - if ( blue ) { - g_led_control_registers[led.driver][control_register_b] |= (1 << bit_b); - } else { - g_led_control_registers[led.driver][control_register_b] &= ~(1 << bit_b); - } - - g_led_control_registers_update_required = true; - - -} - -void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ) -{ - if ( g_pwm_buffer_update_required ) - { - IS31FL3731_write_pwm_buffer( addr1, g_pwm_buffer[0] ); - IS31FL3731_write_pwm_buffer( addr2, g_pwm_buffer[1] ); - } - g_pwm_buffer_update_required = false; -} - -void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 ) -{ - if ( g_led_control_registers_update_required ) - { - for ( int i=0; i<18; i++ ) - { - IS31FL3731_write_register(addr1, i, g_led_control_registers[0][i] ); - IS31FL3731_write_register(addr2, i, g_led_control_registers[1][i] ); - } - } -} - diff --git a/drivers/avr/is31fl3731.h b/drivers/avr/is31fl3731.h deleted file mode 100644 index 3d30fc67b7..0000000000 --- a/drivers/avr/is31fl3731.h +++ /dev/null @@ -1,214 +0,0 @@ -/* Copyright 2017 Jason Williams - * Copyright 2018 Jack Humbert - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - - -#ifndef IS31FL3731_DRIVER_H -#define IS31FL3731_DRIVER_H - -#include -#include - -typedef struct is31_led { - uint8_t driver:2; - uint8_t r; - uint8_t g; - uint8_t b; -} __attribute__((packed)) is31_led; - -extern const is31_led g_is31_leds[DRIVER_LED_TOTAL]; - -void IS31FL3731_init( uint8_t addr ); -void IS31FL3731_write_register( uint8_t addr, uint8_t reg, uint8_t data ); -void IS31FL3731_write_pwm_buffer( uint8_t addr, uint8_t *pwm_buffer ); - -void IS31FL3731_set_color( int index, uint8_t red, uint8_t green, uint8_t blue ); -void IS31FL3731_set_color_all( uint8_t red, uint8_t green, uint8_t blue ); - -void IS31FL3731_set_led_control_register( uint8_t index, bool red, bool green, bool blue ); - -// This should not be called from an interrupt -// (eg. from a timer interrupt). -// Call this while idle (in between matrix scans). -// If the buffer is dirty, it will update the driver with the buffer. -void IS31FL3731_update_pwm_buffers( uint8_t addr1, uint8_t addr2 ); -void IS31FL3731_update_led_control_registers( uint8_t addr1, uint8_t addr2 ); - -#define C1_1 0x24 -#define C1_2 0x25 -#define C1_3 0x26 -#define C1_4 0x27 -#define C1_5 0x28 -#define C1_6 0x29 -#define C1_7 0x2A -#define C1_8 0x2B - -#define C1_9 0x2C -#define C1_10 0x2D -#define C1_11 0x2E -#define C1_12 0x2F -#define C1_13 0x30 -#define C1_14 0x31 -#define C1_15 0x32 -#define C1_16 0x33 - -#define C2_1 0x34 -#define C2_2 0x35 -#define C2_3 0x36 -#define C2_4 0x37 -#define C2_5 0x38 -#define C2_6 0x39 -#define C2_7 0x3A -#define C2_8 0x3B - -#define C2_9 0x3C -#define C2_10 0x3D -#define C2_11 0x3E -#define C2_12 0x3F -#define C2_13 0x40 -#define C2_14 0x41 -#define C2_15 0x42 -#define C2_16 0x43 - -#define C3_1 0x44 -#define C3_2 0x45 -#define C3_3 0x46 -#define C3_4 0x47 -#define C3_5 0x48 -#define C3_6 0x49 -#define C3_7 0x4A -#define C3_8 0x4B - -#define C3_9 0x4C -#define C3_10 0x4D -#define C3_11 0x4E -#define C3_12 0x4F -#define C3_13 0x50 -#define C3_14 0x51 -#define C3_15 0x52 -#define C3_16 0x53 - -#define C4_1 0x54 -#define C4_2 0x55 -#define C4_3 0x56 -#define C4_4 0x57 -#define C4_5 0x58 -#define C4_6 0x59 -#define C4_7 0x5A -#define C4_8 0x5B - -#define C4_9 0x5C -#define C4_10 0x5D -#define C4_11 0x5E -#define C4_12 0x5F -#define C4_13 0x60 -#define C4_14 0x61 -#define C4_15 0x62 -#define C4_16 0x63 - -#define C5_1 0x64 -#define C5_2 0x65 -#define C5_3 0x66 -#define C5_4 0x67 -#define C5_5 0x68 -#define C5_6 0x69 -#define C5_7 0x6A -#define C5_8 0x6B - -#define C5_9 0x6C -#define C5_10 0x6D -#define C5_11 0x6E -#define C5_12 0x6F -#define C5_13 0x70 -#define C5_14 0x71 -#define C5_15 0x72 -#define C5_16 0x73 - -#define C6_1 0x74 -#define C6_2 0x75 -#define C6_3 0x76 -#define C6_4 0x77 -#define C6_5 0x78 -#define C6_6 0x79 -#define C6_7 0x7A -#define C6_8 0x7B - -#define C6_9 0x7C -#define C6_10 0x7D -#define C6_11 0x7E -#define C6_12 0x7F -#define C6_13 0x80 -#define C6_14 0x81 -#define C6_15 0x82 -#define C6_16 0x83 - -#define C7_1 0x84 -#define C7_2 0x85 -#define C7_3 0x86 -#define C7_4 0x87 -#define C7_5 0x88 -#define C7_6 0x89 -#define C7_7 0x8A -#define C7_8 0x8B - -#define C7_9 0x8C -#define C7_10 0x8D -#define C7_11 0x8E -#define C7_12 0x8F -#define C7_13 0x90 -#define C7_14 0x91 -#define C7_15 0x92 -#define C7_16 0x93 - -#define C8_1 0x94 -#define C8_2 0x95 -#define C8_3 0x96 -#define C8_4 0x97 -#define C8_5 0x98 -#define C8_6 0x99 -#define C8_7 0x9A -#define C8_8 0x9B - -#define C8_9 0x9C -#define C8_10 0x9D -#define C8_11 0x9E -#define C8_12 0x9F -#define C8_13 0xA0 -#define C8_14 0xA1 -#define C8_15 0xA2 -#define C8_16 0xA3 - -#define C9_1 0xA4 -#define C9_2 0xA5 -#define C9_3 0xA6 -#define C9_4 0xA7 -#define C9_5 0xA8 -#define C9_6 0xA9 -#define C9_7 0xAA -#define C9_8 0xAB - -#define C9_9 0xAC -#define C9_10 0xAD -#define C9_11 0xAE -#define C9_12 0xAF -#define C9_13 0xB0 -#define C9_14 0xB1 -#define C9_15 0xB2 -#define C9_16 0xB3 - - - -#endif // IS31FL3731_DRIVER_H diff --git a/drivers/avr/i2c_master.c b/drivers/avr/twi2c.c old mode 100755 new mode 100644 similarity index 62% rename from drivers/avr/i2c_master.c rename to drivers/avr/twi2c.c index f4a4bb7b0b..c7df719d37 --- a/drivers/avr/i2c_master.c +++ b/drivers/avr/twi2c.c @@ -5,44 +5,44 @@ #include #include -#include "i2c_master.h" +#include "twi2c.h" #define F_SCL 400000UL // SCL frequency #define Prescaler 1 #define TWBR_val ((((F_CPU / F_SCL) / Prescaler) - 16 ) / 2) -void i2c_init(void) +void twi2c_init(void) { TWBR = (uint8_t)TWBR_val; } -uint8_t i2c_start(uint8_t address) +uint8_t twi2c_start(uint8_t address) { // reset TWI control register TWCR = 0; - // transmit START condition + // transmit START condition TWCR = (1< Date: Sun, 3 Jun 2018 18:01:11 -0400 Subject: [PATCH 39/59] arm lines implemented --- keyboards/planck/light/rev2/config.h | 11 +-- keyboards/planck/light/rev2/matrix.c | 69 ++++------------- quantum/config_common.h | 109 +++++++++++++++++++++++++++ 3 files changed, 129 insertions(+), 60 deletions(-) diff --git a/keyboards/planck/light/rev2/config.h b/keyboards/planck/light/rev2/config.h index 40cf3997d2..ebfb1ddea5 100644 --- a/keyboards/planck/light/rev2/config.h +++ b/keyboards/planck/light/rev2/config.h @@ -18,6 +18,8 @@ #ifndef REV6_CONFIG_H #define REV6_CONFIG_H +#include "config_common.h" + /* USB Device descriptor parameter */ #undef PRODUCT #define PRODUCT Planck Light @@ -41,11 +43,10 @@ * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) * */ -/* Note: These are not used for arm boards. They're here purely as documentation. - * #define MATRIX_ROW_PINS { PB0, PB1, PB2, PA15, PA10 } - * #define MATRIX_COL_PINS { PA2, PA3, PA6, PB14, PB15, PA8, PA9, PA7, PB3, PB4, PC14, PC15, PC13, PB5, PB6 } - * #define UNUSED_PINS - */ +#undef MATRIX_ROW_PINS +#undef MATRIX_COL_PINS +#define MATRIX_ROW_PINS { B5, B10, A9, A8 } +#define MATRIX_COL_PINS { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } #define MUSIC_MAP #undef AUDIO_VOICES diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c index 953c1c2b66..0a0f84ece3 100644 --- a/keyboards/planck/light/rev2/matrix.c +++ b/keyboards/planck/light/rev2/matrix.c @@ -25,6 +25,9 @@ static uint8_t encoder_state = 0; static int8_t encoder_value = 0; static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; +static LINE_TYPE matrix_col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +static LINE_TYPE matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; + __attribute__ ((weak)) void matrix_init_user(void) {} @@ -52,29 +55,17 @@ void matrix_init(void) { encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); // actual matrix setup - palSetPadMode(GPIOA, 10, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 2, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 15, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 0, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 1, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 2, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 0, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOB, 1, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOC, 13, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 6, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 7, PAL_MODE_OUTPUT_PUSHPULL); - palSetPadMode(GPIOA, 3, PAL_MODE_OUTPUT_PUSHPULL); - - palSetPadMode(GPIOB, 5, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOB, 10, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOA, 9, PAL_MODE_INPUT_PULLDOWN); - palSetPadMode(GPIOA, 8, PAL_MODE_INPUT_PULLDOWN); + for (int i = 0; i < MATRIX_COLS; i++) { + setPadMode(matrix_col_pins[i], PAL_MODE_OUTPUT_PUSHPULL); + } + for (int i = 0; i < MATRIX_ROWS; i++) { + setPadMode(matrix_row_pins[i], PAL_MODE_INPUT_PULLDOWN); + } memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); - matrix_init_quantum(); } @@ -106,49 +97,17 @@ uint8_t matrix_scan(void) { for (int col = 0; col < MATRIX_COLS; col++) { matrix_row_t data = 0; - // strobe col { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } - switch (col) { - case 0: palSetPad(GPIOA, 10); break; - case 1: palSetPad(GPIOB, 2); break; - case 2: palSetPad(GPIOA, 15); break; - case 3: palSetPad(GPIOA, 0); break; - case 4: palSetPad(GPIOA, 1); break; - case 5: palSetPad(GPIOA, 2); break; - case 6: palSetPad(GPIOB, 0); break; - case 7: palSetPad(GPIOB, 1); break; - case 8: palSetPad(GPIOC, 13); break; - case 9: palSetPad(GPIOA, 6); break; - case 10: palSetPad(GPIOA, 7); break; - case 11: palSetPad(GPIOA, 3); break; - } + setPad(matrix_col_pins[col]); // need wait to settle pin state wait_us(20); - // read row data { B5, B10, A9, A8 } - data = ( - (palReadPad(GPIOB, 5) << 0 ) | - (palReadPad(GPIOB, 10) << 1 ) | - (palReadPad(GPIOA, 9) << 2 ) | - (palReadPad(GPIOA, 8) << 3 ) - ); - - // unstrobe col { B11, B10, B2, B1, A7, B0 } - switch (col) { - case 0: palClearPad(GPIOA, 10); break; - case 1: palClearPad(GPIOB, 2); break; - case 2: palClearPad(GPIOA, 15); break; - case 3: palClearPad(GPIOA, 0); break; - case 4: palClearPad(GPIOA, 1); break; - case 5: palClearPad(GPIOA, 2); break; - case 6: palClearPad(GPIOB, 0); break; - case 7: palClearPad(GPIOB, 1); break; - case 8: palClearPad(GPIOC, 13); break; - case 9: palClearPad(GPIOA, 6); break; - case 10: palClearPad(GPIOA, 7); break; - case 11: palClearPad(GPIOA, 3); break; + for (int row = 0; row < MATRIX_ROWS; row++) { + data |= (readPad(matrix_row_pins[row]) << row); } + clearPad(matrix_col_pins[col]); + if (matrix_debouncing[col] != data) { matrix_debouncing[col] = data; debouncing = true; diff --git a/quantum/config_common.h b/quantum/config_common.h index f6f51b367d..34cfefb088 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -23,6 +23,8 @@ #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ #ifdef __AVR__ + #define LINE_TYPE uint8_t + /* I/O pins */ #ifndef F0 #define B0 0x30 @@ -74,8 +76,115 @@ #define A6 0x06 #define A7 0x07 #endif +#else + #include "hal.h" + + #define LINE_TYPE ioline_t + + #define A0 PAL_LINE(GPIOA, 0) + #define A1 PAL_LINE(GPIOA, 1) + #define A2 PAL_LINE(GPIOA, 2) + #define A3 PAL_LINE(GPIOA, 3) + #define A4 PAL_LINE(GPIOA, 4) + #define A5 PAL_LINE(GPIOA, 5) + #define A6 PAL_LINE(GPIOA, 6) + #define A7 PAL_LINE(GPIOA, 7) + #define A8 PAL_LINE(GPIOA, 8) + #define A9 PAL_LINE(GPIOA, 9) + #define A10 PAL_LINE(GPIOA, 10) + #define A11 PAL_LINE(GPIOA, 11) + #define A12 PAL_LINE(GPIOA, 12) + #define A13 PAL_LINE(GPIOA, 13) + #define A14 PAL_LINE(GPIOA, 14) + #define A15 PAL_LINE(GPIOA, 15) + #define B0 PAL_LINE(GPIOB, 0) + #define B1 PAL_LINE(GPIOB, 1) + #define B2 PAL_LINE(GPIOB, 2) + #define B3 PAL_LINE(GPIOB, 3) + #define B4 PAL_LINE(GPIOB, 4) + #define B5 PAL_LINE(GPIOB, 5) + #define B6 PAL_LINE(GPIOB, 6) + #define B7 PAL_LINE(GPIOB, 7) + #define B8 PAL_LINE(GPIOB, 8) + #define B9 PAL_LINE(GPIOB, 9) + #define B10 PAL_LINE(GPIOB, 10) + #define B11 PAL_LINE(GPIOB, 11) + #define B12 PAL_LINE(GPIOB, 12) + #define B13 PAL_LINE(GPIOB, 13) + #define B14 PAL_LINE(GPIOB, 14) + #define B15 PAL_LINE(GPIOB, 15) + #define C0 PAL_LINE(GPIOC, 0) + #define C1 PAL_LINE(GPIOC, 1) + #define C2 PAL_LINE(GPIOC, 2) + #define C3 PAL_LINE(GPIOC, 3) + #define C4 PAL_LINE(GPIOC, 4) + #define C5 PAL_LINE(GPIOC, 5) + #define C6 PAL_LINE(GPIOC, 6) + #define C7 PAL_LINE(GPIOC, 7) + #define C8 PAL_LINE(GPIOC, 8) + #define C9 PAL_LINE(GPIOC, 9) + #define C10 PAL_LINE(GPIOC, 10) + #define C11 PAL_LINE(GPIOC, 11) + #define C12 PAL_LINE(GPIOC, 12) + #define C13 PAL_LINE(GPIOC, 13) + #define C14 PAL_LINE(GPIOC, 14) + #define C15 PAL_LINE(GPIOC, 15) + #define D0 PAL_LINE(GPIOD, 0) + #define D1 PAL_LINE(GPIOD, 1) + #define D2 PAL_LINE(GPIOD, 2) + #define D3 PAL_LINE(GPIOD, 3) + #define D4 PAL_LINE(GPIOD, 4) + #define D5 PAL_LINE(GPIOD, 5) + #define D6 PAL_LINE(GPIOD, 6) + #define D7 PAL_LINE(GPIOD, 7) + #define D8 PAL_LINE(GPIOD, 8) + #define D9 PAL_LINE(GPIOD, 9) + #define D10 PAL_LINE(GPIOD, 10) + #define D11 PAL_LINE(GPIOD, 11) + #define D12 PAL_LINE(GPIOD, 12) + #define D13 PAL_LINE(GPIOD, 13) + #define D14 PAL_LINE(GPIOD, 14) + #define D15 PAL_LINE(GPIOD, 15) + #define E0 PAL_LINE(GPIOE, 0) + #define E1 PAL_LINE(GPIOE, 1) + #define E2 PAL_LINE(GPIOE, 2) + #define E3 PAL_LINE(GPIOE, 3) + #define E4 PAL_LINE(GPIOE, 4) + #define E5 PAL_LINE(GPIOE, 5) + #define E6 PAL_LINE(GPIOE, 6) + #define E7 PAL_LINE(GPIOE, 7) + #define E8 PAL_LINE(GPIOE, 8) + #define E9 PAL_LINE(GPIOE, 9) + #define E10 PAL_LINE(GPIOE, 10) + #define E11 PAL_LINE(GPIOE, 11) + #define E12 PAL_LINE(GPIOE, 12) + #define E13 PAL_LINE(GPIOE, 13) + #define E14 PAL_LINE(GPIOE, 14) + #define E15 PAL_LINE(GPIOE, 15) + #define F0 PAL_LINE(GPIOF, 0) + #define F1 PAL_LINE(GPIOF, 1) + #define F2 PAL_LINE(GPIOF, 2) + #define F3 PAL_LINE(GPIOF, 3) + #define F4 PAL_LINE(GPIOF, 4) + #define F5 PAL_LINE(GPIOF, 5) + #define F6 PAL_LINE(GPIOF, 6) + #define F7 PAL_LINE(GPIOF, 7) + #define F8 PAL_LINE(GPIOF, 8) + #define F9 PAL_LINE(GPIOF, 9) + #define F10 PAL_LINE(GPIOF, 10) + #define F11 PAL_LINE(GPIOF, 11) + #define F12 PAL_LINE(GPIOF, 12) + #define F13 PAL_LINE(GPIOF, 13) + #define F14 PAL_LINE(GPIOF, 14) + #define F15 PAL_LINE(GPIOF, 15) + + #define setPadMode(line, mode) palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode) + #define setPad(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) + #define clearPad(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) + #define readPad(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) #endif + /* USART configuration */ #ifdef BLUETOOTH_ENABLE # ifdef __AVR_ATmega32U4__ From ff4a1ae5d203095dedc7a6a6cc9a06bebe2818ed Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 3 Jun 2018 21:55:07 -0400 Subject: [PATCH 40/59] inital encoder implementation --- common_features.mk | 6 +++ keyboards/planck/light/rev1/config.h | 3 ++ keyboards/planck/light/rev1/rules.mk | 3 +- keyboards/planck/light/rev2/config.h | 6 ++- keyboards/planck/light/rev2/matrix.c | 31 ------------- keyboards/planck/light/rev2/rules.mk | 1 + quantum/config_common.h | 14 +++++- quantum/encoder.c | 67 ++++++++++++++++++++++++++++ quantum/encoder.h | 27 +++++++++++ quantum/quantum.c | 7 +++ quantum/quantum.h | 4 ++ 11 files changed, 135 insertions(+), 34 deletions(-) create mode 100644 quantum/encoder.c create mode 100644 quantum/encoder.h diff --git a/common_features.mk b/common_features.mk index a4e744bdb7..a76c522bfc 100644 --- a/common_features.mk +++ b/common_features.mk @@ -209,6 +209,12 @@ ifeq ($(strip $(I2C_SLAVE_ENABLE)), yes) OPT_DEFS += -DI2C_SLAVE_ENABLE endif +ifeq ($(strip $(ENCODER_ENABLE)), yes) + OPT_DEFS += -DENCODER_ENABLE + SRC += $(QUANTUM_DIR)/encoder.c +endif + + QUANTUM_SRC:= \ $(QUANTUM_DIR)/quantum.c \ $(QUANTUM_DIR)/keymap_common.c \ diff --git a/keyboards/planck/light/rev1/config.h b/keyboards/planck/light/rev1/config.h index 17c015ed0f..b1f356c425 100644 --- a/keyboards/planck/light/rev1/config.h +++ b/keyboards/planck/light/rev1/config.h @@ -41,5 +41,8 @@ #define DRIVER_2_LED_TOTAL 24 #define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL +#define NUMBER_OF_ENCODERS 1 +#define ENCODERS_PAD_A { F6 } +#define ENCODERS_PAD_B { F7 } #endif diff --git a/keyboards/planck/light/rev1/rules.mk b/keyboards/planck/light/rev1/rules.mk index c10b8fd1da..4de2f21086 100644 --- a/keyboards/planck/light/rev1/rules.mk +++ b/keyboards/planck/light/rev1/rules.mk @@ -1,5 +1,6 @@ MIDI_ENABLE = yes AUDIO_ENABLE = yes # Audio output on port C6 RGB_MATRIX_ENABLE = yes +ENCODER_ENABLE = yes -MCU = at90usb1286 \ No newline at end of file +MCU = at90usb1286 diff --git a/keyboards/planck/light/rev2/config.h b/keyboards/planck/light/rev2/config.h index ebfb1ddea5..e8cf383c62 100644 --- a/keyboards/planck/light/rev2/config.h +++ b/keyboards/planck/light/rev2/config.h @@ -52,8 +52,12 @@ #undef AUDIO_VOICES #undef C6_AUDIO +#define NUMBER_OF_ENCODERS 1 +#define ENCODERS_PAD_A { B12 } +#define ENCODERS_PAD_B { B13 } + /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ -#define DEBOUNCE 6 +#define DEBOUNCE 0 /* Prevent modifiers from being stuck on after layer changes. */ #define PREVENT_STUCK_MODIFIERS diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c index 0a0f84ece3..0de8b20285 100644 --- a/keyboards/planck/light/rev2/matrix.c +++ b/keyboards/planck/light/rev2/matrix.c @@ -21,10 +21,6 @@ static matrix_row_t matrix_debouncing[MATRIX_COLS]; static bool debouncing = false; static uint16_t debouncing_time = 0; -static uint8_t encoder_state = 0; -static int8_t encoder_value = 0; -static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; - static LINE_TYPE matrix_col_pins[MATRIX_COLS] = MATRIX_COL_PINS; static LINE_TYPE matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; @@ -48,12 +44,6 @@ void matrix_init(void) { printf("matrix init\n"); //debug_matrix = true; - // encoder setup - palSetPadMode(GPIOB, 12, PAL_MODE_INPUT_PULLUP); - palSetPadMode(GPIOB, 13, PAL_MODE_INPUT_PULLUP); - - encoder_state = (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); - // actual matrix setup for (int i = 0; i < MATRIX_COLS; i++) { setPadMode(matrix_col_pins[i], PAL_MODE_OUTPUT_PUSHPULL); @@ -69,29 +59,8 @@ void matrix_init(void) { matrix_init_quantum(); } -__attribute__ ((weak)) -void encoder_update(bool clockwise) { } - -#ifndef ENCODER_RESOLUTION - #define ENCODER_RESOLUTION 4 -#endif - -#define COUNTRECLOCKWISE 0 -#define CLOCKWISE 1 - uint8_t matrix_scan(void) { - // encoder on B12 and B13 - encoder_state <<= 2; - encoder_state |= (palReadPad(GPIOB, 12) << 0) | (palReadPad(GPIOB, 13) << 1); - encoder_value += encoder_LUT[encoder_state & 0xF]; - if (encoder_value >= ENCODER_RESOLUTION) { - encoder_update(COUNTRECLOCKWISE); - } - if (encoder_value <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise - encoder_update(CLOCKWISE); - } - encoder_value %= ENCODER_RESOLUTION; // actual matrix for (int col = 0; col < MATRIX_COLS; col++) { diff --git a/keyboards/planck/light/rev2/rules.mk b/keyboards/planck/light/rev2/rules.mk index f037375bc1..4d90354c95 100644 --- a/keyboards/planck/light/rev2/rules.mk +++ b/keyboards/planck/light/rev2/rules.mk @@ -53,4 +53,5 @@ NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes RGB_MATRIX_ENABLE = yes +ENCODER_ENABLE = yes # SERIAL_LINK_ENABLE = yes diff --git a/quantum/config_common.h b/quantum/config_common.h index 34cfefb088..5de2d13993 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -1,4 +1,4 @@ -/* Copyright 2015-2017 Jack Humbert +/* Copyright 2015-2018 Jack Humbert * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -23,6 +23,7 @@ #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ #ifdef __AVR__ + #include #define LINE_TYPE uint8_t /* I/O pins */ @@ -76,6 +77,15 @@ #define A6 0x06 #define A7 0x07 #endif + + #define setPadMode(line, mode) _SFR_IO8((line >> 4) + 1) mode _BV(line & 0xF) + #define setPad(line) _SFR_IO8((line >> 4) + 2) |= _BV(line & 0xF) + #define clearPad(line) _SFR_IO8((line >> 4) + 2) &= ~_BV(line & 0xF) + #define readPad(line) (_SFR_IO8(line >> 4) & _BV(line & 0xF)) + + #define PAD_MODE_INPUT &= ~ + #define PAD_MODE_OUTPUT |= + #else #include "hal.h" @@ -182,6 +192,8 @@ #define setPad(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) #define clearPad(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) #define readPad(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) + + #define PAD_MODE_INPUT PAL_MODE_INPUT_PULLUP #endif diff --git a/quantum/encoder.c b/quantum/encoder.c new file mode 100644 index 0000000000..022cc1c01c --- /dev/null +++ b/quantum/encoder.c @@ -0,0 +1,67 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "encoder.h" +#include + +#ifndef ENCODER_RESOLUTION + #define ENCODER_RESOLUTION 4 +#endif + +#if !defined(ENCODERS_PAD_A) || !defined(ENCODERS_PAD_B) + #error "No encoder pads defined by ENCODERS_PAD_A and ENCODERS_PAD_B" +#endif + +static LINE_TYPE encoders_pad_a[NUMBER_OF_ENCODERS] = ENCODERS_PAD_A; +static LINE_TYPE encoders_pad_b[NUMBER_OF_ENCODERS] = ENCODERS_PAD_B; + +static int8_t encoder_LUT[] = { 0, -1, 1, 0, 1, 0, 0, -1, -1, 0, 0, 1, 0, 1, -1, 0 }; + +static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; +static int8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; + +__attribute__ ((weak)) +void encoder_update_user(bool clockwise) { } + +__attribute__ ((weak)) +void encoder_update_kb(bool clockwise) { + encoder_update_user(clockwise); +} + +void encoder_init(void) { + for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + setPadMode(encoders_pad_a[i], PAD_MODE_INPUT); + setPadMode(encoders_pad_b[i], PAD_MODE_INPUT); + + encoder_state[i] = (readPad(encoders_pad_a[i]) << 0) | (readPad(encoders_pad_b[i]) << 1); + } +} + +void encoder_read(void) { + for (int i = 0; i < NUMBER_OF_ENCODERS; i++) { + encoder_state[i] <<= 2; + encoder_state[i] |= (readPad(encoders_pad_a[i]) << 0) | (readPad(encoders_pad_b[i]) << 1); + encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF]; + if (encoder_value[i] >= ENCODER_RESOLUTION) { + encoder_update_kb(COUNTRECLOCKWISE); + } + if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise + encoder_update_kb(CLOCKWISE); + } + encoder_value[i] %= ENCODER_RESOLUTION; + } +} diff --git a/quantum/encoder.h b/quantum/encoder.h new file mode 100644 index 0000000000..bf2c73bc24 --- /dev/null +++ b/quantum/encoder.h @@ -0,0 +1,27 @@ +/* + * Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef ENCODER_H +#define ENCODER_H + +#define COUNTRECLOCKWISE 0 +#define CLOCKWISE 1 + +void encoder_init(void); +void encoder_read(void); + +#endif diff --git a/quantum/quantum.c b/quantum/quantum.c index f9b3e2197d..331ed5634c 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -851,6 +851,9 @@ void matrix_init_quantum() { #ifdef RGB_MATRIX_ENABLE rgb_matrix_init_drivers(); #endif + #ifdef ENCODER_ENABLE + encoder_init(); + #endif matrix_init_kb(); } @@ -885,6 +888,10 @@ void matrix_scan_quantum() { rgb_matrix_task_counter = ((rgb_matrix_task_counter + 1) % (RGB_MATRIX_SKIP_FRAMES + 1)); #endif + #ifdef ENCODER_ENABLE + encoder_read(); + #endif + matrix_scan_kb(); } #if defined(BACKLIGHT_ENABLE) && defined(BACKLIGHT_PIN) diff --git a/quantum/quantum.h b/quantum/quantum.h index 36eeedd494..55ea4a5010 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -121,6 +121,10 @@ extern uint32_t default_layer_state; #include "process_terminal_nop.h" #endif +#ifdef ENCODER_ENABLE + #include "encoder.h" +#endif + #ifndef MIN #define MAX(x, y) (((x) > (y)) ? (x) : (y)) #define MIN(x, y) (((x) < (y)) ? (x) : (y)) From 21665df8ebefd05be097f4ce5139174ca36618cd Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 3 Jun 2018 22:58:59 -0400 Subject: [PATCH 41/59] add encoder docs --- docs/_summary.md | 1 + docs/feature_encoders.md | 41 +++++++++++++++++++++++ keyboards/planck/keymaps/default/keymap.c | 2 +- quantum/encoder.c | 10 +++--- 4 files changed, 48 insertions(+), 6 deletions(-) create mode 100644 docs/feature_encoders.md diff --git a/docs/_summary.md b/docs/_summary.md index 318c526a85..75bc5cc784 100644 --- a/docs/_summary.md +++ b/docs/_summary.md @@ -34,6 +34,7 @@ * [Bootmagic](feature_bootmagic.md) * [Command](feature_command.md) * [Dynamic Macros](feature_dynamic_macros.md) + * [Encoders](feature_encoders.md) * [Grave Escape](feature_grave_esc.md) * [Key Lock](feature_key_lock.md) * [Layouts](feature_layouts.md) diff --git a/docs/feature_encoders.md b/docs/feature_encoders.md new file mode 100644 index 0000000000..f482eefec8 --- /dev/null +++ b/docs/feature_encoders.md @@ -0,0 +1,41 @@ +# Encoders + +Basic encoders are supported by adding this to your `rules.mk`: + + ENCODER_ENABLE = yes + +and this to your `config.h`: + + #define NUMBER_OF_ENCODERS 1 + #define ENCODERS_PAD_A { B12 } + #define ENCODERS_PAD_B { B13 } + +Each PAD_A/B variable defines an array so multiple encoders can be defined, e.g.: + + #define ENCODERS_PAD_A { encoder1a, encoder2a } + #define ENCODERS_PAD_B { encoder1a, encoder2b } + +If your encoder's clockwise directions are incorrect, you can swap the A & B pad definitions. + +Additionally, the resolution can be specified in the same file (the default & suggested is 4): + + #define ENCODER_RESOLUTION 4 + +## Callbacks + +The callback functions can be inserted into your `.c`: + + void encoder_update_kb(uint8_t index, bool clockwise) { + encoder_update_user(index, clockwise); + } + +or `keymap.c`: + + void encoder_update_user(uint8_t index, bool clockwise) { + + } + + +## Hardware + +The A an B lines of the encoders should be wired directly to the MCU, and the C/common lines should be wired to ground. diff --git a/keyboards/planck/keymaps/default/keymap.c b/keyboards/planck/keymaps/default/keymap.c index 545ca42299..8c452c8dfb 100644 --- a/keyboards/planck/keymaps/default/keymap.c +++ b/keyboards/planck/keymaps/default/keymap.c @@ -259,7 +259,7 @@ uint16_t muse_counter = 0; uint8_t muse_offset = 70; uint16_t muse_tempo = 50; -void encoder_update(bool clockwise) { +void encoder_update_user(int8_t index, bool clockwise) { if (muse_mode) { if (IS_LAYER_ON(_RAISE)) { if (clockwise) { diff --git a/quantum/encoder.c b/quantum/encoder.c index 022cc1c01c..103ff8289b 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -35,11 +35,11 @@ static uint8_t encoder_state[NUMBER_OF_ENCODERS] = {0}; static int8_t encoder_value[NUMBER_OF_ENCODERS] = {0}; __attribute__ ((weak)) -void encoder_update_user(bool clockwise) { } +void encoder_update_user(int8_t index, bool clockwise) { } __attribute__ ((weak)) -void encoder_update_kb(bool clockwise) { - encoder_update_user(clockwise); +void encoder_update_kb(int8_t index, bool clockwise) { + encoder_update_user(index, clockwise); } void encoder_init(void) { @@ -57,10 +57,10 @@ void encoder_read(void) { encoder_state[i] |= (readPad(encoders_pad_a[i]) << 0) | (readPad(encoders_pad_b[i]) << 1); encoder_value[i] += encoder_LUT[encoder_state[i] & 0xF]; if (encoder_value[i] >= ENCODER_RESOLUTION) { - encoder_update_kb(COUNTRECLOCKWISE); + encoder_update_kb(i, COUNTRECLOCKWISE); } if (encoder_value[i] <= -ENCODER_RESOLUTION) { // direction is arbitrary here, but this clockwise - encoder_update_kb(CLOCKWISE); + encoder_update_kb(i, CLOCKWISE); } encoder_value[i] %= ENCODER_RESOLUTION; } From a6afb16c90169827bd350723a2d530e75de94052 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Mon, 4 Jun 2018 00:50:09 -0400 Subject: [PATCH 42/59] fix assembly errors with hal --- keyboards/planck/light/rev2/matrix.c | 1 + quantum/config_common.h | 20 +----------------- quantum/encoder.c | 2 +- quantum/quantum.h | 31 +++++++++++++++++++++++++--- 4 files changed, 31 insertions(+), 23 deletions(-) diff --git a/keyboards/planck/light/rev2/matrix.c b/keyboards/planck/light/rev2/matrix.c index 0de8b20285..5982741b66 100644 --- a/keyboards/planck/light/rev2/matrix.c +++ b/keyboards/planck/light/rev2/matrix.c @@ -10,6 +10,7 @@ #include "action.h" #include "keycode.h" #include +#include "quantum.h" /* * col: { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } diff --git a/quantum/config_common.h b/quantum/config_common.h index 5de2d13993..7c02e9e5f3 100644 --- a/quantum/config_common.h +++ b/quantum/config_common.h @@ -23,8 +23,6 @@ #define CUSTOM_MATRIX 2 /* Disables built-in matrix scanning code */ #ifdef __AVR__ - #include - #define LINE_TYPE uint8_t /* I/O pins */ #ifndef F0 @@ -78,18 +76,8 @@ #define A7 0x07 #endif - #define setPadMode(line, mode) _SFR_IO8((line >> 4) + 1) mode _BV(line & 0xF) - #define setPad(line) _SFR_IO8((line >> 4) + 2) |= _BV(line & 0xF) - #define clearPad(line) _SFR_IO8((line >> 4) + 2) &= ~_BV(line & 0xF) - #define readPad(line) (_SFR_IO8(line >> 4) & _BV(line & 0xF)) - #define PAD_MODE_INPUT &= ~ - #define PAD_MODE_OUTPUT |= - -#else - #include "hal.h" - - #define LINE_TYPE ioline_t +#elif defined(__arm__) #define A0 PAL_LINE(GPIOA, 0) #define A1 PAL_LINE(GPIOA, 1) @@ -188,12 +176,6 @@ #define F14 PAL_LINE(GPIOF, 14) #define F15 PAL_LINE(GPIOF, 15) - #define setPadMode(line, mode) palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode) - #define setPad(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) - #define clearPad(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) - #define readPad(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) - - #define PAD_MODE_INPUT PAL_MODE_INPUT_PULLUP #endif diff --git a/quantum/encoder.c b/quantum/encoder.c index 103ff8289b..265e0ec206 100644 --- a/quantum/encoder.c +++ b/quantum/encoder.c @@ -16,7 +16,7 @@ */ #include "encoder.h" -#include +#include "quantum.h" #ifndef ENCODER_RESOLUTION #define ENCODER_RESOLUTION 4 diff --git a/quantum/quantum.h b/quantum/quantum.h index 55ea4a5010..b634ab7418 100644 --- a/quantum/quantum.h +++ b/quantum/quantum.h @@ -17,10 +17,11 @@ #define QUANTUM_H #if defined(__AVR__) -#include -#include -#include + #include + #include + #include #endif + #include "wait.h" #include "matrix.h" #include "keymap.h" @@ -130,6 +131,30 @@ extern uint32_t default_layer_state; #define MIN(x, y) (((x) < (y)) ? (x) : (y)) #endif + +#ifdef __AVR__ + #include + #define LINE_TYPE uint8_t + + #define setPadMode(line, mode) _SFR_IO8((line >> 4) + 1) mode _BV(line & 0xF) + #define setPad(line) _SFR_IO8((line >> 4) + 2) |= _BV(line & 0xF) + #define clearPad(line) _SFR_IO8((line >> 4) + 2) &= ~_BV(line & 0xF) + #define readPad(line) (_SFR_IO8(line >> 4) & _BV(line & 0xF)) + + #define PAD_MODE_INPUT &= ~ + #define PAD_MODE_OUTPUT |= +#elif defined(__arm__) + #include "hal.h" + #define LINE_TYPE ioline_t + + #define setPadMode(line, mode) palSetPadMode(PAL_PORT(line), PAL_PAD(line), mode) + #define setPad(line) palSetPad(PAL_PORT(line), PAL_PAD(line)) + #define clearPad(line) palClearPad(PAL_PORT(line), PAL_PAD(line)) + #define readPad(line) palReadPad(PAL_PORT(line), PAL_PAD(line)) + + #define PAD_MODE_INPUT PAL_MODE_INPUT_PULLUP +#endif + #define STRINGIZE(z) #z #define ADD_SLASH_X(y) STRINGIZE(\x ## y) #define SYMBOL_STR(x) ADD_SLASH_X(x) From c53a8ead9320fb7ef635025db78f9dd7f66a8286 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Wed, 6 Jun 2018 18:21:51 -0400 Subject: [PATCH 43/59] inital support for muon --- .../boards/GENERIC_STM32_F303XC/board.c | 126 ++ .../boards/GENERIC_STM32_F303XC/board.h | 1187 +++++++++++++++++ .../boards/GENERIC_STM32_F303XC/board.mk | 5 + keyboards/muon_light/bootloader_defs.h | 7 + keyboards/muon_light/chconf.h | 520 ++++++++ keyboards/muon_light/config.h | 152 +++ keyboards/muon_light/halconf.h | 388 ++++++ keyboards/muon_light/info.json | 38 + keyboards/muon_light/keymaps/default/config.h | 43 + keyboards/muon_light/keymaps/default/keymap.c | 309 +++++ .../muon_light/keymaps/default/readme.md | 2 + keyboards/muon_light/keymaps/default/rules.mk | 0 keyboards/muon_light/matrix.c | 124 ++ keyboards/muon_light/mcuconf.h | 257 ++++ keyboards/muon_light/muon_light.c | 115 ++ keyboards/muon_light/muon_light.h | 35 + keyboards/muon_light/readme.md | 16 + keyboards/muon_light/rules.mk | 62 + 18 files changed, 3386 insertions(+) create mode 100644 keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.c create mode 100644 keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.h create mode 100644 keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.mk create mode 100644 keyboards/muon_light/bootloader_defs.h create mode 100644 keyboards/muon_light/chconf.h create mode 100644 keyboards/muon_light/config.h create mode 100644 keyboards/muon_light/halconf.h create mode 100644 keyboards/muon_light/info.json create mode 100644 keyboards/muon_light/keymaps/default/config.h create mode 100644 keyboards/muon_light/keymaps/default/keymap.c create mode 100644 keyboards/muon_light/keymaps/default/readme.md create mode 100644 keyboards/muon_light/keymaps/default/rules.mk create mode 100644 keyboards/muon_light/matrix.c create mode 100644 keyboards/muon_light/mcuconf.h create mode 100644 keyboards/muon_light/muon_light.c create mode 100644 keyboards/muon_light/muon_light.h create mode 100644 keyboards/muon_light/readme.md create mode 100644 keyboards/muon_light/rules.mk diff --git a/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.c b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.c new file mode 100644 index 0000000000..4331155df4 --- /dev/null +++ b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.c @@ -0,0 +1,126 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#include "hal.h" + +#if HAL_USE_PAL || defined(__DOXYGEN__) +/** + * @brief PAL setup. + * @details Digital I/O ports static configuration as defined in @p board.h. + * This variable is used by the HAL when initializing the PAL driver. + */ +const PALConfig pal_default_config = { +#if STM32_HAS_GPIOA + {VAL_GPIOA_MODER, VAL_GPIOA_OTYPER, VAL_GPIOA_OSPEEDR, VAL_GPIOA_PUPDR, + VAL_GPIOA_ODR, VAL_GPIOA_AFRL, VAL_GPIOA_AFRH}, +#endif +#if STM32_HAS_GPIOB + {VAL_GPIOB_MODER, VAL_GPIOB_OTYPER, VAL_GPIOB_OSPEEDR, VAL_GPIOB_PUPDR, + VAL_GPIOB_ODR, VAL_GPIOB_AFRL, VAL_GPIOB_AFRH}, +#endif +#if STM32_HAS_GPIOC + {VAL_GPIOC_MODER, VAL_GPIOC_OTYPER, VAL_GPIOC_OSPEEDR, VAL_GPIOC_PUPDR, + VAL_GPIOC_ODR, VAL_GPIOC_AFRL, VAL_GPIOC_AFRH}, +#endif +#if STM32_HAS_GPIOD + {VAL_GPIOD_MODER, VAL_GPIOD_OTYPER, VAL_GPIOD_OSPEEDR, VAL_GPIOD_PUPDR, + VAL_GPIOD_ODR, VAL_GPIOD_AFRL, VAL_GPIOD_AFRH}, +#endif +#if STM32_HAS_GPIOE + {VAL_GPIOE_MODER, VAL_GPIOE_OTYPER, VAL_GPIOE_OSPEEDR, VAL_GPIOE_PUPDR, + VAL_GPIOE_ODR, VAL_GPIOE_AFRL, VAL_GPIOE_AFRH}, +#endif +#if STM32_HAS_GPIOF + {VAL_GPIOF_MODER, VAL_GPIOF_OTYPER, VAL_GPIOF_OSPEEDR, VAL_GPIOF_PUPDR, + VAL_GPIOF_ODR, VAL_GPIOF_AFRL, VAL_GPIOF_AFRH}, +#endif +#if STM32_HAS_GPIOG + {VAL_GPIOG_MODER, VAL_GPIOG_OTYPER, VAL_GPIOG_OSPEEDR, VAL_GPIOG_PUPDR, + VAL_GPIOG_ODR, VAL_GPIOG_AFRL, VAL_GPIOG_AFRH}, +#endif +#if STM32_HAS_GPIOH + {VAL_GPIOH_MODER, VAL_GPIOH_OTYPER, VAL_GPIOH_OSPEEDR, VAL_GPIOH_PUPDR, + VAL_GPIOH_ODR, VAL_GPIOH_AFRL, VAL_GPIOH_AFRH}, +#endif +#if STM32_HAS_GPIOI + {VAL_GPIOI_MODER, VAL_GPIOI_OTYPER, VAL_GPIOI_OSPEEDR, VAL_GPIOI_PUPDR, + VAL_GPIOI_ODR, VAL_GPIOI_AFRL, VAL_GPIOI_AFRH} +#endif +}; +#endif + +void enter_bootloader_mode_if_requested(void); + +/** + * @brief Early initialization code. + * @details This initialization must be performed just after stack setup + * and before any other initialization. + */ +void __early_init(void) { + enter_bootloader_mode_if_requested(); + stm32_clock_init(); +} + +#if HAL_USE_SDC || defined(__DOXYGEN__) +/** + * @brief SDC card detection. + */ +bool sdc_lld_is_card_inserted(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief SDC card write protection detection. + */ +bool sdc_lld_is_write_protected(SDCDriver *sdcp) { + + (void)sdcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif /* HAL_USE_SDC */ + +#if HAL_USE_MMC_SPI || defined(__DOXYGEN__) +/** + * @brief MMC_SPI card detection. + */ +bool mmc_lld_is_card_inserted(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return true; +} + +/** + * @brief MMC_SPI card write protection detection. + */ +bool mmc_lld_is_write_protected(MMCDriver *mmcp) { + + (void)mmcp; + /* TODO: Fill the implementation.*/ + return false; +} +#endif + +/** + * @brief Board-specific initialization code. + * @todo Add your board-specific code, if any. + */ +void boardInit(void) { +} diff --git a/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.h b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.h new file mode 100644 index 0000000000..ec26557f3a --- /dev/null +++ b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.h @@ -0,0 +1,1187 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +#ifndef _BOARD_H_ +#define _BOARD_H_ + +/* + * Setup for Clueboard 60% Keyboard + */ + +/* + * Board identifier. + */ +#define BOARD_GENERIC_STM32_F303XC +#define BOARD_NAME "Planck PCB" + +/* + * Board oscillators-related settings. + * NOTE: LSE not fitted. + */ +#if !defined(STM32_LSECLK) +#define STM32_LSECLK 0U +#endif + +#define STM32_LSEDRV (3U << 3U) + +#if !defined(STM32_HSECLK) +#define STM32_HSECLK 8000000U +#endif + +// #define STM32_HSE_BYPASS + +/* + * MCU type as defined in the ST header. + */ +#define STM32F303xC + +/* + * IO pins assignments. + */ +#define GPIOA_PIN0 0U +#define GPIOA_PIN1 1U +#define GPIOA_PIN2 2U +#define GPIOA_PIN3 3U +#define GPIOA_PIN4 4U +#define GPIOA_PIN5 5U +#define GPIOA_PIN6 6U +#define GPIOA_PIN7 7U +#define GPIOA_PIN8 8U +#define GPIOA_PIN9 9U +#define GPIOA_PIN10 10U +#define GPIOA_USB_DM 11U +#define GPIOA_USB_DP 12U +#define GPIOA_SWDIO 13U +#define GPIOA_SWCLK 14U +#define GPIOA_PIN15 15U + +#define GPIOB_PIN0 0U +#define GPIOB_PIN1 1U +#define GPIOB_PIN2 2U +#define GPIOB_PIN3 3U +#define GPIOB_PIN4 4U +#define GPIOB_PIN5 5U +#define GPIOB_PIN6 6U +#define GPIOB_PIN7 7U +#define GPIOB_PIN8 8U +#define GPIOB_PIN9 9U +#define GPIOB_PIN10 10U +#define GPIOB_PIN11 11U +#define GPIOB_PIN12 12U +#define GPIOB_PIN13 13U +#define GPIOB_PIN14 14U +#define GPIOB_PIN15 15U + +#define GPIOC_PIN0 0U +#define GPIOC_PIN1 1U +#define GPIOC_PIN2 2U +#define GPIOC_PIN3 3U +#define GPIOC_PIN4 4U +#define GPIOC_PIN5 5U +#define GPIOC_PIN6 6U +#define GPIOC_PIN7 7U +#define GPIOC_PIN8 8U +#define GPIOC_PIN9 9U +#define GPIOC_PIN10 10U +#define GPIOC_PIN11 11U +#define GPIOC_PIN12 12U +#define GPIOC_PIN13 13U +#define GPIOC_PIN14 14U +#define GPIOC_PIN15 15U + +#define GPIOD_PIN0 0U +#define GPIOD_PIN1 1U +#define GPIOD_PIN2 2U +#define GPIOD_PIN3 3U +#define GPIOD_PIN4 4U +#define GPIOD_PIN5 5U +#define GPIOD_PIN6 6U +#define GPIOD_PIN7 7U +#define GPIOD_PIN8 8U +#define GPIOD_PIN9 9U +#define GPIOD_PIN10 10U +#define GPIOD_PIN11 11U +#define GPIOD_PIN12 12U +#define GPIOD_PIN13 13U +#define GPIOD_PIN14 14U +#define GPIOD_PIN15 15U + +#define GPIOE_PIN0 0U +#define GPIOE_PIN1 1U +#define GPIOE_PIN2 2U +#define GPIOE_PIN3 3U +#define GPIOE_PIN4 4U +#define GPIOE_PIN5 5U +#define GPIOE_PIN6 6U +#define GPIOE_PIN7 7U +#define GPIOE_PIN8 8U +#define GPIOE_PIN9 9U +#define GPIOE_PIN10 10U +#define GPIOE_PIN11 11U +#define GPIOE_PIN12 12U +#define GPIOE_PIN13 13U +#define GPIOE_PIN14 14U +#define GPIOE_PIN15 15U + +#define GPIOF_I2C2_SDA 0U +#define GPIOF_I2C2_SCL 1U +#define GPIOF_PIN2 2U +#define GPIOF_PIN3 3U +#define GPIOF_PIN4 4U +#define GPIOF_PIN5 5U +#define GPIOF_PIN6 6U +#define GPIOF_PIN7 7U +#define GPIOF_PIN8 8U +#define GPIOF_PIN9 9U +#define GPIOF_PIN10 10U +#define GPIOF_PIN11 11U +#define GPIOF_PIN12 12U +#define GPIOF_PIN13 13U +#define GPIOF_PIN14 14U +#define GPIOF_PIN15 15U + +#define GPIOG_PIN0 0U +#define GPIOG_PIN1 1U +#define GPIOG_PIN2 2U +#define GPIOG_PIN3 3U +#define GPIOG_PIN4 4U +#define GPIOG_PIN5 5U +#define GPIOG_PIN6 6U +#define GPIOG_PIN7 7U +#define GPIOG_PIN8 8U +#define GPIOG_PIN9 9U +#define GPIOG_PIN10 10U +#define GPIOG_PIN11 11U +#define GPIOG_PIN12 12U +#define GPIOG_PIN13 13U +#define GPIOG_PIN14 14U +#define GPIOG_PIN15 15U + +#define GPIOH_PIN0 0U +#define GPIOH_PIN1 1U +#define GPIOH_PIN2 2U +#define GPIOH_PIN3 3U +#define GPIOH_PIN4 4U +#define GPIOH_PIN5 5U +#define GPIOH_PIN6 6U +#define GPIOH_PIN7 7U +#define GPIOH_PIN8 8U +#define GPIOH_PIN9 9U +#define GPIOH_PIN10 10U +#define GPIOH_PIN11 11U +#define GPIOH_PIN12 12U +#define GPIOH_PIN13 13U +#define GPIOH_PIN14 14U +#define GPIOH_PIN15 15U + +/* + * IO lines assignments. + */ +#define LINE_L3GD20_SDI PAL_LINE(GPIOA, 7U) +#define LINE_USB_DM PAL_LINE(GPIOA, 11U) +#define LINE_USB_DP PAL_LINE(GPIOA, 12U) +#define LINE_SWDIO PAL_LINE(GPIOA, 13U) +#define LINE_SWCLK PAL_LINE(GPIOA, 14U) + +#define LINE_PIN6 PAL_LINE(GPIOF, 0U) +#define LINE_PIN7 PAL_LINE(GPIOF, 1U) + +#define LINE_CAPS_LOCK PAL_LINE(GPIOB, 7U) + + +/* + * I/O ports initial setup, this configuration is established soon after reset + * in the initialization code. + * Please refer to the STM32 Reference Manual for details. + */ +#define PIN_MODE_INPUT(n) (0U << ((n) * 2U)) +#define PIN_MODE_OUTPUT(n) (1U << ((n) * 2U)) +#define PIN_MODE_ALTERNATE(n) (2U << ((n) * 2U)) +#define PIN_MODE_ANALOG(n) (3U << ((n) * 2U)) +#define PIN_ODR_LOW(n) (0U << (n)) +#define PIN_ODR_HIGH(n) (1U << (n)) +#define PIN_OTYPE_PUSHPULL(n) (0U << (n)) +#define PIN_OTYPE_OPENDRAIN(n) (1U << (n)) +#define PIN_OSPEED_VERYLOW(n) (0U << ((n) * 2U)) +#define PIN_OSPEED_LOW(n) (1U << ((n) * 2U)) +#define PIN_OSPEED_MEDIUM(n) (2U << ((n) * 2U)) +#define PIN_OSPEED_HIGH(n) (3U << ((n) * 2U)) +#define PIN_PUPDR_FLOATING(n) (0U << ((n) * 2U)) +#define PIN_PUPDR_PULLUP(n) (1U << ((n) * 2U)) +#define PIN_PUPDR_PULLDOWN(n) (2U << ((n) * 2U)) +#define PIN_AFIO_AF(n, v) ((v) << (((n) % 8U) * 4U)) + +/* + * GPIOA setup: + * + * PA0 - NC + * PA1 - NC + * PA2 - COL1 + * PA3 - COL2 + * PA4 - SPEAKER1 + * PA5 - SPEAKER2 + * PA6 - COL3 + * PA7 - COL8 + * PA8 - COL6 + * PA9 - COL7 + * PA10 - ROW5 + * PA11 - USB_DM (alternate 14). + * PA12 - USB_DP (alternate 14). + * PA13 - SWDIO (alternate 0). + * PA14 - SWCLK (alternate 0). + * PA15 - ROW4 + */ +#define VAL_GPIOA_MODER (PIN_MODE_INPUT(GPIOA_PIN0) | \ + PIN_MODE_ALTERNATE(GPIOA_PIN1) | \ + PIN_MODE_INPUT(GPIOA_PIN2) | \ + PIN_MODE_INPUT(GPIOA_PIN3) | \ + PIN_MODE_INPUT(GPIOA_PIN4) | \ + PIN_MODE_INPUT(GPIOA_PIN5) | \ + PIN_MODE_INPUT(GPIOA_PIN6) | \ + PIN_MODE_INPUT(GPIOA_PIN7) | \ + PIN_MODE_INPUT(GPIOA_PIN8) | \ + PIN_MODE_INPUT(GPIOA_PIN9) | \ + PIN_MODE_INPUT(GPIOA_PIN10) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DM) | \ + PIN_MODE_ALTERNATE(GPIOA_USB_DP) | \ + PIN_MODE_ALTERNATE(GPIOA_SWDIO) | \ + PIN_MODE_ALTERNATE(GPIOA_SWCLK) | \ + PIN_MODE_INPUT(GPIOA_PIN15)) +#define VAL_GPIOA_OTYPER (PIN_OTYPE_PUSHPULL(GPIOA_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DM) | \ + PIN_OTYPE_PUSHPULL(GPIOA_USB_DP) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWDIO) | \ + PIN_OTYPE_PUSHPULL(GPIOA_SWCLK) | \ + PIN_OTYPE_PUSHPULL(GPIOA_PIN15)) +#define VAL_GPIOA_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOA_PIN0) | \ + PIN_OSPEED_HIGH(GPIOA_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN10) | \ + PIN_OSPEED_HIGH(GPIOA_USB_DM) | \ + PIN_OSPEED_VERYLOW(GPIOA_USB_DP) | \ + PIN_OSPEED_HIGH(GPIOA_SWDIO) | \ + PIN_OSPEED_HIGH(GPIOA_SWCLK) | \ + PIN_OSPEED_VERYLOW(GPIOA_PIN15)) +#define VAL_GPIOA_PUPDR (PIN_PUPDR_FLOATING(GPIOA_PIN0) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN6) | \ + PIN_PUPDR_FLOATING(GPIOA_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DM) | \ + PIN_PUPDR_FLOATING(GPIOA_USB_DP) | \ + PIN_PUPDR_PULLUP(GPIOA_SWDIO) | \ + PIN_PUPDR_PULLDOWN(GPIOA_SWCLK) | \ + PIN_PUPDR_PULLUP(GPIOA_PIN15)) +#define VAL_GPIOA_ODR (PIN_ODR_HIGH(GPIOA_PIN0) | \ + PIN_ODR_HIGH(GPIOA_PIN1) | \ + PIN_ODR_HIGH(GPIOA_PIN2) | \ + PIN_ODR_HIGH(GPIOA_PIN3) | \ + PIN_ODR_HIGH(GPIOA_PIN4) | \ + PIN_ODR_HIGH(GPIOA_PIN5) | \ + PIN_ODR_HIGH(GPIOA_PIN6) | \ + PIN_ODR_HIGH(GPIOA_PIN7) | \ + PIN_ODR_HIGH(GPIOA_PIN8) | \ + PIN_ODR_HIGH(GPIOA_PIN9) | \ + PIN_ODR_HIGH(GPIOA_PIN10) | \ + PIN_ODR_HIGH(GPIOA_USB_DM) | \ + PIN_ODR_HIGH(GPIOA_USB_DP) | \ + PIN_ODR_HIGH(GPIOA_SWDIO) | \ + PIN_ODR_HIGH(GPIOA_SWCLK) | \ + PIN_ODR_HIGH(GPIOA_PIN15)) +#define VAL_GPIOA_AFRL (PIN_AFIO_AF(GPIOA_PIN0, 0) | \ + PIN_AFIO_AF(GPIOA_PIN1, 1) | \ + PIN_AFIO_AF(GPIOA_PIN2, 0) | \ + PIN_AFIO_AF(GPIOA_PIN3, 0) | \ + PIN_AFIO_AF(GPIOA_PIN4, 0) | \ + PIN_AFIO_AF(GPIOA_PIN5, 5) | \ + PIN_AFIO_AF(GPIOA_PIN6, 5) | \ + PIN_AFIO_AF(GPIOA_PIN7, 5)) +#define VAL_GPIOA_AFRH (PIN_AFIO_AF(GPIOA_PIN8, 0) | \ + PIN_AFIO_AF(GPIOA_PIN9, 0) | \ + PIN_AFIO_AF(GPIOA_PIN10, 0) | \ + PIN_AFIO_AF(GPIOA_USB_DM, 14) | \ + PIN_AFIO_AF(GPIOA_USB_DP, 14) | \ + PIN_AFIO_AF(GPIOA_SWDIO, 0) | \ + PIN_AFIO_AF(GPIOA_SWCLK, 0) | \ + PIN_AFIO_AF(GPIOA_PIN15, 0)) + +/* + * GPIOB setup: + * + * PB0 - PIN0 (input pullup). + * PB1 - PIN1 (input pullup). + * PB2 - PIN2 (input pullup). + * PB3 - PIN3 (alternate 0). + * PB4 - PIN4 (input pullup). + * PB5 - PIN5 (input pullup). + * PB6 - PIN6 LSM303DLHC_SCL (alternate 4). + * PB7 - PIN7 LSM303DLHC_SDA (alternate 4). + * PB8 - PIN8 (input pullup). + * PB9 - PIN9 (input pullup). + * PB10 - PIN10 (input pullup). + * PB11 - PIN11 (input pullup). + * PB12 - PIN12 (input pullup). + * PB13 - PIN13 (input pullup). + * PB14 - PIN14 (input pullup). + * PB15 - PIN15 (input pullup). + */ +#define VAL_GPIOB_MODER (PIN_MODE_INPUT(GPIOB_PIN0) | \ + PIN_MODE_INPUT(GPIOB_PIN1) | \ + PIN_MODE_INPUT(GPIOB_PIN2) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN3) | \ + PIN_MODE_INPUT(GPIOB_PIN4) | \ + PIN_MODE_INPUT(GPIOB_PIN5) | \ + PIN_MODE_ALTERNATE(GPIOB_PIN6) | \ + PIN_MODE_OUTPUT(GPIOB_PIN7) | \ + PIN_MODE_INPUT(GPIOB_PIN8) | \ + PIN_MODE_INPUT(GPIOB_PIN9) | \ + PIN_MODE_INPUT(GPIOB_PIN10) | \ + PIN_MODE_INPUT(GPIOB_PIN11) | \ + PIN_MODE_INPUT(GPIOB_PIN12) | \ + PIN_MODE_INPUT(GPIOB_PIN13) | \ + PIN_MODE_INPUT(GPIOB_PIN14) | \ + PIN_MODE_INPUT(GPIOB_PIN15)) +#define VAL_GPIOB_OTYPER (PIN_OTYPE_PUSHPULL(GPIOB_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN5) | \ + PIN_OTYPE_OPENDRAIN(GPIOB_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOB_PIN15)) +#define VAL_GPIOB_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOB_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN2) | \ + PIN_OSPEED_HIGH(GPIOB_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN5) | \ + PIN_OSPEED_HIGH(GPIOB_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOB_PIN15)) +#define VAL_GPIOB_PUPDR (PIN_PUPDR_PULLUP(GPIOB_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN2) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN5) | \ + PIN_PUPDR_FLOATING(GPIOB_PIN6) | \ + PIN_PUPDR_PULLDOWN(GPIOB_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOB_PIN15)) +#define VAL_GPIOB_ODR (PIN_ODR_HIGH(GPIOB_PIN0) | \ + PIN_ODR_HIGH(GPIOB_PIN1) | \ + PIN_ODR_HIGH(GPIOB_PIN2) | \ + PIN_ODR_HIGH(GPIOB_PIN3) | \ + PIN_ODR_HIGH(GPIOB_PIN4) | \ + PIN_ODR_HIGH(GPIOB_PIN5) | \ + PIN_ODR_HIGH(GPIOB_PIN6) | \ + PIN_ODR_LOW(GPIOB_PIN7) | \ + PIN_ODR_HIGH(GPIOB_PIN8) | \ + PIN_ODR_HIGH(GPIOB_PIN9) | \ + PIN_ODR_HIGH(GPIOB_PIN10) | \ + PIN_ODR_HIGH(GPIOB_PIN11) | \ + PIN_ODR_HIGH(GPIOB_PIN12) | \ + PIN_ODR_HIGH(GPIOB_PIN13) | \ + PIN_ODR_HIGH(GPIOB_PIN14) | \ + PIN_ODR_HIGH(GPIOB_PIN15)) +#define VAL_GPIOB_AFRL (PIN_AFIO_AF(GPIOB_PIN0, 0) | \ + PIN_AFIO_AF(GPIOB_PIN1, 0) | \ + PIN_AFIO_AF(GPIOB_PIN2, 0) | \ + PIN_AFIO_AF(GPIOB_PIN3, 0) | \ + PIN_AFIO_AF(GPIOB_PIN4, 0) | \ + PIN_AFIO_AF(GPIOB_PIN5, 0) | \ + PIN_AFIO_AF(GPIOB_PIN6, 4) | \ + PIN_AFIO_AF(GPIOB_PIN7, 0)) +#define VAL_GPIOB_AFRH (PIN_AFIO_AF(GPIOB_PIN8, 0) | \ + PIN_AFIO_AF(GPIOB_PIN9, 0) | \ + PIN_AFIO_AF(GPIOB_PIN10, 0) | \ + PIN_AFIO_AF(GPIOB_PIN11, 0) | \ + PIN_AFIO_AF(GPIOB_PIN12, 0) | \ + PIN_AFIO_AF(GPIOB_PIN13, 0) | \ + PIN_AFIO_AF(GPIOB_PIN14, 0) | \ + PIN_AFIO_AF(GPIOB_PIN15, 0)) + +/* + * GPIOC setup: + * + * PC0 - PIN0 (input pullup). + * PC1 - PIN1 (input pullup). + * PC2 - PIN2 (input pullup). + * PC3 - PIN3 (input pullup). + * PC4 - PIN4 (input pullup). + * PC5 - PIN5 (input pullup). + * PC6 - PIN6 (input pullup). + * PC7 - PIN7 (input pullup). + * PC8 - PIN8 (input pullup). + * PC9 - PIN9 (input pullup). + * PC10 - PIN10 (input pullup). + * PC11 - PIN11 (input pullup). + * PC12 - PIN12 (input pullup). + * PC13 - PIN13 (input pullup). + * PC14 - PIN14 (input floating). + * PC15 - PIN15 (input floating). + */ +#define VAL_GPIOC_MODER (PIN_MODE_INPUT(GPIOC_PIN0) | \ + PIN_MODE_INPUT(GPIOC_PIN1) | \ + PIN_MODE_INPUT(GPIOC_PIN2) | \ + PIN_MODE_INPUT(GPIOC_PIN3) | \ + PIN_MODE_INPUT(GPIOC_PIN4) | \ + PIN_MODE_INPUT(GPIOC_PIN5) | \ + PIN_MODE_INPUT(GPIOC_PIN6) | \ + PIN_MODE_INPUT(GPIOC_PIN7) | \ + PIN_MODE_INPUT(GPIOC_PIN8) | \ + PIN_MODE_INPUT(GPIOC_PIN9) | \ + PIN_MODE_INPUT(GPIOC_PIN10) | \ + PIN_MODE_INPUT(GPIOC_PIN11) | \ + PIN_MODE_INPUT(GPIOC_PIN12) | \ + PIN_MODE_INPUT(GPIOC_PIN13) | \ + PIN_MODE_INPUT(GPIOC_PIN14) | \ + PIN_MODE_INPUT(GPIOC_PIN15)) +#define VAL_GPIOC_OTYPER (PIN_OTYPE_PUSHPULL(GPIOC_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOC_PIN15)) +#define VAL_GPIOC_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOC_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOC_PIN13) | \ + PIN_OSPEED_HIGH(GPIOC_PIN14) | \ + PIN_OSPEED_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_PUPDR (PIN_PUPDR_PULLUP(GPIOC_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOC_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN14) | \ + PIN_PUPDR_FLOATING(GPIOC_PIN15)) +#define VAL_GPIOC_ODR (PIN_ODR_HIGH(GPIOC_PIN0) | \ + PIN_ODR_HIGH(GPIOC_PIN1) | \ + PIN_ODR_HIGH(GPIOC_PIN2) | \ + PIN_ODR_HIGH(GPIOC_PIN3) | \ + PIN_ODR_HIGH(GPIOC_PIN4) | \ + PIN_ODR_HIGH(GPIOC_PIN5) | \ + PIN_ODR_HIGH(GPIOC_PIN6) | \ + PIN_ODR_HIGH(GPIOC_PIN7) | \ + PIN_ODR_HIGH(GPIOC_PIN8) | \ + PIN_ODR_HIGH(GPIOC_PIN9) | \ + PIN_ODR_HIGH(GPIOC_PIN10) | \ + PIN_ODR_HIGH(GPIOC_PIN11) | \ + PIN_ODR_HIGH(GPIOC_PIN12) | \ + PIN_ODR_HIGH(GPIOC_PIN13) | \ + PIN_ODR_HIGH(GPIOC_PIN14) | \ + PIN_ODR_HIGH(GPIOC_PIN15)) +#define VAL_GPIOC_AFRL (PIN_AFIO_AF(GPIOC_PIN0, 0) | \ + PIN_AFIO_AF(GPIOC_PIN1, 0) | \ + PIN_AFIO_AF(GPIOC_PIN2, 0) | \ + PIN_AFIO_AF(GPIOC_PIN3, 0) | \ + PIN_AFIO_AF(GPIOC_PIN4, 0) | \ + PIN_AFIO_AF(GPIOC_PIN5, 0) | \ + PIN_AFIO_AF(GPIOC_PIN6, 0) | \ + PIN_AFIO_AF(GPIOC_PIN7, 0)) +#define VAL_GPIOC_AFRH (PIN_AFIO_AF(GPIOC_PIN8, 0) | \ + PIN_AFIO_AF(GPIOC_PIN9, 0) | \ + PIN_AFIO_AF(GPIOC_PIN10, 0) | \ + PIN_AFIO_AF(GPIOC_PIN11, 0) | \ + PIN_AFIO_AF(GPIOC_PIN12, 0) | \ + PIN_AFIO_AF(GPIOC_PIN13, 0) | \ + PIN_AFIO_AF(GPIOC_PIN14, 0) | \ + PIN_AFIO_AF(GPIOC_PIN15, 0)) + +/* + * GPIOD setup: + * + * PD0 - PIN0 (input pullup). + * PD1 - PIN1 (input pullup). + * PD2 - PIN2 (input pullup). + * PD3 - PIN3 (input pullup). + * PD4 - PIN4 (input pullup). + * PD5 - PIN5 (input pullup). + * PD6 - PIN6 (input pullup). + * PD7 - PIN7 (input pullup). + * PD8 - PIN8 (input pullup). + * PD9 - PIN9 (input pullup). + * PD11 - PIN10 (input pullup). + * PD11 - PIN11 (input pullup). + * PD12 - PIN12 (input pullup). + * PD13 - PIN13 (input pullup). + * PD14 - PIN14 (input pullup). + * PD15 - PIN15 (input pullup). + */ +#define VAL_GPIOD_MODER (PIN_MODE_INPUT(GPIOD_PIN0) | \ + PIN_MODE_INPUT(GPIOD_PIN1) | \ + PIN_MODE_INPUT(GPIOD_PIN2) | \ + PIN_MODE_INPUT(GPIOD_PIN3) | \ + PIN_MODE_INPUT(GPIOD_PIN4) | \ + PIN_MODE_INPUT(GPIOD_PIN5) | \ + PIN_MODE_INPUT(GPIOD_PIN6) | \ + PIN_MODE_INPUT(GPIOD_PIN7) | \ + PIN_MODE_INPUT(GPIOD_PIN8) | \ + PIN_MODE_INPUT(GPIOD_PIN9) | \ + PIN_MODE_INPUT(GPIOD_PIN10) | \ + PIN_MODE_INPUT(GPIOD_PIN11) | \ + PIN_MODE_INPUT(GPIOD_PIN12) | \ + PIN_MODE_INPUT(GPIOD_PIN13) | \ + PIN_MODE_INPUT(GPIOD_PIN14) | \ + PIN_MODE_INPUT(GPIOD_PIN15)) +#define VAL_GPIOD_OTYPER (PIN_OTYPE_PUSHPULL(GPIOD_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOD_PIN15)) +#define VAL_GPIOD_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOD_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOD_PIN15)) +#define VAL_GPIOD_PUPDR (PIN_PUPDR_PULLUP(GPIOD_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOD_PIN15)) +#define VAL_GPIOD_ODR (PIN_ODR_HIGH(GPIOD_PIN0) | \ + PIN_ODR_HIGH(GPIOD_PIN1) | \ + PIN_ODR_HIGH(GPIOD_PIN2) | \ + PIN_ODR_HIGH(GPIOD_PIN3) | \ + PIN_ODR_HIGH(GPIOD_PIN4) | \ + PIN_ODR_HIGH(GPIOD_PIN5) | \ + PIN_ODR_HIGH(GPIOD_PIN6) | \ + PIN_ODR_HIGH(GPIOD_PIN7) | \ + PIN_ODR_HIGH(GPIOD_PIN8) | \ + PIN_ODR_HIGH(GPIOD_PIN9) | \ + PIN_ODR_HIGH(GPIOD_PIN10) | \ + PIN_ODR_HIGH(GPIOD_PIN11) | \ + PIN_ODR_HIGH(GPIOD_PIN12) | \ + PIN_ODR_HIGH(GPIOD_PIN13) | \ + PIN_ODR_HIGH(GPIOD_PIN14) | \ + PIN_ODR_HIGH(GPIOD_PIN15)) +#define VAL_GPIOD_AFRL (PIN_AFIO_AF(GPIOD_PIN0, 0) | \ + PIN_AFIO_AF(GPIOD_PIN1, 0) | \ + PIN_AFIO_AF(GPIOD_PIN2, 0) | \ + PIN_AFIO_AF(GPIOD_PIN3, 0) | \ + PIN_AFIO_AF(GPIOD_PIN4, 0) | \ + PIN_AFIO_AF(GPIOD_PIN5, 0) | \ + PIN_AFIO_AF(GPIOD_PIN6, 0) | \ + PIN_AFIO_AF(GPIOD_PIN7, 0)) +#define VAL_GPIOD_AFRH (PIN_AFIO_AF(GPIOD_PIN8, 0) | \ + PIN_AFIO_AF(GPIOD_PIN9, 0) | \ + PIN_AFIO_AF(GPIOD_PIN10, 0) | \ + PIN_AFIO_AF(GPIOD_PIN11, 0) | \ + PIN_AFIO_AF(GPIOD_PIN12, 0) | \ + PIN_AFIO_AF(GPIOD_PIN13, 0) | \ + PIN_AFIO_AF(GPIOD_PIN14, 0) | \ + PIN_AFIO_AF(GPIOD_PIN15, 0)) + +/* + * GPIOE setup: + * + * PE0 - PIN0 (input pullup). + * PE1 - PIN1 (input pullup). + * PE2 - PIN2 (input pullup). + * PE3 - PIN3 L3GD20_CS (output pushpull maximum). + * PE4 - PIN4 (input pullup). + * PE5 - PIN5 (input pullup). + * PE6 - PIN6 (input pullup). + * PE7 - PIN7 (input pullup). + * PE8 - PIN8 (output pushpull maximum). + * PE9 - PIN9 (output pushpull maximum). + * PE10 - PIN10 (output pushpull maximum). + * PE11 - PIN11 (output pushpull maximum). + * PE12 - PIN12 (output pushpull maximum). + * PE13 - PIN13 (output pushpull maximum). + * PE14 - PIN14 (output pushpull maximum). + * PE15 - PIN15 (output pushpull maximum). + */ +#define VAL_GPIOE_MODER (PIN_MODE_INPUT(GPIOE_PIN0) | \ + PIN_MODE_INPUT(GPIOE_PIN1) | \ + PIN_MODE_INPUT(GPIOE_PIN2) |\ + PIN_MODE_OUTPUT(GPIOE_PIN3) | \ + PIN_MODE_INPUT(GPIOE_PIN4) |\ + PIN_MODE_INPUT(GPIOE_PIN5) |\ + PIN_MODE_INPUT(GPIOE_PIN6) | \ + PIN_MODE_INPUT(GPIOE_PIN7) | \ + PIN_MODE_OUTPUT(GPIOE_PIN8) | \ + PIN_MODE_OUTPUT(GPIOE_PIN9) | \ + PIN_MODE_OUTPUT(GPIOE_PIN10) | \ + PIN_MODE_OUTPUT(GPIOE_PIN11) | \ + PIN_MODE_OUTPUT(GPIOE_PIN12) | \ + PIN_MODE_OUTPUT(GPIOE_PIN13) | \ + PIN_MODE_OUTPUT(GPIOE_PIN14) | \ + PIN_MODE_OUTPUT(GPIOE_PIN15)) +#define VAL_GPIOE_OTYPER (PIN_OTYPE_PUSHPULL(GPIOE_PIN0) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN1) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN2) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN4) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN5) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN10) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOE_PIN14) |\ + PIN_OTYPE_PUSHPULL(GPIOE_PIN15)) +#define VAL_GPIOE_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOE_PIN0) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN1) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN2) |\ + PIN_OSPEED_HIGH(GPIOE_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN4) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN5) |\ + PIN_OSPEED_VERYLOW(GPIOE_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOE_PIN7) | \ + PIN_OSPEED_HIGH(GPIOE_PIN8) | \ + PIN_OSPEED_HIGH(GPIOE_PIN9) | \ + PIN_OSPEED_HIGH(GPIOE_PIN10) | \ + PIN_OSPEED_HIGH(GPIOE_PIN11) | \ + PIN_OSPEED_HIGH(GPIOE_PIN12) | \ + PIN_OSPEED_HIGH(GPIOE_PIN13) | \ + PIN_OSPEED_HIGH(GPIOE_PIN14) | \ + PIN_OSPEED_HIGH(GPIOE_PIN15)) +#define VAL_GPIOE_PUPDR (PIN_PUPDR_PULLUP(GPIOE_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN2) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN4) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN5) |\ + PIN_PUPDR_PULLUP(GPIOE_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN10) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOE_PIN12) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN13) | \ + PIN_PUPDR_FLOATING(GPIOE_PIN14) |\ + PIN_PUPDR_FLOATING(GPIOE_PIN15)) +#define VAL_GPIOE_ODR (PIN_ODR_HIGH(GPIOE_PIN0) | \ + PIN_ODR_HIGH(GPIOE_PIN1) | \ + PIN_ODR_HIGH(GPIOE_PIN2) | \ + PIN_ODR_HIGH(GPIOE_PIN3) | \ + PIN_ODR_HIGH(GPIOE_PIN4) | \ + PIN_ODR_HIGH(GPIOE_PIN5) | \ + PIN_ODR_HIGH(GPIOE_PIN6) | \ + PIN_ODR_HIGH(GPIOE_PIN7) | \ + PIN_ODR_LOW(GPIOE_PIN8) | \ + PIN_ODR_LOW(GPIOE_PIN9) | \ + PIN_ODR_LOW(GPIOE_PIN10) | \ + PIN_ODR_LOW(GPIOE_PIN11) | \ + PIN_ODR_LOW(GPIOE_PIN12) | \ + PIN_ODR_LOW(GPIOE_PIN13) | \ + PIN_ODR_LOW(GPIOE_PIN14) | \ + PIN_ODR_LOW(GPIOE_PIN15)) +#define VAL_GPIOE_AFRL (PIN_AFIO_AF(GPIOE_PIN0, 0) | \ + PIN_AFIO_AF(GPIOE_PIN1, 0) | \ + PIN_AFIO_AF(GPIOE_PIN2, 0) |\ + PIN_AFIO_AF(GPIOE_PIN3, 0) | \ + PIN_AFIO_AF(GPIOE_PIN4, 0) |\ + PIN_AFIO_AF(GPIOE_PIN5, 0) |\ + PIN_AFIO_AF(GPIOE_PIN6, 0) | \ + PIN_AFIO_AF(GPIOE_PIN7, 0)) +#define VAL_GPIOE_AFRH (PIN_AFIO_AF(GPIOE_PIN8, 0) | \ + PIN_AFIO_AF(GPIOE_PIN9, 0) | \ + PIN_AFIO_AF(GPIOE_PIN10, 0) | \ + PIN_AFIO_AF(GPIOE_PIN11, 0) | \ + PIN_AFIO_AF(GPIOE_PIN12, 0) | \ + PIN_AFIO_AF(GPIOE_PIN13, 0) | \ + PIN_AFIO_AF(GPIOE_PIN14, 0) | \ + PIN_AFIO_AF(GPIOE_PIN15, 0)) + +/* + * GPIOF setup: + * + * PF0 - I2C2_SDA (input floating). + * PF1 - I2C2_SCL (input floating). + * PF2 - PIN2 (input pullup). + * PF3 - PIN3 (input pullup). + * PF4 - PIN4 (input pullup). + * PF5 - PIN5 (input pullup). + * PF6 - PIN6 (input pullup). + * PF7 - PIN7 (input pullup). + * PF8 - PIN8 (input pullup). + * PF9 - PIN9 (input pullup). + * PF10 - PIN10 (input pullup). + * PF11 - PIN11 (input pullup). + * PF12 - PIN12 (input pullup). + * PF13 - PIN13 (input pullup). + * PF14 - PIN14 (input pullup). + * PF15 - PIN15 (input pullup). + */ +#define VAL_GPIOF_MODER (PIN_MODE_INPUT(GPIOF_I2C2_SDA) | \ + PIN_MODE_INPUT(GPIOF_I2C2_SCL) | \ + PIN_MODE_INPUT(GPIOF_PIN2) | \ + PIN_MODE_INPUT(GPIOF_PIN3) | \ + PIN_MODE_INPUT(GPIOF_PIN4) | \ + PIN_MODE_INPUT(GPIOF_PIN5) | \ + PIN_MODE_INPUT(GPIOF_PIN6) | \ + PIN_MODE_INPUT(GPIOF_PIN7) | \ + PIN_MODE_INPUT(GPIOF_PIN8) | \ + PIN_MODE_INPUT(GPIOF_PIN9) | \ + PIN_MODE_INPUT(GPIOF_PIN10) | \ + PIN_MODE_INPUT(GPIOF_PIN11) | \ + PIN_MODE_INPUT(GPIOF_PIN12) | \ + PIN_MODE_INPUT(GPIOF_PIN13) | \ + PIN_MODE_INPUT(GPIOF_PIN14) | \ + PIN_MODE_INPUT(GPIOF_PIN15)) +#define VAL_GPIOF_OTYPER (PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SDA) | \ + PIN_OTYPE_PUSHPULL(GPIOF_I2C2_SCL) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOF_PIN15)) +#define VAL_GPIOF_OSPEEDR (PIN_OSPEED_HIGH(GPIOF_I2C2_SDA) | \ + PIN_OSPEED_HIGH(GPIOF_I2C2_SCL) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOF_PIN15)) +#define VAL_GPIOF_PUPDR (PIN_PUPDR_FLOATING(GPIOF_I2C2_SDA) | \ + PIN_PUPDR_FLOATING(GPIOF_I2C2_SCL) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOF_PIN15)) +#define VAL_GPIOF_ODR (PIN_ODR_HIGH(GPIOF_I2C2_SDA) | \ + PIN_ODR_HIGH(GPIOF_I2C2_SCL) | \ + PIN_ODR_HIGH(GPIOF_PIN2) | \ + PIN_ODR_HIGH(GPIOF_PIN3) | \ + PIN_ODR_HIGH(GPIOF_PIN4) | \ + PIN_ODR_HIGH(GPIOF_PIN5) | \ + PIN_ODR_HIGH(GPIOF_PIN6) | \ + PIN_ODR_HIGH(GPIOF_PIN7) | \ + PIN_ODR_HIGH(GPIOF_PIN8) | \ + PIN_ODR_HIGH(GPIOF_PIN9) | \ + PIN_ODR_HIGH(GPIOF_PIN10) | \ + PIN_ODR_HIGH(GPIOF_PIN11) | \ + PIN_ODR_HIGH(GPIOF_PIN12) | \ + PIN_ODR_HIGH(GPIOF_PIN13) | \ + PIN_ODR_HIGH(GPIOF_PIN14) | \ + PIN_ODR_HIGH(GPIOF_PIN15)) +#define VAL_GPIOF_AFRL (PIN_AFIO_AF(GPIOF_I2C2_SDA, 0) | \ + PIN_AFIO_AF(GPIOF_I2C2_SCL, 0) | \ + PIN_AFIO_AF(GPIOF_PIN2, 0) | \ + PIN_AFIO_AF(GPIOF_PIN3, 0) | \ + PIN_AFIO_AF(GPIOF_PIN4, 0) | \ + PIN_AFIO_AF(GPIOF_PIN5, 0) | \ + PIN_AFIO_AF(GPIOF_PIN6, 0) | \ + PIN_AFIO_AF(GPIOF_PIN7, 0)) +#define VAL_GPIOF_AFRH (PIN_AFIO_AF(GPIOF_PIN8, 0) | \ + PIN_AFIO_AF(GPIOF_PIN9, 0) | \ + PIN_AFIO_AF(GPIOF_PIN10, 0) | \ + PIN_AFIO_AF(GPIOF_PIN11, 0) | \ + PIN_AFIO_AF(GPIOF_PIN12, 0) | \ + PIN_AFIO_AF(GPIOF_PIN13, 0) | \ + PIN_AFIO_AF(GPIOF_PIN14, 0) | \ + PIN_AFIO_AF(GPIOF_PIN15, 0)) + +/* + * GPIOG setup: + * + * PG0 - PIN0 (input pullup). + * PG1 - PIN1 (input pullup). + * PG2 - PIN2 (input pullup). + * PG3 - PIN3 (input pullup). + * PG4 - PIN4 (input pullup). + * PG5 - PIN5 (input pullup). + * PG6 - PIN6 (input pullup). + * PG7 - PIN7 (input pullup). + * PG8 - PIN8 (input pullup). + * PG9 - PIN9 (input pullup). + * PG10 - PIN10 (input pullup). + * PG11 - PIN11 (input pullup). + * PG12 - PIN12 (input pullup). + * PG13 - PIN13 (input pullup). + * PG14 - PIN14 (input pullup). + * PG15 - PIN15 (input pullup). + */ +#define VAL_GPIOG_MODER (PIN_MODE_INPUT(GPIOG_PIN0) | \ + PIN_MODE_INPUT(GPIOG_PIN1) | \ + PIN_MODE_INPUT(GPIOG_PIN2) | \ + PIN_MODE_INPUT(GPIOG_PIN3) | \ + PIN_MODE_INPUT(GPIOG_PIN4) | \ + PIN_MODE_INPUT(GPIOG_PIN5) | \ + PIN_MODE_INPUT(GPIOG_PIN6) | \ + PIN_MODE_INPUT(GPIOG_PIN7) | \ + PIN_MODE_INPUT(GPIOG_PIN8) | \ + PIN_MODE_INPUT(GPIOG_PIN9) | \ + PIN_MODE_INPUT(GPIOG_PIN10) | \ + PIN_MODE_INPUT(GPIOG_PIN11) | \ + PIN_MODE_INPUT(GPIOG_PIN12) | \ + PIN_MODE_INPUT(GPIOG_PIN13) | \ + PIN_MODE_INPUT(GPIOG_PIN14) | \ + PIN_MODE_INPUT(GPIOG_PIN15)) +#define VAL_GPIOG_OTYPER (PIN_OTYPE_PUSHPULL(GPIOG_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOG_PIN15)) +#define VAL_GPIOG_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOG_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOG_PIN15)) +#define VAL_GPIOG_PUPDR (PIN_PUPDR_PULLUP(GPIOG_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOG_PIN15)) +#define VAL_GPIOG_ODR (PIN_ODR_HIGH(GPIOG_PIN0) | \ + PIN_ODR_HIGH(GPIOG_PIN1) | \ + PIN_ODR_HIGH(GPIOG_PIN2) | \ + PIN_ODR_HIGH(GPIOG_PIN3) | \ + PIN_ODR_HIGH(GPIOG_PIN4) | \ + PIN_ODR_HIGH(GPIOG_PIN5) | \ + PIN_ODR_HIGH(GPIOG_PIN6) | \ + PIN_ODR_HIGH(GPIOG_PIN7) | \ + PIN_ODR_HIGH(GPIOG_PIN8) | \ + PIN_ODR_HIGH(GPIOG_PIN9) | \ + PIN_ODR_HIGH(GPIOG_PIN10) | \ + PIN_ODR_HIGH(GPIOG_PIN11) | \ + PIN_ODR_HIGH(GPIOG_PIN12) | \ + PIN_ODR_HIGH(GPIOG_PIN13) | \ + PIN_ODR_HIGH(GPIOG_PIN14) | \ + PIN_ODR_HIGH(GPIOG_PIN15)) +#define VAL_GPIOG_AFRL (PIN_AFIO_AF(GPIOG_PIN0, 0) | \ + PIN_AFIO_AF(GPIOG_PIN1, 0) | \ + PIN_AFIO_AF(GPIOG_PIN2, 0) | \ + PIN_AFIO_AF(GPIOG_PIN3, 0) | \ + PIN_AFIO_AF(GPIOG_PIN4, 0) | \ + PIN_AFIO_AF(GPIOG_PIN5, 0) | \ + PIN_AFIO_AF(GPIOG_PIN6, 0) | \ + PIN_AFIO_AF(GPIOG_PIN7, 0)) +#define VAL_GPIOG_AFRH (PIN_AFIO_AF(GPIOG_PIN8, 0) | \ + PIN_AFIO_AF(GPIOG_PIN9, 0) | \ + PIN_AFIO_AF(GPIOG_PIN10, 0) | \ + PIN_AFIO_AF(GPIOG_PIN11, 0) | \ + PIN_AFIO_AF(GPIOG_PIN12, 0) | \ + PIN_AFIO_AF(GPIOG_PIN13, 0) | \ + PIN_AFIO_AF(GPIOG_PIN14, 0) | \ + PIN_AFIO_AF(GPIOG_PIN15, 0)) + +/* + * GPIOH setup: + * + * PH0 - PIN0 (input pullup). + * PH1 - PIN1 (input pullup). + * PH2 - PIN2 (input pullup). + * PH3 - PIN3 (input pullup). + * PH4 - PIN4 (input pullup). + * PH5 - PIN5 (input pullup). + * PH6 - PIN6 (input pullup). + * PH7 - PIN7 (input pullup). + * PH8 - PIN8 (input pullup). + * PH9 - PIN9 (input pullup). + * PH10 - PIN10 (input pullup). + * PH11 - PIN11 (input pullup). + * PH12 - PIN12 (input pullup). + * PH13 - PIN13 (input pullup). + * PH14 - PIN14 (input pullup). + * PH15 - PIN15 (input pullup). + */ +#define VAL_GPIOH_MODER (PIN_MODE_INPUT(GPIOH_PIN0) | \ + PIN_MODE_INPUT(GPIOH_PIN1) | \ + PIN_MODE_INPUT(GPIOH_PIN2) | \ + PIN_MODE_INPUT(GPIOH_PIN3) | \ + PIN_MODE_INPUT(GPIOH_PIN4) | \ + PIN_MODE_INPUT(GPIOH_PIN5) | \ + PIN_MODE_INPUT(GPIOH_PIN6) | \ + PIN_MODE_INPUT(GPIOH_PIN7) | \ + PIN_MODE_INPUT(GPIOH_PIN8) | \ + PIN_MODE_INPUT(GPIOH_PIN9) | \ + PIN_MODE_INPUT(GPIOH_PIN10) | \ + PIN_MODE_INPUT(GPIOH_PIN11) | \ + PIN_MODE_INPUT(GPIOH_PIN12) | \ + PIN_MODE_INPUT(GPIOH_PIN13) | \ + PIN_MODE_INPUT(GPIOH_PIN14) | \ + PIN_MODE_INPUT(GPIOH_PIN15)) +#define VAL_GPIOH_OTYPER (PIN_OTYPE_PUSHPULL(GPIOH_PIN0) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN1) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN2) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN3) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN4) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN5) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN6) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN7) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN8) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN9) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN10) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN11) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN12) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN13) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN14) | \ + PIN_OTYPE_PUSHPULL(GPIOH_PIN15)) +#define VAL_GPIOH_OSPEEDR (PIN_OSPEED_VERYLOW(GPIOH_PIN0) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN1) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN2) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN3) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN4) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN5) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN6) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN7) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN8) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN9) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN10) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN11) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN12) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN13) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN14) | \ + PIN_OSPEED_VERYLOW(GPIOH_PIN15)) +#define VAL_GPIOH_PUPDR (PIN_PUPDR_PULLUP(GPIOH_PIN0) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN1) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN2) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN3) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN4) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN5) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN6) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN7) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN8) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN9) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN10) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN11) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN12) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN13) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN14) | \ + PIN_PUPDR_PULLUP(GPIOH_PIN15)) +#define VAL_GPIOH_ODR (PIN_ODR_HIGH(GPIOH_PIN0) | \ + PIN_ODR_HIGH(GPIOH_PIN1) | \ + PIN_ODR_HIGH(GPIOH_PIN2) | \ + PIN_ODR_HIGH(GPIOH_PIN3) | \ + PIN_ODR_HIGH(GPIOH_PIN4) | \ + PIN_ODR_HIGH(GPIOH_PIN5) | \ + PIN_ODR_HIGH(GPIOH_PIN6) | \ + PIN_ODR_HIGH(GPIOH_PIN7) | \ + PIN_ODR_HIGH(GPIOH_PIN8) | \ + PIN_ODR_HIGH(GPIOH_PIN9) | \ + PIN_ODR_HIGH(GPIOH_PIN10) | \ + PIN_ODR_HIGH(GPIOH_PIN11) | \ + PIN_ODR_HIGH(GPIOH_PIN12) | \ + PIN_ODR_HIGH(GPIOH_PIN13) | \ + PIN_ODR_HIGH(GPIOH_PIN14) | \ + PIN_ODR_HIGH(GPIOH_PIN15)) +#define VAL_GPIOH_AFRL (PIN_AFIO_AF(GPIOH_PIN0, 0) | \ + PIN_AFIO_AF(GPIOH_PIN1, 0) | \ + PIN_AFIO_AF(GPIOH_PIN2, 0) | \ + PIN_AFIO_AF(GPIOH_PIN3, 0) | \ + PIN_AFIO_AF(GPIOH_PIN4, 0) | \ + PIN_AFIO_AF(GPIOH_PIN5, 0) | \ + PIN_AFIO_AF(GPIOH_PIN6, 0) | \ + PIN_AFIO_AF(GPIOH_PIN7, 0)) +#define VAL_GPIOH_AFRH (PIN_AFIO_AF(GPIOH_PIN8, 0) | \ + PIN_AFIO_AF(GPIOH_PIN9, 0) | \ + PIN_AFIO_AF(GPIOH_PIN10, 0) | \ + PIN_AFIO_AF(GPIOH_PIN11, 0) | \ + PIN_AFIO_AF(GPIOH_PIN12, 0) | \ + PIN_AFIO_AF(GPIOH_PIN13, 0) | \ + PIN_AFIO_AF(GPIOH_PIN14, 0) | \ + PIN_AFIO_AF(GPIOH_PIN15, 0)) + + +/* + * USB bus activation macro, required by the USB driver. + */ +// #define usb_lld_connect_bus(usbp) +#define usb_lld_connect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_ALTERNATE(14))) +// #define usb_lld_connect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_INPUT) +/* + * USB bus de-activation macro, required by the USB driver. + */ +// #define usb_lld_disconnect_bus(usbp) +#define usb_lld_disconnect_bus(usbp) (palSetPadMode(GPIOA, GPIOA_USB_DP, PAL_MODE_OUTPUT_PUSHPULL)); palClearPad(GPIOA, GPIOA_USB_DP) +// #define usb_lld_disconnect_bus(usbp) palSetPadMode(GPIOA, 12, PAL_MODE_OUTPUT_PUSHPULL); palClearPad(GPIOA, 12) + +#if !defined(_FROM_ASM_) +#ifdef __cplusplus +extern "C" { +#endif + void boardInit(void); +#ifdef __cplusplus +} +#endif +#endif /* _FROM_ASM_ */ + +#endif /* _BOARD_H_ */ diff --git a/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.mk b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.mk new file mode 100644 index 0000000000..43377629a3 --- /dev/null +++ b/keyboards/muon_light/boards/GENERIC_STM32_F303XC/board.mk @@ -0,0 +1,5 @@ +# List of all the board related files. +BOARDSRC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC/board.c + +# Required include directories +BOARDINC = $(BOARD_PATH)/boards/GENERIC_STM32_F303XC diff --git a/keyboards/muon_light/bootloader_defs.h b/keyboards/muon_light/bootloader_defs.h new file mode 100644 index 0000000000..3b0e9d20a6 --- /dev/null +++ b/keyboards/muon_light/bootloader_defs.h @@ -0,0 +1,7 @@ +/* Address for jumping to bootloader on STM32 chips. */ +/* It is chip dependent, the correct number can be looked up here: + * http://www.st.com/web/en/resource/technical/document/application_note/CD00167594.pdf + * This also requires a patch to chibios: + * /tmk_core/tool/chibios/ch-bootloader-jump.patch + */ +#define STM32_BOOTLOADER_ADDRESS 0x1FFFD800 diff --git a/keyboards/muon_light/chconf.h b/keyboards/muon_light/chconf.h new file mode 100644 index 0000000000..5a9b833107 --- /dev/null +++ b/keyboards/muon_light/chconf.h @@ -0,0 +1,520 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/chconf.h + * @brief Configuration file template. + * @details A copy of this file must be placed in each project directory, it + * contains the application specific kernel settings. + * + * @addtogroup config + * @details Kernel related settings and hooks. + * @{ + */ + +#ifndef CHCONF_H +#define CHCONF_H + +#define _CHIBIOS_RT_CONF_ + +/*===========================================================================*/ +/** + * @name System timers settings + * @{ + */ +/*===========================================================================*/ + +/** + * @brief System time counter resolution. + * @note Allowed values are 16 or 32 bits. + */ +#define CH_CFG_ST_RESOLUTION 32 + +/** + * @brief System tick frequency. + * @details Frequency of the system timer that drives the system ticks. This + * setting also defines the system tick time unit. + */ +#define CH_CFG_ST_FREQUENCY 10000 + +/** + * @brief Time delta constant for the tick-less mode. + * @note If this value is zero then the system uses the classic + * periodic tick. This value represents the minimum number + * of ticks that is safe to specify in a timeout directive. + * The value one is not valid, timeouts are rounded up to + * this value. + */ +#define CH_CFG_ST_TIMEDELTA 2 + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel parameters and options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Round robin interval. + * @details This constant is the number of system ticks allowed for the + * threads before preemption occurs. Setting this value to zero + * disables the preemption for threads with equal priority and the + * round robin becomes cooperative. Note that higher priority + * threads can still preempt, the kernel is always preemptive. + * @note Disabling the round robin preemption makes the kernel more compact + * and generally faster. + * @note The round robin preemption is not supported in tickless mode and + * must be set to zero in that case. + */ +#define CH_CFG_TIME_QUANTUM 0 + +/** + * @brief Managed RAM size. + * @details Size of the RAM area to be managed by the OS. If set to zero + * then the whole available RAM is used. The core memory is made + * available to the heap allocator and/or can be used directly through + * the simplified core memory allocator. + * + * @note In order to let the OS manage the whole RAM the linker script must + * provide the @p __heap_base__ and @p __heap_end__ symbols. + * @note Requires @p CH_CFG_USE_MEMCORE. + */ +#define CH_CFG_MEMCORE_SIZE 0 + +/** + * @brief Idle thread automatic spawn suppression. + * @details When this option is activated the function @p chSysInit() + * does not spawn the idle thread. The application @p main() + * function becomes the idle thread and must implement an + * infinite loop. + */ +#define CH_CFG_NO_IDLE_THREAD FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Performance options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief OS optimization. + * @details If enabled then time efficient rather than space efficient code + * is used when two possible implementations exist. + * + * @note This is not related to the compiler optimization options. + * @note The default is @p TRUE. + */ +#define CH_CFG_OPTIMIZE_SPEED TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Subsystem options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Time Measurement APIs. + * @details If enabled then the time measurement APIs are included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_TM TRUE + +/** + * @brief Threads registry APIs. + * @details If enabled then the registry APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_REGISTRY TRUE + +/** + * @brief Threads synchronization APIs. + * @details If enabled then the @p chThdWait() function is included in + * the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_WAITEXIT TRUE + +/** + * @brief Semaphores APIs. + * @details If enabled then the Semaphores APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_SEMAPHORES TRUE + +/** + * @brief Semaphores queuing mode. + * @details If enabled then the threads are enqueued on semaphores by + * priority rather than in FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_SEMAPHORES_PRIORITY FALSE + +/** + * @brief Mutexes APIs. + * @details If enabled then the mutexes APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MUTEXES TRUE + +/** + * @brief Enables recursive behavior on mutexes. + * @note Recursive mutexes are heavier and have an increased + * memory footprint. + * + * @note The default is @p FALSE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_MUTEXES_RECURSIVE FALSE + +/** + * @brief Conditional Variables APIs. + * @details If enabled then the conditional variables APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MUTEXES. + */ +#define CH_CFG_USE_CONDVARS TRUE + +/** + * @brief Conditional Variables APIs with timeout. + * @details If enabled then the conditional variables APIs with timeout + * specification are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_CONDVARS. + */ +#define CH_CFG_USE_CONDVARS_TIMEOUT TRUE + +/** + * @brief Events Flags APIs. + * @details If enabled then the event flags APIs are included in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_EVENTS TRUE + +/** + * @brief Events Flags APIs with timeout. + * @details If enabled then the events APIs with timeout specification + * are included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_EVENTS. + */ +#define CH_CFG_USE_EVENTS_TIMEOUT TRUE + +/** + * @brief Synchronous Messages APIs. + * @details If enabled then the synchronous messages APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MESSAGES TRUE + +/** + * @brief Synchronous Messages queuing mode. + * @details If enabled then messages are served by priority rather than in + * FIFO order. + * + * @note The default is @p FALSE. Enable this if you have special + * requirements. + * @note Requires @p CH_CFG_USE_MESSAGES. + */ +#define CH_CFG_USE_MESSAGES_PRIORITY TRUE + +/** + * @brief Mailboxes APIs. + * @details If enabled then the asynchronous messages (mailboxes) APIs are + * included in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_SEMAPHORES. + */ +#define CH_CFG_USE_MAILBOXES TRUE + +/** + * @brief Core Memory Manager APIs. + * @details If enabled then the core memory manager APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMCORE TRUE + +/** + * @brief Heap Allocator APIs. + * @details If enabled then the memory heap allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_MEMCORE and either @p CH_CFG_USE_MUTEXES or + * @p CH_CFG_USE_SEMAPHORES. + * @note Mutexes are recommended. + */ +#define CH_CFG_USE_HEAP TRUE + +/** + * @brief Memory Pools Allocator APIs. + * @details If enabled then the memory pools allocator APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + */ +#define CH_CFG_USE_MEMPOOLS TRUE + +/** + * @brief Dynamic Threads APIs. + * @details If enabled then the dynamic threads creation APIs are included + * in the kernel. + * + * @note The default is @p TRUE. + * @note Requires @p CH_CFG_USE_WAITEXIT. + * @note Requires @p CH_CFG_USE_HEAP and/or @p CH_CFG_USE_MEMPOOLS. + */ +#define CH_CFG_USE_DYNAMIC TRUE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Debug options + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Debug option, kernel statistics. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_STATISTICS FALSE + +/** + * @brief Debug option, system state check. + * @details If enabled the correct call protocol for system APIs is checked + * at runtime. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_SYSTEM_STATE_CHECK FALSE + +/** + * @brief Debug option, parameters checks. + * @details If enabled then the checks on the API functions input + * parameters are activated. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_CHECKS FALSE + +/** + * @brief Debug option, consistency checks. + * @details If enabled then all the assertions in the kernel code are + * activated. This includes consistency checks inside the kernel, + * runtime anomalies and port-defined checks. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_ENABLE_ASSERTS FALSE + +/** + * @brief Debug option, trace buffer. + * @details If enabled then the trace buffer is activated. + * + * @note The default is @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_MASK CH_DBG_TRACE_MASK_DISABLED + +/** + * @brief Trace buffer entries. + * @note The trace buffer is only allocated if @p CH_DBG_TRACE_MASK is + * different from @p CH_DBG_TRACE_MASK_DISABLED. + */ +#define CH_DBG_TRACE_BUFFER_SIZE 128 + +/** + * @brief Debug option, stack checks. + * @details If enabled then a runtime stack check is performed. + * + * @note The default is @p FALSE. + * @note The stack check is performed in a architecture/port dependent way. + * It may not be implemented or some ports. + * @note The default failure mode is to halt the system with the global + * @p panic_msg variable set to @p NULL. + */ +#define CH_DBG_ENABLE_STACK_CHECK TRUE + +/** + * @brief Debug option, stacks initialization. + * @details If enabled then the threads working area is filled with a byte + * value when a thread is created. This can be useful for the + * runtime measurement of the used stack. + * + * @note The default is @p FALSE. + */ +#define CH_DBG_FILL_THREADS FALSE + +/** + * @brief Debug option, threads profiling. + * @details If enabled then a field is added to the @p thread_t structure that + * counts the system ticks occurred while executing the thread. + * + * @note The default is @p FALSE. + * @note This debug option is not currently compatible with the + * tickless mode. + */ +#define CH_DBG_THREADS_PROFILING FALSE + +/** @} */ + +/*===========================================================================*/ +/** + * @name Kernel hooks + * @{ + */ +/*===========================================================================*/ + +/** + * @brief Threads descriptor structure extension. + * @details User fields added to the end of the @p thread_t structure. + */ +#define CH_CFG_THREAD_EXTRA_FIELDS \ + /* Add threads custom fields here.*/ + +/** + * @brief Threads initialization hook. + * @details User initialization code added to the @p chThdInit() API. + * + * @note It is invoked from within @p chThdInit() and implicitly from all + * the threads creation APIs. + */ +#define CH_CFG_THREAD_INIT_HOOK(tp) { \ + /* Add threads initialization code here.*/ \ +} + +/** + * @brief Threads finalization hook. + * @details User finalization code added to the @p chThdExit() API. + */ +#define CH_CFG_THREAD_EXIT_HOOK(tp) { \ + /* Add threads finalization code here.*/ \ +} + +/** + * @brief Context switch hook. + * @details This hook is invoked just before switching between threads. + */ +#define CH_CFG_CONTEXT_SWITCH_HOOK(ntp, otp) { \ + /* Context switch code here.*/ \ +} + +/** + * @brief ISR enter hook. + */ +#define CH_CFG_IRQ_PROLOGUE_HOOK() { \ + /* IRQ prologue code here.*/ \ +} + +/** + * @brief ISR exit hook. + */ +#define CH_CFG_IRQ_EPILOGUE_HOOK() { \ + /* IRQ epilogue code here.*/ \ +} + +/** + * @brief Idle thread enter hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to activate a power saving mode. + */ +#define CH_CFG_IDLE_ENTER_HOOK() { \ + /* Idle-enter code here.*/ \ +} + +/** + * @brief Idle thread leave hook. + * @note This hook is invoked within a critical zone, no OS functions + * should be invoked from here. + * @note This macro can be used to deactivate a power saving mode. + */ +#define CH_CFG_IDLE_LEAVE_HOOK() { \ + /* Idle-leave code here.*/ \ +} + +/** + * @brief Idle Loop hook. + * @details This hook is continuously invoked by the idle thread loop. + */ +#define CH_CFG_IDLE_LOOP_HOOK() { \ + /* Idle loop code here.*/ \ +} + +/** + * @brief System tick event hook. + * @details This hook is invoked in the system tick handler immediately + * after processing the virtual timers queue. + */ +#define CH_CFG_SYSTEM_TICK_HOOK() { \ + /* System tick event code here.*/ \ +} + +/** + * @brief System halt hook. + * @details This hook is invoked in case to a system halting error before + * the system is halted. + */ +#define CH_CFG_SYSTEM_HALT_HOOK(reason) { \ + /* System halt code here.*/ \ +} + +/** + * @brief Trace hook. + * @details This hook is invoked each time a new record is written in the + * trace buffer. + */ +#define CH_CFG_TRACE_HOOK(tep) { \ + /* Trace code here.*/ \ +} + +/** @} */ + +/*===========================================================================*/ +/* Port-specific settings (override port settings defaulted in chcore.h). */ +/*===========================================================================*/ + +#endif /* CHCONF_H */ + +/** @} */ diff --git a/keyboards/muon_light/config.h b/keyboards/muon_light/config.h new file mode 100644 index 0000000000..b4c7b6051b --- /dev/null +++ b/keyboards/muon_light/config.h @@ -0,0 +1,152 @@ +/* +Copyright 2012 Jun Wako + +This program is free software: you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation, either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program. If not, see . +*/ + +#ifndef CONFIG_H +#define CONFIG_H + +#include "config_common.h" + +/* USB Device descriptor parameter */ +#define VENDOR_ID 0xFEED +#define PRODUCT_ID 0x6160 +#define MANUFACTURER OLKB +#define PRODUCT Muon Light +#define DESCRIPTION A compact ortholinear keyboard +#define DEVICE_VER 0x0001 + +/* key matrix size */ +#define MATRIX_ROWS 4 +#define MATRIX_COLS 6 + +/* + * Keyboard Matrix Assignments + * + * Change this to how you wired your keyboard + * COLS: AVR pins used for columns, left to right + * ROWS: AVR pins used for rows, top to bottom + * DIODE_DIRECTION: COL2ROW = COL = Anode (+), ROW = Cathode (-, marked on diode) + * ROW2COL = ROW = Anode (+), COL = Cathode (-, marked on diode) + * +*/ +#undef MATRIX_ROW_PINS +#undef MATRIX_COL_PINS +#define MATRIX_ROW_PINS { B5, B10, A9, A8 } +#define MATRIX_COL_PINS { A10, B2, A15, A0, A1, A2 } + +/* COL2ROW or ROW2COL */ +#define DIODE_DIRECTION COL2ROW + +#define MUSIC_MAP + +#define NUMBER_OF_ENCODERS 1 +#define ENCODERS_PAD_A { B12 } +#define ENCODERS_PAD_B { B13 } + +/* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ +#define DEBOUNCE 0 + +/* Prevent modifiers from being stuck on after layer changes. */ +#define PREVENT_STUCK_MODIFIERS + +/* Mechanical locking support. Use KC_LCAP, KC_LNUM or KC_LSCR instead in keymap */ +//#define LOCKING_SUPPORT_ENABLE +/* Locking resynchronize hack */ +//#define LOCKING_RESYNC_ENABLE + +/* + * Force NKRO + * + * Force NKRO (nKey Rollover) to be enabled by default, regardless of the saved + * state in the bootmagic EEPROM settings. (Note that NKRO must be enabled in the + * makefile for this to work.) + * + * If forced on, NKRO can be disabled via magic key (default = LShift+RShift+N) + * until the next keyboard reset. + * + * NKRO may prevent your keystrokes from being detected in the BIOS, but it is + * fully operational during normal computer usage. + * + * For a less heavy-handed approach, enable NKRO via magic key (LShift+RShift+N) + * or via bootmagic (hold SPACE+N while plugging in the keyboard). Once set by + * bootmagic, NKRO mode will always be enabled until it is toggled again during a + * power-up. + * + */ +//#define FORCE_NKRO + +/* key combination for magic key command */ +#define IS_COMMAND() ( \ + keyboard_report->mods == (MOD_BIT(KC_LSHIFT) | MOD_BIT(KC_RSHIFT)) \ +) + +/* + * Feature disable options + * These options are also useful to firmware size reduction. + */ + +/* disable debug print */ +//#define NO_DEBUG + +/* disable print */ +//#define NO_PRINT + +/* disable action features */ +//#define NO_ACTION_LAYER +//#define NO_ACTION_TAPPING +//#define NO_ACTION_ONESHOT +//#define NO_ACTION_MACRO +//#define NO_ACTION_FUNCTION + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ +//#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 1 + +// This is a 7-bit address, that gets left-shifted and bit 0 +// set to 0 for write, 1 for read (as per I2C protocol) +// The address will vary depending on your wiring: +// 0b1110100 AD <-> GND +// 0b1110111 AD <-> VCC +// 0b1110101 AD <-> SCL +// 0b1110110 AD <-> SDA +#define DRIVER_ADDR_1 0b1110100 +#define DRIVER_ADDR_2 0b1110110 + +#define DRIVER_COUNT 2 +#define DRIVER_1_LED_TOTAL 25 +#define DRIVER_2_LED_TOTAL 24 +#define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL + +#endif diff --git a/keyboards/muon_light/halconf.h b/keyboards/muon_light/halconf.h new file mode 100644 index 0000000000..c3e0cbb728 --- /dev/null +++ b/keyboards/muon_light/halconf.h @@ -0,0 +1,388 @@ +/* + ChibiOS - Copyright (C) 2006..2016 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/** + * @file templates/halconf.h + * @brief HAL configuration header. + * @details HAL configuration file, this file allows to enable or disable the + * various device drivers from your application. You may also use + * this file in order to override the device drivers default settings. + * + * @addtogroup HAL_CONF + * @{ + */ + +#ifndef HALCONF_H +#define HALCONF_H + +#include "mcuconf.h" + +/** + * @brief Enables the PAL subsystem. + */ +#if !defined(HAL_USE_PAL) || defined(__DOXYGEN__) +#define HAL_USE_PAL TRUE +#endif + +/** + * @brief Enables the ADC subsystem. + */ +#if !defined(HAL_USE_ADC) || defined(__DOXYGEN__) +#define HAL_USE_ADC FALSE +#endif + +/** + * @brief Enables the CAN subsystem. + */ +#if !defined(HAL_USE_CAN) || defined(__DOXYGEN__) +#define HAL_USE_CAN FALSE +#endif + +/** + * @brief Enables the DAC subsystem. + */ +#if !defined(HAL_USE_DAC) || defined(__DOXYGEN__) +#define HAL_USE_DAC TRUE +#endif + +/** + * @brief Enables the EXT subsystem. + */ +#if !defined(HAL_USE_EXT) || defined(__DOXYGEN__) +#define HAL_USE_EXT FALSE +#endif + +/** + * @brief Enables the GPT subsystem. + */ +#if !defined(HAL_USE_GPT) || defined(__DOXYGEN__) +#define HAL_USE_GPT TRUE +#endif + +/** + * @brief Enables the I2C subsystem. + */ +#if !defined(HAL_USE_I2C) || defined(__DOXYGEN__) +#define HAL_USE_I2C TRUE +#endif + +/** + * @brief Enables the I2S subsystem. + */ +#if !defined(HAL_USE_I2S) || defined(__DOXYGEN__) +#define HAL_USE_I2S FALSE +#endif + +/** + * @brief Enables the ICU subsystem. + */ +#if !defined(HAL_USE_ICU) || defined(__DOXYGEN__) +#define HAL_USE_ICU FALSE +#endif + +/** + * @brief Enables the MAC subsystem. + */ +#if !defined(HAL_USE_MAC) || defined(__DOXYGEN__) +#define HAL_USE_MAC FALSE +#endif + +/** + * @brief Enables the MMC_SPI subsystem. + */ +#if !defined(HAL_USE_MMC_SPI) || defined(__DOXYGEN__) +#define HAL_USE_MMC_SPI FALSE +#endif + +/** + * @brief Enables the PWM subsystem. + */ +#if !defined(HAL_USE_PWM) || defined(__DOXYGEN__) +#define HAL_USE_PWM FALSE +#endif + +/** + * @brief Enables the QSPI subsystem. + */ +#if !defined(HAL_USE_QSPI) || defined(__DOXYGEN__) +#define HAL_USE_QSPI FALSE +#endif + +/** + * @brief Enables the RTC subsystem. + */ +#if !defined(HAL_USE_RTC) || defined(__DOXYGEN__) +#define HAL_USE_RTC FALSE +#endif + +/** + * @brief Enables the SDC subsystem. + */ +#if !defined(HAL_USE_SDC) || defined(__DOXYGEN__) +#define HAL_USE_SDC FALSE +#endif + +/** + * @brief Enables the SERIAL subsystem. + */ +#if !defined(HAL_USE_SERIAL) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL FALSE +#endif + +/** + * @brief Enables the SERIAL over USB subsystem. + */ +#if !defined(HAL_USE_SERIAL_USB) || defined(__DOXYGEN__) +#define HAL_USE_SERIAL_USB TRUE +#endif + +/** + * @brief Enables the SPI subsystem. + */ +#if !defined(HAL_USE_SPI) || defined(__DOXYGEN__) +#define HAL_USE_SPI FALSE +#endif + +/** + * @brief Enables the UART subsystem. + */ +#if !defined(HAL_USE_UART) || defined(__DOXYGEN__) +#define HAL_USE_UART FALSE +#endif + +/** + * @brief Enables the USB subsystem. + */ +#if !defined(HAL_USE_USB) || defined(__DOXYGEN__) +#define HAL_USE_USB TRUE +#endif + +/** + * @brief Enables the WDG subsystem. + */ +#if !defined(HAL_USE_WDG) || defined(__DOXYGEN__) +#define HAL_USE_WDG FALSE +#endif + +/*===========================================================================*/ +/* ADC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_WAIT) || defined(__DOXYGEN__) +#define ADC_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p adcAcquireBus() and @p adcReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(ADC_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define ADC_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* CAN driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Sleep mode related APIs inclusion switch. + */ +#if !defined(CAN_USE_SLEEP_MODE) || defined(__DOXYGEN__) +#define CAN_USE_SLEEP_MODE TRUE +#endif + +/*===========================================================================*/ +/* I2C driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* MAC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_ZERO_COPY) || defined(__DOXYGEN__) +#define MAC_USE_ZERO_COPY FALSE +#endif + +/** + * @brief Enables an event sources for incoming packets. + */ +#if !defined(MAC_USE_EVENTS) || defined(__DOXYGEN__) +#define MAC_USE_EVENTS TRUE +#endif + +/*===========================================================================*/ +/* MMC_SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + * This option is recommended also if the SPI driver does not + * use a DMA channel and heavily loads the CPU. + */ +#if !defined(MMC_NICE_WAITING) || defined(__DOXYGEN__) +#define MMC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SDC driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Number of initialization attempts before rejecting the card. + * @note Attempts are performed at 10mS intervals. + */ +#if !defined(SDC_INIT_RETRY) || defined(__DOXYGEN__) +#define SDC_INIT_RETRY 100 +#endif + +/** + * @brief Include support for MMC cards. + * @note MMC support is not yet implemented so this option must be kept + * at @p FALSE. + */ +#if !defined(SDC_MMC_SUPPORT) || defined(__DOXYGEN__) +#define SDC_MMC_SUPPORT FALSE +#endif + +/** + * @brief Delays insertions. + * @details If enabled this options inserts delays into the MMC waiting + * routines releasing some extra CPU time for the threads with + * lower priority, this may slow down the driver a bit however. + */ +#if !defined(SDC_NICE_WAITING) || defined(__DOXYGEN__) +#define SDC_NICE_WAITING TRUE +#endif + +/*===========================================================================*/ +/* SERIAL driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Default bit rate. + * @details Configuration parameter, this is the baud rate selected for the + * default configuration. + */ +#if !defined(SERIAL_DEFAULT_BITRATE) || defined(__DOXYGEN__) +#define SERIAL_DEFAULT_BITRATE 38400 +#endif + +/** + * @brief Serial buffers size. + * @details Configuration parameter, you can change the depth of the queue + * buffers depending on the requirements of your application. + * @note The default is 16 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_BUFFERS_SIZE 16 +#endif + +/*===========================================================================*/ +/* SERIAL_USB driver related setting. */ +/*===========================================================================*/ + +/** + * @brief Serial over USB buffers size. + * @details Configuration parameter, the buffer size must be a multiple of + * the USB data endpoint maximum packet size. + * @note The default is 256 bytes for both the transmission and receive + * buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_SIZE) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_SIZE 1 +#endif + +/** + * @brief Serial over USB number of buffers. + * @note The default is 2 buffers. + */ +#if !defined(SERIAL_USB_BUFFERS_NUMBER) || defined(__DOXYGEN__) +#define SERIAL_USB_BUFFERS_NUMBER 2 +#endif + +/*===========================================================================*/ +/* SPI driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_WAIT) || defined(__DOXYGEN__) +#define SPI_USE_WAIT TRUE +#endif + +/** + * @brief Enables the @p spiAcquireBus() and @p spiReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(SPI_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define SPI_USE_MUTUAL_EXCLUSION TRUE +#endif + +/*===========================================================================*/ +/* UART driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_WAIT) || defined(__DOXYGEN__) +#define UART_USE_WAIT FALSE +#endif + +/** + * @brief Enables the @p uartAcquireBus() and @p uartReleaseBus() APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(UART_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define UART_USE_MUTUAL_EXCLUSION FALSE +#endif + +/*===========================================================================*/ +/* USB driver related settings. */ +/*===========================================================================*/ + +/** + * @brief Enables synchronous APIs. + * @note Disabling this option saves both code and data space. + */ +#if !defined(USB_USE_WAIT) || defined(__DOXYGEN__) +#define USB_USE_WAIT TRUE +#endif + +#endif /* HALCONF_H */ + +/** @} */ diff --git a/keyboards/muon_light/info.json b/keyboards/muon_light/info.json new file mode 100644 index 0000000000..bed83b3903 --- /dev/null +++ b/keyboards/muon_light/info.json @@ -0,0 +1,38 @@ +{ + "keyboard_name": "Muon Light", + "keyboard_folder": "muon_light", + "url": "https://olkb.com/muon_light", + "maintainer": "jackhumbert", + "width": 6, + "height": 4, + "layouts": { + "LAYOUT_4x6_ortho": { + "key_count": 24, + "layout": [ + { "w": 1, "x": 0, "y": 0 }, + { "w": 1, "x": 1, "y": 0 }, + { "w": 1, "x": 2, "y": 0 }, + { "w": 1, "x": 3, "y": 0 }, + { "w": 1, "x": 4, "y": 0 }, + { "w": 1, "x": 5, "y": 0 }, + { "w": 1, "x": 0, "y": 1 }, + { "w": 1, "x": 1, "y": 1 }, + { "w": 1, "x": 2, "y": 1 }, + { "w": 1, "x": 3, "y": 1 }, + { "w": 1, "x": 4, "y": 1 }, + { "w": 1, "x": 5, "y": 1 }, + { "w": 1, "x": 0, "y": 2 }, + { "w": 1, "x": 1, "y": 2 }, + { "w": 1, "x": 2, "y": 2 }, + { "w": 1, "x": 3, "y": 2 }, + { "w": 1, "x": 4, "y": 2 }, + { "w": 1, "x": 5, "y": 2 }, + { "w": 1, "x": 0, "y": 3 }, + { "w": 1, "x": 1, "y": 3 }, + { "w": 1, "x": 2, "y": 3 }, + { "w": 1, "x": 3, "y": 3 }, + { "w": 1, "x": 4, "y": 3 }, + { "w": 1, "x": 5, "y": 3 } ] + } + } +} diff --git a/keyboards/muon_light/keymaps/default/config.h b/keyboards/muon_light/keymaps/default/config.h new file mode 100644 index 0000000000..fbd2fdb272 --- /dev/null +++ b/keyboards/muon_light/keymaps/default/config.h @@ -0,0 +1,43 @@ +#ifndef CONFIG_USER_H +#define CONFIG_USER_H + +#include "config_common.h" + +#ifdef AUDIO_ENABLE + #define STARTUP_SONG SONG(PLANCK_SOUND) + // #define STARTUP_SONG SONG(NO_SOUND) + + #define DEFAULT_LAYER_SONGS { SONG(QWERTY_SOUND), \ + SONG(COLEMAK_SOUND), \ + SONG(DVORAK_SOUND) \ + } +#endif + +/* + * MIDI options + */ + +/* Prevent use of disabled MIDI features in the keymap */ +//#define MIDI_ENABLE_STRICT 1 + +/* enable basic MIDI features: + - MIDI notes can be sent when in Music mode is on +*/ + +#define MIDI_BASIC + +/* enable advanced MIDI features: + - MIDI notes can be added to the keymap + - Octave shift and transpose + - Virtual sustain, portamento, and modulation wheel + - etc. +*/ +//#define MIDI_ADVANCED + +/* override number of MIDI tone keycodes (each octave adds 12 keycodes and allocates 12 bytes) */ +//#define MIDI_TONE_KEYCODE_OCTAVES 2 + +// Most tactile encoders have detents every 4 stages +#define ENCODER_RESOLUTION 4 + +#endif diff --git a/keyboards/muon_light/keymaps/default/keymap.c b/keyboards/muon_light/keymaps/default/keymap.c new file mode 100644 index 0000000000..e2ac79206b --- /dev/null +++ b/keyboards/muon_light/keymaps/default/keymap.c @@ -0,0 +1,309 @@ +/* Copyright 2015-2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "muon_light.h" +#include "action_layer.h" + +extern keymap_config_t keymap_config; + +enum planck_layers { + _QWERTY, + _COLEMAK, + _DVORAK, + _LOWER, + _RAISE, + _PLOVER, + _ADJUST +}; + +enum planck_keycodes { + QWERTY = SAFE_RANGE, + COLEMAK, + DVORAK, + PLOVER, + BACKLIT, + EXT_PLV +}; + +#define LOWER MO(_LOWER) +#define RAISE MO(_RAISE) + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + +/* Qwerty + * ,-----------------------------------------------------------------------------------. + * | Tab | Q | W | E | R | T | Y | U | I | O | P | Bksp | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | Esc | A | S | D | F | G | H | J | K | L | ; | " | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | Shift| Z | X | C | V | B | N | M | , | . | / |Enter | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | + * `-----------------------------------------------------------------------------------' + */ +[_QWERTY] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_TAB, KC_Q, KC_W, KC_E, KC_R, KC_T, + KC_ESC, KC_A, KC_S, KC_D, KC_F, KC_G, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC + #else + KC_Y, KC_U, KC_I, KC_O, KC_P, KC_BSPC, + KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, + KC_N, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT + #endif +), + +/* Colemak + * ,-----------------------------------------------------------------------------------. + * | Tab | Q | W | F | P | G | J | L | U | Y | ; | Bksp | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | Esc | A | R | S | T | D | H | N | E | I | O | " | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | Shift| Z | X | C | V | B | K | M | , | . | / |Enter | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | + * `-----------------------------------------------------------------------------------' + */ +[_COLEMAK] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_TAB, KC_Q, KC_W, KC_F, KC_P, KC_G, + KC_ESC, KC_A, KC_R, KC_S, KC_T, KC_D, + KC_LSFT, KC_Z, KC_X, KC_C, KC_V, KC_B, + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC + #else + KC_J, KC_L, KC_U, KC_Y, KC_SCLN, KC_BSPC, + KC_H, KC_N, KC_E, KC_I, KC_O, KC_QUOT, + KC_K, KC_M, KC_COMM, KC_DOT, KC_SLSH, KC_ENT, + KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT + #endif +), + +/* Dvorak + * ,-----------------------------------------------------------------------------------. + * | Tab | " | , | . | P | Y | F | G | C | R | L | Bksp | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | Esc | A | O | E | U | I | D | H | T | N | S | / | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | Shift| ; | Q | J | K | X | B | M | W | V | Z |Enter | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | Brite| Ctrl | Alt | GUI |Lower | Space |Raise | Left | Down | Up |Right | + * `-----------------------------------------------------------------------------------' + */ +[_DVORAK] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_TAB, KC_QUOT, KC_COMM, KC_DOT, KC_P, KC_Y, + KC_ESC, KC_A, KC_O, KC_E, KC_U, KC_I, + KC_LSFT, KC_SCLN, KC_Q, KC_J, KC_K, KC_X, + BACKLIT, KC_LCTL, KC_LALT, KC_LGUI, LOWER, KC_SPC + #else + KC_F, KC_G, KC_C, KC_R, KC_L, KC_BSPC, + KC_D, KC_H, KC_T, KC_N, KC_S, KC_SLSH, + KC_B, KC_M, KC_W, KC_V, KC_Z, KC_ENT, + KC_SPC, RAISE, KC_LEFT, KC_DOWN, KC_UP, KC_RGHT + #endif +), + +/* Lower + * ,-----------------------------------------------------------------------------------. + * | ~ | ! | @ | # | $ | % | ^ | & | * | ( | ) | Bksp | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | Del | F1 | F2 | F3 | F4 | F5 | F6 | _ | + | { | } | | | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO ~ |ISO | | Home | End | | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | | | | | | | | Next | Vol- | Vol+ | Play | + * `-----------------------------------------------------------------------------------' + */ +[_LOWER] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_TILD, KC_EXLM, KC_AT, KC_HASH, KC_DLR, KC_PERC, + KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, + _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, + _______, _______, _______, _______, _______, _______ + #else + KC_CIRC, KC_AMPR, KC_ASTR, KC_LPRN, KC_RPRN, KC_BSPC, + KC_F6, KC_UNDS, KC_PLUS, KC_LCBR, KC_RCBR, KC_PIPE, + KC_F12, S(KC_NUHS), S(KC_NUBS), KC_HOME, KC_END, _______, + _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY + #endif +), + +/* Raise + * ,-----------------------------------------------------------------------------------. + * | ` | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 0 | Bksp | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | Del | F1 | F2 | F3 | F4 | F5 | F6 | - | = | [ | ] | \ | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | | F7 | F8 | F9 | F10 | F11 | F12 |ISO # |ISO / |Pg Up |Pg Dn | | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | | | | | | | | Next | Vol- | Vol+ | Play | + * `-----------------------------------------------------------------------------------' + */ +[_RAISE] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_GRV, KC_1, KC_2, KC_3, KC_4, KC_5, + KC_DEL, KC_F1, KC_F2, KC_F3, KC_F4, KC_F5, + _______, KC_F7, KC_F8, KC_F9, KC_F10, KC_F11, + _______, _______, _______, _______, _______, _______ + #else + KC_6, KC_7, KC_8, KC_9, KC_0, KC_BSPC, + KC_F6, KC_MINS, KC_EQL, KC_LBRC, KC_RBRC, KC_BSLS, + KC_F12, KC_NUHS, KC_NUBS, KC_PGUP, KC_PGDN, _______, + _______, _______, KC_MNXT, KC_VOLD, KC_VOLU, KC_MPLY + #endif +), + +/* Plover layer (http://opensteno.org) + * ,-----------------------------------------------------------------------------------. + * | # | # | # | # | # | # | # | # | # | # | # | # | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | | S | T | P | H | * | * | F | P | L | T | D | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | | S | K | W | R | * | * | R | B | G | S | Z | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | Exit | | | A | O | | E | U | | | | + * `-----------------------------------------------------------------------------------' + */ + +[_PLOVER] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + KC_1, KC_1, KC_1, KC_1, KC_1, KC_1, + XXXXXXX, KC_Q, KC_W, KC_E, KC_R, KC_T, + XXXXXXX, KC_A, KC_S, KC_D, KC_F, KC_G, + EXT_PLV, XXXXXXX, XXXXXXX, KC_C, KC_V, XXXXXXX + #else + KC_1, KC_1, KC_1, KC_1, KC_1, KC_1 , + KC_Y, KC_U, KC_I, KC_O, KC_P, KC_LBRC, + KC_H, KC_J, KC_K, KC_L, KC_SCLN, KC_QUOT, + XXXXXXX, KC_N, KC_M, XXXXXXX, XXXXXXX, XXXXXXX + #endif +), + +/* Adjust (Lower + Raise) + * ,-----------------------------------------------------------------------------------. + * | | Reset| | | | | | | | | | Del | + * |------+------+------+------+------+-------------+------+------+------+------+------| + * | | | |Aud on|Audoff|AGnorm|AGswap|Qwerty|Colemk|Dvorak|Plover| | + * |------+------+------+------+------+------|------+------+------+------+------+------| + * | |Voice-|Voice+|Mus on|Musoff|MIDIon|MIDIof| | | | | | + * |------+------+------+------+------+------+------+------+------+------+------+------| + * | | | | | | | | | | | | + * `-----------------------------------------------------------------------------------' + */ +[_ADJUST] = LAYOUT_ortho_4x6( + #ifdef MUON_LEFT + _______, RESET, DEBUG, RGB_TOG, RGB_MOD, RGB_HUI, + _______, _______, MU_MOD, AU_ON, AU_OFF, AG_NORM, + _______, MUV_DE, MUV_IN, MU_ON, MU_OFF, MI_ON, + _______, _______, _______, _______, _______, _______ + #else + RGB_HUD, RGB_SAI, RGB_SAD, RGB_VAI, RGB_VAD, KC_DEL , + AG_SWAP, QWERTY, COLEMAK, DVORAK, PLOVER, _______, + MI_OFF, TERM_ON, TERM_OFF, _______, _______, _______, + _______, _______, _______, _______, _______, _______ + #endif +) + + +}; + +#ifdef AUDIO_ENABLE + float plover_song[][2] = SONG(PLOVER_SOUND); + float plover_gb_song[][2] = SONG(PLOVER_GOODBYE_SOUND); +#endif + +uint32_t layer_state_set_user(uint32_t state) { + return update_tri_layer_state(state, _LOWER, _RAISE, _ADJUST); +} + +bool process_record_user(uint16_t keycode, keyrecord_t *record) { + switch (keycode) { + case QWERTY: + if (record->event.pressed) { + print("mode just switched to qwerty and this is a huge string\n"); + set_single_persistent_default_layer(_QWERTY); + } + return false; + break; + case COLEMAK: + if (record->event.pressed) { + set_single_persistent_default_layer(_COLEMAK); + } + return false; + break; + case DVORAK: + if (record->event.pressed) { + set_single_persistent_default_layer(_DVORAK); + } + return false; + break; + case BACKLIT: + if (record->event.pressed) { + register_code(KC_RSFT); + #ifdef BACKLIGHT_ENABLE + backlight_step(); + #endif + } else { + unregister_code(KC_RSFT); + } + return false; + break; + case PLOVER: + if (record->event.pressed) { + #ifdef AUDIO_ENABLE + stop_all_notes(); + PLAY_SONG(plover_song); + #endif + layer_off(_RAISE); + layer_off(_LOWER); + layer_off(_ADJUST); + layer_on(_PLOVER); + if (!eeconfig_is_enabled()) { + eeconfig_init(); + } + keymap_config.raw = eeconfig_read_keymap(); + keymap_config.nkro = 1; + eeconfig_update_keymap(keymap_config.raw); + } + return false; + break; + case EXT_PLV: + if (record->event.pressed) { + #ifdef AUDIO_ENABLE + PLAY_SONG(plover_gb_song); + #endif + layer_off(_PLOVER); + } + return false; + break; + } + return true; +} + +void matrix_scan_user(void) { +} + +bool music_mask_user(uint16_t keycode) { + switch (keycode) { + case RAISE: + case LOWER: + return false; + default: + return true; + } +} diff --git a/keyboards/muon_light/keymaps/default/readme.md b/keyboards/muon_light/keymaps/default/readme.md new file mode 100644 index 0000000000..de9680b498 --- /dev/null +++ b/keyboards/muon_light/keymaps/default/readme.md @@ -0,0 +1,2 @@ +# The Default Planck Layout + diff --git a/keyboards/muon_light/keymaps/default/rules.mk b/keyboards/muon_light/keymaps/default/rules.mk new file mode 100644 index 0000000000..e69de29bb2 diff --git a/keyboards/muon_light/matrix.c b/keyboards/muon_light/matrix.c new file mode 100644 index 0000000000..5982741b66 --- /dev/null +++ b/keyboards/muon_light/matrix.c @@ -0,0 +1,124 @@ +#include +#include +#include +#include "hal.h" +#include "timer.h" +#include "wait.h" +#include "printf.h" +#include "backlight.h" +#include "matrix.h" +#include "action.h" +#include "keycode.h" +#include +#include "quantum.h" + +/* + * col: { A10, B2, A15, A0, A1, A2, B0, B1, C13, A6, A7, A3 } + * row: { B5, B10, A9, A8 } + */ +/* matrix state(1:on, 0:off) */ +static matrix_row_t matrix[MATRIX_ROWS]; +static matrix_row_t matrix_debouncing[MATRIX_COLS]; +static bool debouncing = false; +static uint16_t debouncing_time = 0; + +static LINE_TYPE matrix_col_pins[MATRIX_COLS] = MATRIX_COL_PINS; +static LINE_TYPE matrix_row_pins[MATRIX_ROWS] = MATRIX_ROW_PINS; + +__attribute__ ((weak)) +void matrix_init_user(void) {} + +__attribute__ ((weak)) +void matrix_scan_user(void) {} + +__attribute__ ((weak)) +void matrix_init_kb(void) { + matrix_init_user(); +} + +__attribute__ ((weak)) +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void matrix_init(void) { + printf("matrix init\n"); + //debug_matrix = true; + + // actual matrix setup + for (int i = 0; i < MATRIX_COLS; i++) { + setPadMode(matrix_col_pins[i], PAL_MODE_OUTPUT_PUSHPULL); + } + + for (int i = 0; i < MATRIX_ROWS; i++) { + setPadMode(matrix_row_pins[i], PAL_MODE_INPUT_PULLDOWN); + } + + memset(matrix, 0, MATRIX_ROWS * sizeof(matrix_row_t)); + memset(matrix_debouncing, 0, MATRIX_COLS * sizeof(matrix_row_t)); + + matrix_init_quantum(); +} + +uint8_t matrix_scan(void) { + + + // actual matrix + for (int col = 0; col < MATRIX_COLS; col++) { + matrix_row_t data = 0; + + setPad(matrix_col_pins[col]); + + // need wait to settle pin state + wait_us(20); + + for (int row = 0; row < MATRIX_ROWS; row++) { + data |= (readPad(matrix_row_pins[row]) << row); + } + + clearPad(matrix_col_pins[col]); + + if (matrix_debouncing[col] != data) { + matrix_debouncing[col] = data; + debouncing = true; + debouncing_time = timer_read(); + } + } + + if (debouncing && timer_elapsed(debouncing_time) > DEBOUNCE) { + for (int row = 0; row < MATRIX_ROWS; row++) { + matrix[row] = 0; + for (int col = 0; col < MATRIX_COLS; col++) { + matrix[row] |= ((matrix_debouncing[col] & (1 << row) ? 1 : 0) << col); + } + } + debouncing = false; + } + + matrix_scan_quantum(); + + return 1; +} + +bool matrix_is_on(uint8_t row, uint8_t col) { + return (matrix[row] & (1<. + */ + +#include "muon_light.h" + +void matrix_init_kb(void) { + matrix_init_user(); +} + +bool process_record_kb(uint16_t keycode, keyrecord_t *record) { + return process_record_user(keycode, record); +} + +void matrix_scan_kb(void) { + matrix_scan_user(); +} + +void suspend_power_down_kb(void) { + rgb_matrix_set_suspend_state(true); +} + +void suspend_wakeup_init_kb(void) { + rgb_matrix_set_suspend_state(false); +} + +const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_ortho_4x6( + 18, 19, 20, 21, 22, 23, + 12, 13, 14, 15, 16, 17, + 6, 7, 8, 9, 10, 11, + 0, 1, 2, 3, 4, 5 +); + +const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +/* Refer to IS31 manual for these locations + * driver + * | R location + * | | G location + * | | | B location + * | | | | */ + {0, C1_3, C2_3, C3_3}, + {0, C1_4, C2_4, C3_4}, + {0, C1_5, C2_5, C3_5}, + {0, C1_11, C2_11, C3_11}, + {0, C1_12, C2_12, C3_12}, + {0, C1_13, C2_13, C3_13}, + + {0, C1_6, C2_6, C3_6}, + {0, C1_7, C2_7, C3_7}, + {0, C1_8, C2_8, C3_8}, + {0, C1_14, C2_14, C3_14}, + {0, C1_15, C2_15, C3_15}, + {0, C1_16, C2_16, C3_16}, + + {0, C9_1, C8_1, C7_1}, + {0, C9_2, C8_2, C7_2}, + {0, C9_3, C8_3, C7_3}, + {0, C9_9, C8_9, C7_9}, + {0, C9_10, C8_10, C7_10}, + {0, C9_11, C8_11, C7_11}, + + {0, C9_4, C8_4, C7_4}, + {0, C9_5, C8_5, C7_5}, + {0, C9_6, C8_6, C7_6}, + {0, C9_12, C8_12, C7_12}, + {0, C9_13, C8_13, C7_13}, + {0, C9_14, C8_14, C7_14} +}; + +const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = { + + /*{row | col << 4} + | {x=0..224, y=0..64} + | | modifier + | | | */ + {{0|(0<<4)}, {20.36*0, 21.33*0}, 1}, + {{0|(1<<4)}, {20.36*1, 21.33*0}, 0}, + {{0|(2<<4)}, {20.36*2, 21.33*0}, 0}, + {{0|(3<<4)}, {20.36*3, 21.33*0}, 0}, + {{0|(4<<4)}, {20.36*4, 21.33*0}, 0}, + {{0|(5<<4)}, {20.36*5, 21.33*0}, 0}, + + {{1|(0<<4)}, {20.36*0, 21.33*1}, 1}, + {{1|(1<<4)}, {20.36*1, 21.33*1}, 0}, + {{1|(2<<4)}, {20.36*2, 21.33*1}, 0}, + {{1|(3<<4)}, {20.36*3, 21.33*1}, 0}, + {{1|(4<<4)}, {20.36*4, 21.33*1}, 0}, + {{1|(5<<4)}, {20.36*5, 21.33*1}, 0}, + + {{2|(0<<4)}, {20.36*0, 21.33*2}, 1}, + {{2|(1<<4)}, {20.36*1, 21.33*2}, 0}, + {{2|(2<<4)}, {20.36*2, 21.33*2}, 0}, + {{2|(3<<4)}, {20.36*3, 21.33*2}, 0}, + {{2|(4<<4)}, {20.36*4, 21.33*2}, 0}, + {{2|(5<<4)}, {20.36*5, 21.33*2}, 0}, + + {{3|(0<<4)}, {20.36*0, 21.33*3}, 1}, + {{3|(1<<4)}, {20.36*1, 21.33*3}, 1}, + {{3|(2<<4)}, {20.36*2, 21.33*3}, 1}, + {{3|(3<<4)}, {20.36*3, 21.33*3}, 1}, + {{3|(4<<4)}, {20.36*4, 21.33*3}, 1}, + {{3|(5<<4)}, {20.36*5, 21.33*3}, 0} +}; diff --git a/keyboards/muon_light/muon_light.h b/keyboards/muon_light/muon_light.h new file mode 100644 index 0000000000..7315eef84e --- /dev/null +++ b/keyboards/muon_light/muon_light.h @@ -0,0 +1,35 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef MUON_LIGHT_H +#define MUON_LIGHT_H + +#include "quantum.h" + +#define LAYOUT_ortho_4x6( \ + k00, k01, k02, k03, k04, k05, \ + k10, k11, k12, k13, k14, k15, \ + k20, k21, k22, k23, k24, k25, \ + k30, k31, k32, k33, k34, k35 \ +) \ +{ \ + { k00, k01, k02, k03, k04, k05 }, \ + { k10, k11, k12, k13, k14, k15 }, \ + { k20, k21, k22, k23, k24, k25 }, \ + { k30, k31, k32, k33, k34, k35 } \ +} + +#endif diff --git a/keyboards/muon_light/readme.md b/keyboards/muon_light/readme.md new file mode 100644 index 0000000000..2d76a312a0 --- /dev/null +++ b/keyboards/muon_light/readme.md @@ -0,0 +1,16 @@ +Planck +=== + +![Planck](http://i.imgur.com/q2M3uEU.jpg) + +A compact 40% (12x4) ortholinear keyboard kit made and sold by OLKB and Massdrop. [More info on qmk.fm](http://qmk.fm/planck/) + +Keyboard Maintainer: [Jack Humbert](https://github.com/jackhumbert) +Hardware Supported: Planck PCB rev1, rev2, rev3, rev4, Teensy 2.0 +Hardware Availability: [OLKB.com](https://olkb.com), [Massdrop](https://www.massdrop.com/buy/planck-mechanical-keyboard?mode=guest_open) + +Make example for this keyboard (after setting up your build environment): + + make planck/rev4:default + +See [build environment setup](https://docs.qmk.fm/build_environment_setup.html) then the [make instructions](https://docs.qmk.fm/make_instructions.html) for more information. \ No newline at end of file diff --git a/keyboards/muon_light/rules.mk b/keyboards/muon_light/rules.mk new file mode 100644 index 0000000000..7047f6566e --- /dev/null +++ b/keyboards/muon_light/rules.mk @@ -0,0 +1,62 @@ +# project specific files +SRC = matrix.c + +## chip/board settings +# - the next two should match the directories in +# /os/hal/ports/$(MCU_FAMILY)/$(MCU_SERIES) +MCU_FAMILY = STM32 +MCU_SERIES = STM32F3xx + +# Linker script to use +# - it should exist either in /os/common/ports/ARMCMx/compilers/GCC/ld/ +# or /ld/ +MCU_LDSCRIPT = STM32F303xC + +# Startup code to use +# - it should exist in /os/common/startup/ARMCMx/compilers/GCC/mk/ +MCU_STARTUP = stm32f3xx + +# Board: it should exist either in /os/hal/boards/ +# or /boards +BOARD = GENERIC_STM32_F303XC + +# Cortex version +MCU = cortex-m4 + +# ARM version, CORTEX-M0/M1 are 6, CORTEX-M3/M4/M7 are 7 +ARMV = 7 + +USE_FPU = yes + +# Vector table for application +# 0x00000000-0x00001000 area is occupied by bootlaoder.*/ +# The CORTEX_VTOR... is needed only for MCHCK/Infinity KB +# OPT_DEFS = -DCORTEX_VTOR_INIT=0x08005000 +OPT_DEFS = + +# Options to pass to dfu-util when flashing +DFU_ARGS = -d 0483:df11 -a 0 -s 0x08000000:leave + +# Build Options +# comment out to disable the options. +# +BACKLIGHT_ENABLE = no +BOOTMAGIC_ENABLE = yes # Virtual DIP switch configuration +## (Note that for BOOTMAGIC on Teensy LC you have to use a custom .ld script.) +MOUSEKEY_ENABLE = yes # Mouse keys +EXTRAKEY_ENABLE = yes # Audio control and System control +CONSOLE_ENABLE = yes # Console for debug +COMMAND_ENABLE = yes # Commands for debug and configuration +#SLEEP_LED_ENABLE = yes # Breathing sleep LED during USB suspend +NKRO_ENABLE = yes # USB Nkey Rollover +CUSTOM_MATRIX = yes # Custom matrix file +AUDIO_ENABLE = yes +RGB_MATRIX_ENABLE = yes +ENCODER_ENABLE = yes +# SERIAL_LINK_ENABLE = yes + +# Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE +SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend + +LAYOUTS = ortho_4x6 +LAYOUTS_HAS_RGB = no From c8cc9c6aabfb1c775c4785727524c737416823a0 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 7 Jun 2018 17:21:35 -0400 Subject: [PATCH 44/59] add i2c slave files --- drivers/chibios/i2cslave/I2Cv1/driver.mk | 21 + drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c | 1745 +++++++++++++++ drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h | 777 +++++++ drivers/chibios/i2cslave/I2Cv2/driver.mk | 21 + drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c | 2065 ++++++++++++++++++ drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h | 806 +++++++ drivers/chibios/i2cslave/hal_i2c.c | 480 ++++ drivers/chibios/i2cslave/hal_i2c.h | 212 ++ drivers/chibios/i2cslave/hal_i2cslave.h | 423 ++++ 9 files changed, 6550 insertions(+) create mode 100644 drivers/chibios/i2cslave/I2Cv1/driver.mk create mode 100644 drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c create mode 100644 drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h create mode 100644 drivers/chibios/i2cslave/I2Cv2/driver.mk create mode 100644 drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c create mode 100644 drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h create mode 100644 drivers/chibios/i2cslave/hal_i2c.c create mode 100644 drivers/chibios/i2cslave/hal_i2c.h create mode 100644 drivers/chibios/i2cslave/hal_i2cslave.h diff --git a/drivers/chibios/i2cslave/I2Cv1/driver.mk b/drivers/chibios/i2cslave/I2Cv1/driver.mk new file mode 100644 index 0000000000..f8cca018e9 --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv1/driver.mk @@ -0,0 +1,21 @@ +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1 +endif diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c new file mode 100644 index 0000000000..e62e6db1f3 --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c @@ -0,0 +1,1745 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + + I2C Slave mode support added by Brent Roman (brent@mbari.org) + Ported to ChibiOs V3 by steved + Latest updates from original code applied 18.12.15 + + Note that all I2C registers are 16-bit (not 32-bit, as on the later devices in the series) + */ + +/** + * @file STM32/I2Cv1/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +// Some master code has been brought in line with V3 - set next define to zero to stick with original code +#define USE_OLD_MASTER_STARTUP 0 + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +#define I2C3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_CHN) + +#define I2C3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_CHN) + +/*===========================================================================*/ +/* Driver constants -- see ST document RM0038 figure 208 */ +/*===========================================================================*/ +#define I2C_EV5_MASTER_MODE_SELECT \ + (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_SB) + +#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ + (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_ADDR) + +#define I2C_EV6_MASTER_REC_MODE_SELECTED \ + (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_ADDR) + +#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ + (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_BTF) + +#define I2C_EV9_MASTER_ADD10 \ + ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10)) + +#if HAL_USE_I2C_SLAVE +#define I2C_EV1_SLAVE_RXADRMATCH \ + ((uint32_t)I2C_SR1_ADDR) + +#define I2C_EV1_SLAVE_TXADRMATCH \ + (((uint32_t)I2C_SR2_TRA << 16) | I2C_SR1_ADDR) + +#define I2C_EV2_SLAVE_RXSTOP \ + (I2C_SR1_STOPF) +#endif + +#define I2C_EV_MASK ( \ + ((uint32_t)(I2C_SR2_MSL|I2C_SR2_TRA)<<16) | \ + (I2C_SR1_SB|I2C_SR1_ADDR|I2C_SR1_STOPF|I2C_SR1_BTF)) + +#define I2C_ERROR_MASK \ + ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ + I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/* quick and dirty queue to record event interrupts */ +#define QEVENTS 32 +#if QEVENTS > 0 +typedef struct i2cQ_t { + uint8_t code; + uint8_t state; + uint16_t param; +} i2cQ_t; +i2cQ_t i2cQ[QEVENTS]; +unsigned i2cI = QEVENTS; +#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \ + i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->mode); i2cQ[i2cI].param=(info); } +#else +#define qEvt(posn,info) +#endif + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +void I2CSlaveDummyCB(I2CDriver *i2cp) +/* + dummy callback -- placeholder to ignore event +*/ +{(void)i2cp;} + + /* lock bus on receive or reply message */ +const I2CSlaveMsg I2CSlaveLockOnMsg = { + 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB +}; + +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/** + * @brief Resets and disables the I2C channel + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2cReset(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + /* reset the I2C registers.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + dp->CR2 = 0; + dp->SR1 = 0; + + /* Stop the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +} + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2cAbortOperation(I2CDriver *i2cp) { + /* save control registers */ + I2C_TypeDef *dp = i2cp->i2c; + uint16_t cr2 = dp->CR2, cr1 = dp->CR1; +#if HAL_USE_I2C_SLAVE + uint16_t oar1 = dp->OAR1, oar2 = dp->OAR2; +#endif + uint16_t ccr = dp->CCR, trise = dp->TRISE; + + /* reset the I2C channel */ + i2cReset(i2cp); + + /* restore control registers */ + dp->TRISE = trise; dp->CCR = ccr; +#if HAL_USE_I2C_SLAVE + /* restore address mataching */ + dp->OAR1 = oar1; dp->OAR2 = oar2; +#endif + + /* Enable interrrupts */ + dp->CR2 = (cr2 & 0x3F) | I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN; + + /* Finish restoring and enable pheripheral */ + dp->CR1 = I2C_CR1_ACK | I2C_CR1_PE | (cr1 & (I2C_CR1_SMBUS | I2C_CR1_SMBTYPE)) +#if HAL_USE_I2C_SLAVE + | (cr1 & I2C_CR1_ENGC) +#endif + ; +} + + +#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK +/** + * @brief stop transaction timeout countdown + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static inline void stopTimer(I2CDriver *i2cp) +{ + osalSysLockFromISR(); + chVTResetI(&i2cp->timer); + osalSysUnlockFromISR(); +} +#else +#define stopTimer(ignored) {} +#endif + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +/** + * @brief return the address matched + * + * @param[in] dp pointer to the @p I2C registers object + * @param[in] sr2 I2C SR2 register contents + * + * @notapi + * Only supports 7-bit addressing for now + */ +static inline i2caddr_t matchedAdr(I2C_TypeDef *dp, uint32_t sr2) { + if (sr2 & I2C_SR2_GENCALL) + return 0; + if (sr2 & I2C_SR2_DUALF) + return (dp->OAR2>>1) & 0x7f; + return (dp->OAR1>>1) & 0x7f; +} + + +/** + * @brief report error via slave exception callback + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @note moves back to the idle mode + * @notapi + */ +static inline void reportSlaveError(I2CDriver *i2cp) { +#if HAL_USE_I2C_STARTFIX + i2cp->config->disarmStartDetect(); +#endif + { + const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ? + i2cp->slaveReply : i2cp->slaveRx; + if (xfer->exception) + xfer->exception(i2cp); /* in this case, i2cp->slaveErrors == 0 */ + } + i2cp->mode = i2cIdle; + i2cp->targetAdr = i2cInvalidAdr; +} + + +/** + * @brief Handling of stalled slave mode I2C transactions. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void slaveTimeExpired(void *i2cv) { + I2CDriver *i2cp = i2cv; + + if (i2cp->mode < i2cIsMaster) + { + i2cAbortOperation(i2cp); + reportSlaveError(i2cp); + } +} + + +/** + * @brief start or restart slave mode transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static inline void startSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr) +{ + stopTimer(i2cp); + i2cp->targetAdr = targetAdr; + i2cp->slaveBytes = 0; + i2cp->slaveErrors = 0; + if (i2cp->slaveTimeout != TIME_INFINITE) + { + osalSysLockFromISR(); + chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp); + osalSysUnlockFromISR(); + } +} + +/** + * @brief end slave receive message DMA + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static inline void endSlaveRxDMA(I2CDriver *i2cp) +{ + size_t bytesRemaining = dmaStreamGetTransactionSize(i2cp->dmarx); + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff - bytesRemaining; + else + i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining; + dmaStreamDisable(i2cp->dmarx); +} + +/** + * @brief end slave transmit DMA + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] bytesRemaining bytes lost in output queue + * + * @notapi + */ +static inline void endSlaveReplyDMA(I2CDriver *i2cp, size_t bytesRemaining) +{ + bytesRemaining += dmaStreamGetTransactionSize(i2cp->dmatx); + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff - bytesRemaining; + else + i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining; + dmaStreamDisable(i2cp->dmatx); +} + +#endif + + +/** + * @brief Wakes up a waiting thread. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] msg wakeup message + * + * @notapi + */ +static inline void wakeup_isr(I2CDriver *i2cp, msg_t msg) +{ + do { + osalSysLockFromISR(); + osalThreadResumeI(&(i2cp)->thread, msg); + osalSysUnlockFromISR(); + } while(0); + +#if 0 + chSysLockFromISR(); + thread_t *tp = i2cp->thread; + if (tp != NULL) { + i2cp->thread = NULL; + tp->p_u.rdymsg = msg; + chSchReadyI(tp); + } + chSysUnlockFromISR(); +#endif +} + + +/** + * @brief Set clock speed. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_clock(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint16_t regCCR, clock_div; + int32_t clock_speed = i2cp->config->clock_speed; + i2cdutycycle_t duty = i2cp->config->duty_cycle; + + osalDbgCheck((i2cp != NULL) && + (clock_speed > 0) && + (clock_speed <= 4000000)); + + /* CR2 Configuration.*/ + dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; + dp->CR2 |= (uint16_t)I2C_CLK_FREQ; + + /* CCR Configuration.*/ + regCCR = 0; + clock_div = I2C_CCR_CCR; + + switch (duty) { + case STD_DUTY_CYCLE: + /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ +#ifndef STM32_I2C_LOOSE_CLK + /* Configure clock_div in standard mode.*/ + osalDbgAssert(clock_speed <= 100000, + "#1 - STD_DUTY_CYCLE limited to 100khz"); + osalDbgAssert(STM32_PCLK1 % (clock_speed * 2) == 0, + "#2 - PCLK1 not divisible by 2*I2Cclk"); +#endif + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); + + + osalDbgAssert(clock_div >= 0x04, + "clock divider less then 0x04 not allowed"); + regCCR |= (clock_div & I2C_CCR_CCR); + + /* Sets the Maximum Rise Time for standard mode.*/ + dp->TRISE = (uint16_t)(I2C_CLK_FREQ + 1); + break; + + case FAST_DUTY_CYCLE_2: + case FAST_DUTY_CYCLE_16_9: + /* Configure clock_div in fast mode.*/ +#ifndef STM32_I2C_LOOSE_CLK + osalDbgAssert(clock_speed > 100000 && clock_speed <= 400000, + "#4 - I2Cclk out of range for FAST_DUTY_CYCLE"); +#endif + if (duty == FAST_DUTY_CYCLE_2) { + /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ +#ifndef STM32_I2C_LOOSE_CLK + osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, + "#6 - PCLK1 not divisible by 3*I2Cclk"); +#endif + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); + }else{ /* FAST_DUTY_CYCLE_16_9 */ + /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ +#ifndef STM32_I2C_LOOSE_CLK + osalDbgAssert(STM32_PCLK1 % (clock_speed * 25) == 0, + "#7 - PCLK1 not divisible by 25*I2Cclk"); +#endif + clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); + regCCR |= I2C_CCR_DUTY; + } + + osalDbgAssert(clock_div >= 0x01, + "clock divider less then 0x04 not allowed"); + regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); + + /* Sets the Maximum Rise Time for fast mode.*/ + dp->TRISE = (uint16_t)((I2C_CLK_FREQ * 300 / 1000) + 1); + break; + + default: + osalSysHalt("Invalid I2C duty_cycle"); + } + + osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); + + dp->CCR = (uint16_t)regCCR; +} + + +/** + * @brief Set operation mode of I2C hardware. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_set_opmode(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + i2copmode_t opmode = i2cp->config->op_mode; + uint16_t regCR1; + + regCR1 = dp->CR1; + switch (opmode) { + case OPMODE_I2C: + regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_DEVICE: + regCR1 |= I2C_CR1_SMBUS; + regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); + break; + case OPMODE_SMBUS_HOST: + regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); + } + dp->CR1 = (uint16_t)regCR1; +} + + + +#if USE_OLD_MASTER_STARTUP +/** + * @brief Handling of stalled master mode I2C transactions. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_safety_timeout(void *p) { + I2CDriver *i2cp = p; + + stopTimer(i2cp); +#if HAL_USE_I2C_SLAVE /* abort any slave operation in progress */ + if (!(i2cp->i2c->SR2 & I2C_SR2_MSL)) + slaveTimeExpired(i2cp); /* in case slave preventing master bus access */ + else +#endif + { + i2cAbortOperation(i2cp); + i2cp->mode = i2cIdle; + } + wakeup_isr(i2cp, I2C_ERR_TIMEOUT); +} +#endif + + +#if HAL_USE_I2C_LOCK /* I2C bus locking support */ + +/** + * @brief Handling of expired master bus lock timer + * + * @param[in] i2cv pointer to the @p I2CDriver object + * + * @notapi + */ +static void lockExpired(void *i2cv) { + I2CDriver *i2cp = i2cv; + + if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */ + i2cp->i2c->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); + i2cp->mode = i2cIdle; + } + i2cp->lockDuration = TIME_IMMEDIATE; +} + + +/** + * @brief Lock I2C bus at the beginning of the next message + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] lockDuration max number of ticks to hold bus locked + * - @a TIME_INFINITE no timeout. + * - @a TIME_IMMEDIATE unlock the bus immediately + * . + * + * Lock I2C bus at the beginning of the next message sent + * for a maximum of lockDuration ticks. No other I2C masters will + * be allowed to interrupt until i2cUnlock() is called. + * + * @notapi + **/ +void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration) +{ + i2cp->lockDuration = lockDuration; + if (i2cp->mode >= i2cIsMaster) { + stopTimer(i2cp); + if (lockDuration == TIME_IMMEDIATE) + lockExpired(i2cp); + else if (lockDuration != TIME_INFINITE) + chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); + } +} + +#endif + + + +/** + * @brief report error waking thread or invoking callback as appropriate + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] errCode error bit mask or code + * + * @notapi + */ +static void reportErrs(I2CDriver *i2cp, i2cflags_t errCode) +{ +qEvt(0xee,errCode); + I2C_TypeDef *dp = i2cp->i2c; + if (i2cp->mode <= i2cIdle) /* failing to master bus */ + i2cAbortOperation(i2cp); + else if (dp->SR2 & I2C_SR2_MSL) { +#if HAL_USE_I2C_LOCK /* I2C bus locking support */ + i2cp->mode = i2cIsMaster; + switch (i2cp->lockDuration) { + case TIME_INFINITE: + break; + case TIME_IMMEDIATE: + stopTimer(i2cp); + default: + if (!chVTIsArmedI(&i2cp->timer)) { + dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); + i2cp->mode = i2cIdle; + i2cp->lockDuration = TIME_IMMEDIATE; + } + } +#else /* signal stop condition on any error */ + dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); + i2cp->mode = i2cIdle; +#endif + } +#if HAL_USE_I2C_SLAVE + else if (i2cp->mode < i2cIsMaster) { + i2cp->slaveErrors = errCode; + i2cAbortOperation(i2cp); + stopTimer(i2cp); + reportSlaveError(i2cp); + return; + } +#endif + /* wake any waiting master mode handling thread. */ + i2cp->errors = errCode; + wakeup_isr(i2cp, I2C_ERROR); +} + + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] sr content of the SR1 register to be decoded + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { +#if HAL_USE_I2C_SLAVE +/* NACK of last byte transmitted in slave response is NORMAL -- not an error! */ + if (i2cp->mode == i2cSlaveReplying && (sr & I2C_ERROR_MASK) == I2C_SR1_AF) { +qEvt(0xcc,sr); + endSlaveReplyDMA(i2cp, 1); +#if HAL_USE_I2C_STARTFIX + i2cp->config->disarmStartDetect(); +#endif + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + i2cp->targetAdr = i2cInvalidAdr; + stopTimer(i2cp); + i2cp->mode = i2cIdle; + return; + } +#endif + i2cflags_t errs = 0; + + if (sr & I2C_SR1_BERR) /* Bus error. */ + errs = I2C_BUS_ERROR; + + if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ + errs |= I2C_ARBITRATION_LOST; + + if (sr & I2C_SR1_AF) /* Acknowledge fail. */ + errs |= I2C_ACK_FAILURE; + + if (sr & I2C_SR1_OVR) /* Overrun. */ + errs |= I2C_OVERRUN; + + if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ + errs |= I2C_TIMEOUT; + + if (sr & I2C_SR1_PECERR) /* PEC error. */ + errs |= I2C_PEC_ERROR; + + if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ + errs |= I2C_SMB_ALERT; + + if (!errs) + errs = I2C_UNKNOWN_ERROR; +qEvt(0xcb,errs); + + /* Disable any active DMA */ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); + + reportErrs(i2cp, errs); +} + + +static inline void endMasterAction(I2CDriver *i2cp, uint32_t regCR1) +{ +#if HAL_USE_I2C_LOCK + if (i2cp->lockDuration != TIME_IMMEDIATE && ( + chVTIsArmedI(&i2cp->timer) || i2cp->lockDuration == TIME_INFINITE)) { + i2cp->mode = i2cIsMaster; + return; + } + stopTimer(i2cp); +#endif + i2cp->i2c->CR1 = (regCR1 | I2C_CR1_STOP | I2C_CR1_ACK); + i2cp->mode = i2cIdle; +} + + +/** + * @brief I2C event handler ISR + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) +{ + I2C_TypeDef *dp = i2cp->i2c; + uint16_t regCR1 = dp->CR1; + uint32_t regSR2 = dp->SR2; + uint32_t event = dp->SR1 | (regSR2 << 16); + + + switch (event & I2C_EV_MASK) { + +#define chkTransition(expectedMode) { \ + if (i2cp->mode != (expectedMode)) goto invalidTransition;} + + invalidTransition: /* error on known event out of expected sequence */ + i2cAbortOperation(i2cp); /* reset and reinit */ + qEvt(0x10, (event & 0xffff)); + reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode); + break; + +#if HAL_USE_I2C_SLAVE + case I2C_EV1_SLAVE_RXADRMATCH : /* Slave mode - receive a message */ +qEvt(0x11,0); + { + i2caddr_t targetAdr = matchedAdr(dp, regSR2); + switch (i2cp->mode) { + case i2cIdle: +#if HAL_USE_I2C_STARTFIX + i2cp->config->armStartDetect(); +#endif + break; + case i2cSlaveRxing: + endSlaveRxDMA(i2cp); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); + break; + case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ + endSlaveReplyDMA(i2cp, 2); + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + break; + default: + goto invalidTransition; + } + startSlaveAction(i2cp, targetAdr); + } + { + const I2CSlaveMsg *rx = i2cp->slaveNextRx; + if (rx->adrMatched) // Q: Can rx ever be NULL? + rx->adrMatched(i2cp); // Execute callback on address match if specified + rx = i2cp->slaveRx = i2cp->slaveNextRx; + if (rx->body && rx->size) { + (void)dp->SR2; /* clear I2C_SR1_ADDR */ + /* Receive buffer available - can receive immediately. Set up slave RX DMA */ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rx->body); + dmaStreamSetTransactionSize(i2cp->dmarx, rx->size); + dmaStreamEnable(i2cp->dmarx); + i2cp->mode = i2cSlaveRxing; + }else{ + dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); /* No reply set up - hold clock low and wait */ + i2cp->mode = i2cLockedRxing; + } + } + break; + + case I2C_EV2_SLAVE_RXSTOP: /* STOP received - possibly without NAK */ +qEvt(0x22,0); + dp->CR1 = (uint16_t)regCR1; /* clear STOPF */ + i2cp->slaveErrors = I2C_STOPPED; /* indicate that bus has been released */ + switch (i2cp->mode) { + case i2cSlaveRxing: + endSlaveRxDMA(i2cp); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); + break; + case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ + endSlaveReplyDMA(i2cp, 2); + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + break; + default: + goto invalidTransition; + } +#if HAL_USE_I2C_STARTFIX + i2cp->config->disarmStartDetect(); +#endif + i2cp->targetAdr = i2cInvalidAdr; + stopTimer(i2cp); + i2cp->mode = i2cIdle; + break; + + case I2C_EV1_SLAVE_TXADRMATCH: /* Slave mode - reply */ +qEvt(0x33,0); + { + i2caddr_t targetAdr = matchedAdr(dp, regSR2); + (void)dp->SR2; /* clear I2C_SR1_ADDR */ // TODO: Check + switch (i2cp->mode) { + case i2cIdle: +#if HAL_USE_I2C_STARTFIX + i2cp->config->armStartDetect(); +#endif + break; + case i2cSlaveRxing: /* Previous transaction not completed properly */ + endSlaveRxDMA(i2cp); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); + break; + default: + goto invalidTransition; + } + startSlaveAction(i2cp, targetAdr); + } + { + const I2CSlaveMsg *reply = i2cp->slaveNextReply; + if (reply->adrMatched) // Q: Can reply be NULL? + reply->adrMatched(i2cp); + reply = i2cp->slaveReply = i2cp->slaveNextReply; // Q: Duplicate action? + if (reply->body && reply->size) { + /* Reply message available - can send immediately. Set up slave TX DMA */ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, reply->body); + dmaStreamSetTransactionSize(i2cp->dmatx, reply->size); + dmaStreamEnable(i2cp->dmatx); + i2cp->mode = i2cSlaveReplying; + }else{ + dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); + i2cp->mode = i2cLockedReplying; + } + } + break; +#endif /* HAL_USE_I2C_SLAVE */ + + case I2C_EV5_MASTER_MODE_SELECT: +qEvt(0x55,0); + dp->DR = (uint16_t)i2cp->addr; + switch (i2cp->mode) { + case i2cIdle: +#if HAL_USE_I2C_LOCK + { + systime_t lockDuration = i2cp->lockDuration; + if (lockDuration != TIME_IMMEDIATE && lockDuration != TIME_INFINITE) + { + osalSysLockFromISR(); + chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); + osalSysUnlockFromISR(); + } + } +#endif + break; + case i2cIsMaster: + case i2cMasterStarted: + break; + default: + goto invalidTransition; + } + i2cp->mode = i2cMasterSelecting; + break; + + case I2C_EV6_MASTER_REC_MODE_SELECTED: +qEvt(0x66,0); + chkTransition(i2cMasterSelecting); + if (!i2cp->masterRxbytes) { /* 0-length SMBus style quick read */ + endMasterAction(i2cp, regCR1); + (void)dp->SR2; /* clear I2C_SR1_ADDR */ + wakeup_isr(i2cp, I2C_OK); + break; + } + (void)dp->SR2; /* clear I2C_SR1_ADDR */ + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, i2cp->masterRxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, i2cp->masterRxbytes); + dmaStreamEnable(i2cp->dmarx); + dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ + if (i2cp->masterRxbytes < 2) + dp->CR1 = (uint16_t)(regCR1 & ~I2C_CR1_ACK); + i2cp->mode = i2cMasterRxing; + break; + + case I2C_EV6_MASTER_TRA_MODE_SELECTED: +qEvt(0x77,0); + (void)dp->SR2; /* clear I2C_SR1_ADDR */ + chkTransition(i2cMasterSelecting); + switch (i2cp->masterTxbytes) { + case 0: + goto doneWriting; + case 1: + dp->DR = i2cp->masterTxbuf[0]; + break; + case 2: + dp->DR = i2cp->masterTxbuf[0]; + dp->DR = i2cp->masterTxbuf[1]; + break; + default: + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, i2cp->masterTxbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, i2cp->masterTxbytes); + dmaStreamEnable(i2cp->dmatx); + } + i2cp->mode = i2cMasterTxing; + break; + + case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: +qEvt(0x88,0); + /* Catches BTF event after the end of transmission.*/ + (void)dp->DR; /* clears BTF flag */ + chkTransition(i2cMasterTxing); +doneWriting: + if (i2cp->masterRxbuf) { + /* Starts "read after write" operation, LSB = 1 -> receive.*/ + dp->CR1 = (uint16_t)(regCR1 | I2C_CR1_START | I2C_CR1_ACK); + i2cp->addr |= 1; + i2cp->mode = i2cMasterStarted; + }else{ + endMasterAction(i2cp, regCR1); + wakeup_isr(i2cp, I2C_OK); + } + break; + + case 0: /* quietly ignore "uninteresting" events (i.e. i2c bus busy) */ + qEvt(0x0000); + break; + + default: /* unhandled event -- abort transaction, flag unknown err */ +qEvt(0x9999,0); + //i2cAbortOperation(i2cp); + i2c_lld_serve_error_interrupt(i2cp, event); + } +} + + +#if HAL_USE_I2C_STARTFIX +/** + * @brief external device detected start condition + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details invoked from ISR if a START CONDITION detected during the time + * the startDetector is armed. + * This is a workaround for the STM32's lack of a repeated start event + * + * @notapi + */ +void i2c_lld_startDetected(I2CDriver *i2cp) +{ +qEvt(0xdddd,0); + switch (i2cp->mode) { + case i2cIdle: + i2cAbortOperation(i2cp); /* quietly reset and reinit */ + return; + case i2cSlaveRxing: + endSlaveRxDMA(i2cp); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); + break; + case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ + endSlaveReplyDMA(i2cp, 2); + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + break; + default: + i2cAbortOperation(i2cp); /* reset and reinit */ + reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode); + return; + } + i2cp->targetAdr = i2cInvalidAdr; + stopTimer(i2cp); + i2cp->mode = i2cIdle; +} + +/** + * @brief dummy placeholder for armStartDetector() and disarmStartDetector() + * + * @details *MUST* be placed in the configuration struct in cases where + * HAL_USE_I2C_STARTFIX is configured and no startDetector is defined, + * otherwise NULL pointers will be called for these functions! + * + * @notapi + */ +void i2c_lld_noStartDetector(void) {} +#endif + + +/** + * @brief DMA RX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] flags pre-shifted content of the ISR register + * + * @notapi + */ +static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { + I2C_TypeDef *dp = i2cp->i2c; + +qEvt(0xaa,0); + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + + dmaStreamDisable(i2cp->dmarx); + +#if HAL_USE_I2C_SLAVE + if (i2cp->mode < i2cIsMaster) { + static uint8_t bitbucket; + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32) + else + i2cp->slaveBytes = i2cp->slaveRx->size; + /* discard data overrunning available rx buffer, but record total length */ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode & ~STM32_DMA_CR_MINC); + dmaStreamSetMemory0(i2cp->dmarx, &bitbucket); + dmaStreamSetTransactionSize(i2cp->dmarx, 0xffff); + dmaStreamEnable(i2cp->dmarx); + return; + } +#endif + + dp->CR2 &= (uint16_t)(~I2C_CR2_LAST); + endMasterAction(i2cp, dp->CR1); + wakeup_isr(i2cp, I2C_OK); +} + +/** + * @brief DMA TX end IRQ handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { +qEvt(0xbb,0); + /* DMA errors handling.*/ +#if defined(STM32_I2C_DMA_ERROR_HOOK) + if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { + STM32_I2C_DMA_ERROR_HOOK(i2cp); + } +#else + (void)flags; +#endif + dmaStreamDisable(i2cp->dmatx); + +#if HAL_USE_I2C_SLAVE + if (i2cp->mode < i2cIsMaster) { + const I2CSlaveMsg *reply = i2cp->slaveReply; + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32) + else + i2cp->slaveBytes = reply->size; + /* repeat the last byte in the reply */ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode & ~STM32_DMA_CR_MINC); + dmaStreamSetMemory0(i2cp->dmatx, reply->body+reply->size-1); + dmaStreamSetTransactionSize(i2cp->dmatx, 0xffff); + dmaStreamEnable(i2cp->dmatx); + } +#endif +} + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD1); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C1 error interrupt handler. + */ +OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint16_t sr = I2CD1.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD1, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD2); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C2 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint16_t sr = I2CD2.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD2, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { + + OSAL_IRQ_PROLOGUE(); + + i2c_lld_serve_event_interrupt(&I2CD3); + + OSAL_IRQ_EPILOGUE(); +} + +/** + * @brief I2C3 error interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { + uint16_t sr = I2CD3.i2c->SR1; + + OSAL_IRQ_PROLOGUE(); + + I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); + i2c_lld_serve_error_interrupt(&I2CD3, sr); + + OSAL_IRQ_EPILOGUE(); +} +#endif /* STM32_I2C_USE_I2C3 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; + I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); + I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); +#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE + chVTObjectInit(&I2CD1.timer); +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; + I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); + I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); +#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE + chVTObjectInit(&I2CD2.timer); +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; + I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); + I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); +#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE + chVTObjectInit(&I2CD3.timer); +#endif +#endif /* STM32_I2C_USE_I2C3 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + + i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | + STM32_DMA_CR_DIR_P2M; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + bool b; + + rccResetI2C1(); // **** From trunk + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C1_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C1(FALSE); + nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + bool b; + + rccResetI2C2(); // *** From trunk + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C2_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C2(FALSE); + nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + bool b; + + rccResetI2C3(); // *** From trunk + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C3_IRQ_PRIORITY, + (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + rccEnableI2C3(FALSE); + nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_I2C3 */ + } + + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); + + /* Reset i2c peripheral.*/ + dp->CR1 = I2C_CR1_SWRST; + dp->CR1 = 0; + + i2cp->mode = i2cIdle; +#if HAL_USE_I2C_LOCK + i2cp->lockDuration = TIME_IMMEDIATE; +#endif +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg; + i2cp->targetAdr = i2cInvalidAdr; + i2cp->slaveTimeout = TIME_INFINITE; +#endif + + /* Setup I2C parameters.*/ + i2c_lld_set_clock(i2cp); + i2c_lld_set_opmode(i2cp); + + /* Enable interrrupts */ + dp->CR2 |= I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN; + /* Ready to go.*/ + dp->CR1 |= I2C_CR1_PE | I2C_CR1_ACK; +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state, then disable the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + + /* I2C disable.*/ + i2cReset(i2cp); + dmaStreamRelease(i2cp->dmatx); + dmaStreamRelease(i2cp->dmarx); + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + nvicDisableVector(I2C1_EV_IRQn); + nvicDisableVector(I2C1_ER_IRQn); + rccDisableI2C1(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + nvicDisableVector(I2C2_EV_IRQn); + nvicDisableVector(I2C2_ER_IRQn); + rccDisableI2C2(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + nvicDisableVector(I2C3_EV_IRQn); + nvicDisableVector(I2C3_ER_IRQn); + rccDisableI2C3(FALSE); + } +#endif + + reportErrs(i2cp, I2C_STOPPED); /* wake any blocked thread */ +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + reportErrs(i2cp, I2C_STOPPED); /* ensure both master and slave notified */ +#endif + } +} + + +/** + * @brief Starts an I2C bus master transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval I2C_OK if the function succeeded. + * @retval I2C_ERROR if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a + * timeout the driver should be stopped and restarted + * because the bus may in an uncertain state. + * Drivers that support slave mode require only the the driver be restarted + * after a timeout, as stopping and restarting may result in missed events. + * + * There's a system lock active from higher levels when this is called + * + * @notapi + */ +#if USE_OLD_MASTER_STARTUP +// This is the 'original' from the V2.x master/slave code +static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) +{ + osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); + + i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + + virtual_timer_t vt; /* Global timeout for the whole operation.*/ + chVTObjectInit(&vt); + + if (timeout != TIME_INFINITE) + chVTSetI(&vt, timeout, i2c_lld_safety_timeout, i2cp); + i2cp->errors = 0; + i2cp->thread = chThdGetSelfX(); + chSchGoSleepS(CH_STATE_SUSPENDED); + chVTResetI(&vt); + return chThdGetSelfX()->p_u.rdymsg; +} + + +#else + + + +// This version uses same logic as the 'original' V3.x master-only driver. +// Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout() +static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) +{ + systime_t start, end; + + osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); + + osalSysUnlock(); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ + if (!(i2cp->i2c->SR2 & I2C_SR2_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + } + + + i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; + + /* Waits for the operation completion or a timeout.*/ + return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); +} +#endif + +/** + * @brief Receives data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval I2C_OK if the function succeeded. + * @retval I2C_ERROR if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a + * timeout the driver should be stopped and restarted + * because the bus may in an uncertain state. + * Drivers that support slave mode require only the the driver be restarted + * after a timeout, as stopping and restarting may result in missed events. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + osalDbgAssert((rxbytes < (1<<16)), + "#1 - >64Kbytes"); +#if defined(STM32F1XX_I2C) + osalDbgAssert((rxbytes != 1), + "#2 - rxbytes==1"); +#endif + osalDbgAssert((i2cp->thread==NULL), + "#3 - reentry"); + + /* Initializes driver fields, LSB = 1 -> receive.*/ + i2cp->addr = (addr << 1) | 1; + + /* store away DMA info for later activation in event ISR */ + i2cp->masterRxbuf = rxbuf; + i2cp->masterRxbytes = (uint16_t) rxbytes; + return startMasterAction(i2cp, timeout); +} + +/** + * @brief Transmits data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval I2C_OK if the function succeeded. + * @retval I2C_ERROR if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a + * timeout the driver should be stopped and restarted + * because the bus is in an uncertain state. + * Drivers that support slave mode require only the the driver be restarted + * after a timeout, as stopping and restarting may result in missed events. + * + * There's a system lock active on entry from higher level driver + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + if (rxbuf == NULL) + rxbytes = 0; + osalDbgAssert(((rxbytes | txbytes) < (1<<16)), "#1 - >64Kbytes"); +#if defined(STM32F1XX_I2C) + osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))); +#endif + osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); + + /* Initializes driver fields, LSB = 0 -> write.*/ + i2cp->addr = addr << 1; + /* store away DMA info for later activation in event ISR */ + i2cp->masterTxbuf = txbuf; + i2cp->masterTxbytes = (uint16_t) txbytes; + i2cp->masterRxbuf = rxbuf; + i2cp->masterRxbytes = (uint16_t) rxbytes; + return startMasterAction(i2cp, timeout); +} + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +/* These bits are undocumented, but used in STM32l1xx I2C example driver */ +#define I2C_OAR1_Ack_7bit (0x4000) /*enable 7 bit address acknowledge*/ +#define I2C_OAR1_Ack_10bit (0xC000) /*enable 10 bit address acknowledge*/ + +/** + * @brief Reconfigure I2C channel to respond to indicated address + * in addition to those already matched + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C network address + * + * @return Length of message OR the type of event received + * @retval I2C_OK Success + * @retval I2C_ERROR Cannot match address in addition of those already + * + * @details MatchAddress calls are cumulative. + * Specify address zero to match I2C "all call" + * Does not support 10-bit addressing. + * + * @notapi + **/ +msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + I2C_TypeDef *dp = i2cp->i2c; + if (i2cadr == 0) { + dp->CR1 |= I2C_CR1_ENGC; + dp->OAR1 |= I2C_OAR1_Ack_7bit; + }else{ + uint16_t adr = i2cadr << 1; + uint16_t ownAdr = dp->OAR1 & (0x7f<<1); + if (ownAdr == 0 || ownAdr == adr) + dp->OAR1 = adr | I2C_OAR1_Ack_7bit; + else if (!(dp->OAR2 & I2C_OAR2_ENDUAL)) + dp->OAR2 = adr | I2C_OAR2_ENDUAL; + else if ((dp->OAR2 & (0x7f<<1)) != adr) + return I2C_ERROR; /* cannot add this address to set of those matched */ + } + return I2C_OK; +} + + +/** + * @brief Reconfigure I2C channel to no longer match specified address + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C network address + * + * @details A message being transferred that has already matched the + * specified address will continue being processed. + * Requests to unmatch an address that is not currently being matched + * are ignored. + * Does not support 10-bit addressing. + * + * @notapi + **/ +void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + I2C_TypeDef *dp = i2cp->i2c; + if (i2cadr == 0) { + dp->CR1 &= (uint16_t)~I2C_CR1_ENGC; + if ((dp->OAR1 & (0x7f<<1)) == 0) + dp->OAR1 = 0; + }else{ + uint16_t adr = i2cadr << 1; + if ((dp->OAR1 & (0x7f<<1)) == adr) { + if (dp->OAR2 & I2C_OAR2_ENDUAL) + dp->OAR1 = (dp->OAR2 & (0x7f<<1)) | I2C_OAR1_Ack_7bit; + else + dp->OAR1 = dp->CR1 & I2C_CR1_ENGC ? I2C_OAR1_Ack_7bit : 0; + }else if (dp->OAR2 & I2C_OAR2_ENDUAL && (dp->OAR2 & (0x7f<<1)) == adr) + dp->OAR2 &= ~I2C_OAR2_ENDUAL; + } +} + + +/** + * @brief Reconfigure I2C channel to no longer match any address + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details Causes all subsequent messages to be ignored. + * A message being transferred that has already matched a + * slave address will continue being processed. + * + * @notapi + **/ +void i2c_lld_unmatchAll(I2CDriver *i2cp) +{ + I2C_TypeDef *dp = i2cp->i2c; + dp->CR1 &= (uint16_t)~I2C_CR1_ENGC; + dp->OAR1 = 0; + dp->OAR2 = 0; +} + + +/** + * @brief Configure callbacks & buffers to receive messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @notapi + */ +void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) +{ + osalDbgCheck((rxMsg && rxMsg->size <= 0xffff)); + i2cp->slaveNextRx = rxMsg; + if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) { + /* We can receive now! */ + I2C_TypeDef *dp = i2cp->i2c; + (void)dp->SR1, dp->SR2; /* clear I2C_SR1_ADDR */ + i2cp->slaveRx = rxMsg; + /* slave RX DMA setup */ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body); + dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size); + dmaStreamEnable(i2cp->dmarx); + i2cp->mode = i2cSlaveRxing; + dp->CR2 |= I2C_CR2_ITEVTEN; + } +} + + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @notapi + */ +void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) +{ + osalDbgCheck((replyMsg && replyMsg->size <= 0xffff)); + i2cp->slaveNextReply = replyMsg; + if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size) { + i2cp->slaveReply = replyMsg; + /* slave TX DMA setup -- we can reply now! */ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body); + dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size); + dmaStreamEnable(i2cp->dmatx); + i2cp->mode = i2cSlaveReplying; + i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; + } +} + +#endif /* HAL_USE_I2C_SLAVE */ + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h new file mode 100644 index 0000000000..d45acaa671 --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h @@ -0,0 +1,777 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. I2C Slave API contributed by Brent Roman (brent@mbari.org) + */ + +/** + * @file STM32/I2Cv1/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @brief Peripheral clock frequency. + */ +#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) + +/** + * @brief Invalid I2C bus address + */ +#define i2cInvalidAdr ((i2caddr_t) -1) + + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief Enables support for I2C slave mode operation + */ +#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) +#define HAL_USE_I2C_SLAVE FALSE +#define HAL_USE_I2C_STARTFIX FALSE +#endif + +/** + * @brief Enables additional code needed with V1 I2C + */ +#if !defined(HAL_USE_I2C_STARTFIX) || defined(__DOXYGEN__) +#define HAL_USE_I2C_STARTFIX FALSE +#endif + + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** +* @brief I2C1 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C2 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** +* @brief I2C3 DMA priority (0..3|lowest..highest). +* @note The priority level is used for both the TX and RX DMA streams but +* because of the streams ordering the RX stream has always priority +* over the TX stream. +*/ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif + +#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) + +/** + * @brief DMA stream used for I2C1 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) +#endif + +/** + * @brief DMA stream used for I2C1 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#endif + +/** + * @brief DMA stream used for I2C2 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C2 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#endif + +/** + * @brief DMA stream used for I2C3 RX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) +#endif + +/** + * @brief DMA stream used for I2C3 TX operations. + * @note This option is only available on platforms with enhanced DMA. + */ +#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) +#endif + +#else /* !STM32_ADVANCED_DMA */ + +/* Fixed streams for platforms using the old DMA peripheral, the values are + valid for both STM32F1xx and STM32L1xx.*/ +#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) +#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) +#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) +#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) + +#endif /* !STM32_ADVANCED_DMA*/ + +/* Flag for the whole STM32F1XX family. */ +#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ + defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ + defined(STM32F10X_XL) || defined(STM32F10X_CL) +#define STM32F1XX_I2C +#endif +/** @} */ + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ + !STM32_I2C_USE_I2C3 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C3" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) +#error "I2C1 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) +#error "I2C2 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 RX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif + +/* Check clock range. */ +#if defined(STM32F4XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32L1XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F2XX) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ + defined(STM32F10X_HD_VL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) +#error "I2C peripheral clock frequency out of range." +#endif + +#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ + defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ + defined(STM32F10X_CL) +#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) +#error "I2C peripheral clock frequency out of range." +#endif +#else +#error "unspecified, unsupported or invalid STM32 platform" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing an I2C address. + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C driver condition flags. + */ +typedef uint32_t i2cflags_t; + +/** + * @brief Supported modes for the I2C bus. + */ +typedef enum { + OPMODE_I2C = 1, + OPMODE_SMBUS_DEVICE = 2, + OPMODE_SMBUS_HOST = 3, +} i2copmode_t; + +/** + * @brief Supported duty cycle modes for the I2C bus. + */ +typedef enum { + STD_DUTY_CYCLE = 1, + FAST_DUTY_CYCLE_2 = 2, + FAST_DUTY_CYCLE_16_9 = 3, +} i2cdutycycle_t; + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + +/** + * @brief Driver configuration structure. + */ +typedef struct { + i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ + uint32_t clock_speed; /**< @brief Specifies the clock frequency. + @note Must be set to a value lower + than 400kHz. */ + i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode + duty cycle. */ +#if HAL_USE_I2C_STARTFIX && HAL_USE_I2C_SLAVE + void (*armStartDetect)(void); /**< @brief Arm Start Condition Detector */ + void (*disarmStartDetect)(void);/**< @brief Disarm Start Condition Detector */ +#endif +} I2CConfig; + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +typedef struct I2CSlaveMsg I2CSlaveMsg; + +/* + returns the current I2C slave message receive configuration +*/ +I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp); + + +/* + returns the current I2C slave message reply configuration +*/ +I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp); + + +/* + I2C Slave Message Call Back. + Invoked from interrupt context just after + the last byte of the message is transferred or slaveAdr is matched. + + Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access + the relevant message handling configuration +*/ +typedef void I2CSlaveMsgCB(I2CDriver *i2cp); + + +/* + I2CSlaveMsg message handling configurations are normally + stored in read-only memory. + They describe either a buffer to contain incoming messages from + a bus master and associated callback functions, or one + preloaded with an outgoing reply to a read request and its callbacks. +*/ + +struct I2CSlaveMsg { + size_t size; /* sizeof(body) -- zero if master must wait */ + uint8_t *body; /* message contents -- or NULL if master must wait */ + I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */ + I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */ + I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */ +}; + + +I2CSlaveMsgCB I2CSlaveDummyCB; +/* + dummy callback -- placeholder to ignore event +*/ + + /* lock bus on receive or reply -- force master to wait */ +extern const I2CSlaveMsg I2CSlaveLockOnMsg; + +#endif /* HAL_USE_I2C_SLAVE */ + + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) +#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) + /** + * @brief Mutex protecting the bus. + */ + mutex_t mutex; +#elif CH_CFG_USE_SEMAPHORES + semaphore_t semaphore; +#endif +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + /** + * @brief Current slave address without R/W bit. + */ + i2caddr_t addr; + /** + * @brief Master RX DMA buffer size. + */ + uint16_t masterRxbytes; + /** + * @brief Master TX DMA buffer size. + */ + uint16_t masterTxbytes; + /** + * @brief Master RX DMA buffer base. + */ + uint8_t *masterRxbuf; + /** + * @brief Master TX DMA buffer base. + */ + const uint8_t *masterTxbuf; + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; + + /** + * @brief low level I2C interface / protocol state + */ + enum i2cMode { + i2cIdle=1, /* awaiting address or inactive */ + i2cSlaveRxing, /* receiving message */ + i2cLockedRxing, /* stretching clock before receiving message */ + i2cSlaveReplying, /* replying to query */ + i2cLockedReplying, /* stretching clock before replying to query */ + + i2cIsMaster=0x11, /* sent start bit (mastering bus) */ + i2cMasterStarted, /* repeated start after write */ + i2cMasterSelecting, /* sending slave address */ + i2cMasterRxing, /* receiving reply from slave */ + i2cMasterTxing /* sending message to slave */ + } mode; + +#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE + /** + * @brief I2C transaction timer + */ + virtual_timer_t timer; +#endif +#if HAL_USE_I2C_LOCK + /** + * @brief I2C bus lock duration + */ + systime_t lockDuration; +#endif +#if HAL_USE_I2C_SLAVE + /* additional fields to support I2C slave transactions */ + + /** + * @brief slave address of message being processed + */ + i2caddr_t targetAdr; + /** + * @brief Error Mask for last slave message + */ + i2cflags_t slaveErrors; + /** + * @brief Length of most recently transferred slave message + */ + uint32_t slaveBytes; + /** + * @brief Maximum # of ticks slave may stretch the I2C clock + */ + systime_t slaveTimeout; + /** + * @brief Pointer to slave message reception handler + */ + const I2CSlaveMsg *slaveRx; + /** + * @brief Pointer to slave message Reply handler + */ + const I2CSlaveMsg *slaveReply; + /** + * @brief Pointer to handler for next slave received message + */ + const I2CSlaveMsg *slaveNextRx; + /** + * @brief Pointer to handler for next slave reply message + */ + const I2CSlaveMsg *slaveNextReply; +#endif +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + + +#if HAL_USE_I2C_LOCK +/** + * @brief Unlock I2C bus after the end of the next transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + **/ +#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE) +#endif + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ +/** + * @brief Get slave errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors) + +/** + * @brief Get slave message bytes transferred from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes) + + +/** + * @brief Get slave timeout in ticks from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout) + +/** + * @brief Set slave timeout in ticks for I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks)) + +/** + * @brief Get slave target address from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr) + +/** + * @brief Get slave receive message descriptor from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx) + +/** + * @brief Get slave reply message descriptor from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply) + +#endif + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + +#if HAL_USE_I2C_LOCK /* I2C slave mode support */ + void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration); +#endif +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + void i2c_lld_unmatchAll(I2CDriver *i2cp); + void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); + void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); +#if HAL_USE_I2C_STARTFIX + void i2c_lld_startDetected(I2CDriver *i2cp); + void i2c_lld_noStartDetector(void); +#define i2cNoStartDetector i2c_lld_noStartDetector +#endif +#endif /* HAL_USE_I2C_SLAVE */ + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_LLD_H_ */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv2/driver.mk b/drivers/chibios/i2cslave/I2Cv2/driver.mk new file mode 100644 index 0000000000..06fb82ff8f --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv2/driver.mk @@ -0,0 +1,21 @@ +ifeq ($(USE_HAL_I2C_FALLBACK),yes) + # Fallback SW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C +else + # Default HW driver. + ifeq ($(USE_SMART_BUILD),yes) + ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c + endif + else + PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c + endif + PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2 +endif diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c new file mode 100644 index 0000000000..b6df7c7169 --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c @@ -0,0 +1,2065 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ + +/* +TODO: +1. Make sure slave mode registers updated OK +2. Test what of the newly inserted defines etc is actually necessary +3. Check whether all relevant features available on all ports on all processors (they are on F7, F051) +4. Do we need timer to get involved on master mode transactions? (May be multimaster requirement) +5. What about multimaster? Possibly nothing special to do, other than support all transitions round master and slave modes. +(Manual: "By default, it operates in slave mode. The interface automatically switches from slave to +master when it generates a START condition, and from master to slave if an arbitration loss +or a STOP generation occurs, allowing multimaster capability") +6. Understand use of lock timer - may only be relevant for multimaster, or even unnecessary +7. Check slave transfers > 255 bytes + +NOTES: +1. 10-bit addressing, masking options not currently supported in software in slave mode + (OAR1 hardware supports single 10-bit address matching; OAR2 supports 7-bit addressing with mask) +2. Address zero supported by setting 'General Call' flag in CR1 in slave mode (set with call to match address zero) +3. Clock stretching always enabled +4. Relevant configurable bits in CR1: + ANFOFF (analog noise filter) + DNF (digital noise filter bits) +5. Setting STM32_I2C_DEBUG_ENABLE to TRUE logs various events into a short circular buffer, which can then be examined using +the debugger. Alternatively, a call to i2cPrintQ(BaseSequentialStream *chp) prints the buffer. Note that the buffer only +has a write pointer, so once full its necessary to infer the start and end of the data + + */ + +/** + * @file STM32/I2Cv2/i2c_lld.c + * @brief STM32 I2C subsystem low level driver source. + * + * @addtogroup I2C + * @{ + */ + +#include "hal.h" + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_DMA == TRUE +#define DMAMODE_COMMON \ + (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ + STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ + STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) + +#define I2C1_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_CHN) + +#define I2C1_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_CHN) + +#define I2C2_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_CHN) + +#define I2C2_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_CHN) + +#define I2C3_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_CHN) + +#define I2C3_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_CHN) + +#define I2C4_RX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \ + STM32_I2C4_RX_DMA_CHN) + +#define I2C4_TX_DMA_CHANNEL \ + STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \ + STM32_I2C4_TX_DMA_CHN) +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if STM32_I2C_USE_DMA == TRUE +#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx) +#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx) +#else +#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes +#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes +#endif + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ +#define I2C_ERROR_MASK \ + ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ + I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) + +#define I2C_INT_MASK \ + ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ + I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) + +/* Mask of interrupt bits cleared automatically - we mustn't clear ADDR else clock stretching doesn't happen */ +#define I2C_INT_CLEAR_MASK \ + ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ + I2C_ISR_RXNE | I2C_ISR_TXIS)) + + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/** @brief I2C1 driver identifier.*/ +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +I2CDriver I2CD1; +#endif + +/** @brief I2C2 driver identifier.*/ +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +I2CDriver I2CD2; +#endif + +/** @brief I2C3 driver identifier.*/ +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +I2CDriver I2CD3; +#endif + +/** @brief I2C4 driver identifier.*/ +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +I2CDriver I2CD4; +#endif + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +#if STM32_I2C_DEBUG_ENABLE +/* + * Quick and dirty queue to record event interrupts (useful for debug) + * + * Assigned codes (may be others not noted here): + * 0x02 - NAK received + * 0x03 - transfer complete received + * 0x04 - Address match (records current mode before any error recovery etc) + * 0x05 - STOP received + * 0x06 - Part transfer complete interrupt + * 0x07 - Recovery from untidily finished previous transaction + * 0x08 - Recovery from untidily finished previous transaction + * 0x09 - Recovery from untidily finished previous transaction + * 0x10 - error in slave address match - send + * 0x11 - error in slave address match - receive + * 0x12 - address match - send + * 0x13 - address match - receive + * 0x14 - start slave receive operation + * 0x15 - lock on pending slave receive operation (no buffer) + * 0x16 - start slave transmit operation + * 0x17 - lock on pending slave transmit operation (no buffer available) + * 0x80 - new reply set + * 0x81 - reply used immediately + * 0x82 - new receive buffer set + * 0x83 - receive buffer used immediately + * 0xcc - clearing down after transmission - triggered by NAK received (usually valid) + * 0xd0 - Slave error being signalled + * 0xd1 - Slave error due to timeout +*/ +#define QEVENTS 32 + +typedef struct i2cQ_t { + uint8_t code; + uint8_t state; // Channel state + uint8_t mode; // Mode (mostly for slave) + uint16_t param; // Parameter sometimes used +} i2cQ_t; +i2cQ_t i2cQ[QEVENTS]; +unsigned i2cI = QEVENTS; +#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \ + i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->state); i2cQ[i2cI].mode=(i2cp->mode); i2cQ[i2cI].param=(info); } + +#include "chprintf.h" + +void i2cPrintQ(BaseSequentialStream *chp) +{ + uint8_t i; + if (QEVENTS == 0) + { + chprintf(chp, "I2C Debug queue disabled\r\n"); + } + else + { + chprintf(chp, "I2C debug ring - write pointer currently %02d\r\n", i2cI); + } + for (i = 0; i < QEVENTS; i++) + { + chprintf(chp, "%02d: %02x->%02x %02x %04x\r\n", i, i2cQ[i].code, i2cQ[i].state, i2cQ[i].mode, i2cQ[i].param); + if (i2cQ[i].code == 0) break; // Handle partially filled queue + } +} + +#else +#define qEvt(posn,info) +#endif + + + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + + +void I2CSlaveDummyCB(I2CDriver *i2cp) +/* + dummy callback -- placeholder to ignore event +*/ +{(void)i2cp;} + + /* lock bus on receive or reply message */ +const I2CSlaveMsg I2CSlaveLockOnMsg = { + 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB +}; + +#endif + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +#if HAL_USE_I2C_MASTER +/** + * @brief Slave (remote) address setup in master mode. + * @note The RW bit is set to zero internally. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * + * @notapi + */ +static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Address alignment depends on the addressing mode selected.*/ + if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) + dp->CR2 = (uint32_t)addr << 1U; + else + dp->CR2 = (uint32_t)addr; +} +#endif + + + +/** + * @brief I2C RX transfer setup. + * @note Configures transfer count and related flags + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation (device constraint). */ +#if STM32_I2C_USE_DMA + if (i2cp->config->rxchar_cb) + { + n = i2cp->rxbytes; // Always interrupt-driven if we have a receive callback + } + else + { + n = i2c_lld_get_rxbytes(i2cp); // Otherwise get length from DMA or counter as appropriate + } +#else + n = i2cp->rxbytes; +#endif + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + + /* Configures the CR2 registers with both the calculated and static + settings. (Nothing much relevant in static settings - just PEC for SMBUS? */ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | I2C_CR2_RD_WRN | + (n << 16U) | reload; +} + + + +/** + * @brief I2C TX transfer setup. + * @note Configures transfer count and related flags + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + uint32_t reload; + size_t n; + + /* The unit can transfer 255 bytes maximum in a single operation. */ + n = i2c_lld_get_txbytes(i2cp); // Get transaction size from DMA or buffer as configured + if (n > 255U) { + n = 255U; + reload = I2C_CR2_RELOAD; + } + else { + reload = 0U; + } + + /* Configures the CR2 registers with both the calculated and static + settings.*/ + dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | + (n << 16U) | reload; +} + + + +/** + * @brief Aborts an I2C transaction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void i2c_lld_abort_operation(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + +// Note: clearing PE doesn't affect configuration bits (including slave addresses) + if (dp->CR1 & I2C_CR1_PE) { + /* Stops the I2C peripheral.*/ + dp->CR1 &= ~I2C_CR1_PE; + while (dp->CR1 & I2C_CR1_PE) + dp->CR1 &= ~I2C_CR1_PE; + dp->CR1 |= I2C_CR1_PE; + } + +#if STM32_I2C_USE_DMA == TRUE + /* Stops the associated DMA streams.*/ + dmaStreamDisable(i2cp->dmatx); + dmaStreamDisable(i2cp->dmarx); +#else + dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); // Stop byte-orientated interrupts +#endif +} + + + +#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK +/** + * @brief stop transaction timeout countdown + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static inline void stopTimer(I2CDriver *i2cp) +{ + osalSysLockFromISR(); + chVTResetI(&i2cp->timer); + osalSysUnlockFromISR(); +} +#else +#define stopTimer(ignored) {} +#endif + + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +/** + * @brief report error via slave exception callback + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @note moves back to the idle mode + * @notapi + */ +static inline void reportSlaveError(I2CDriver *i2cp) { + if (i2cp->mode >= i2cIsMaster) return; + qEvt(0xd0, i2cp->slaveErrors); + const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ? + i2cp->slaveReply : i2cp->slaveRx; + if (xfer->exception) + xfer->exception(i2cp); + i2cp->mode = i2cIdle; + i2cp->targetAdr = i2cInvalidAdr; +} + + +/** + * @brief Handling of stalled slave mode I2C transactions - timer handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static void slaveTimeExpired(void *i2cv) { + I2CDriver *i2cp = i2cv; + + if (i2cp->mode < i2cIsMaster) + { + i2c_lld_abort_operation(i2cp); + reportSlaveError(i2cp); + qEvt(0xd1, 0); + } +} + + +/** + * @brief start or restart slave mode transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] targetAdr slave address which was matched + * + * @notapi + */ +static inline void i2cStartSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr) +{ + stopTimer(i2cp); + i2cp->targetAdr = targetAdr; + i2cp->slaveBytes = 0; + i2cp->slaveErrors = 0; + if (i2cp->slaveTimeout != TIME_INFINITE) + { + osalSysLockFromISR(); + chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp); + osalSysUnlockFromISR(); + } +} + + +/** + * @brief end slave receive message DMA + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +static inline void i2cEndSlaveRxDMA(I2CDriver *i2cp) +{ + size_t bytesRemaining = i2c_lld_get_rxbytes(i2cp); + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff - bytesRemaining; + else + i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining; +#if STM32_I2C_USE_DMA == TRUE + /* Disabling RX DMA channel.*/ + dmaStreamDisable(i2cp->dmarx); +#else + i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE); +#endif +} + + + +/** + * @brief end slave transmit DMA + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] bytesRemaining bytes lost in output queue + * + * @notapi + */ +static inline void i2cEndSlaveTxDMA(I2CDriver *i2cp, size_t bytesRemaining) +{ + bytesRemaining += i2c_lld_get_rxbytes(i2cp); + if (i2cp->slaveBytes) + i2cp->slaveBytes += 0xffff - bytesRemaining; + else + i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining; +#if STM32_I2C_USE_DMA == TRUE + /* Disabling TX DMA channel.*/ + dmaStreamDisable(i2cp->dmatx); +#else + i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE); +#endif +} + +#endif + + + + +/** + * @brief Start a receive transaction (by enabling DMA, or enabling Rx character interrupts) + * + * @note All registers etc must be set up first + */ +static inline void i2cStartReceive(I2CDriver *i2cp) +{ +#if STM32_I2C_USE_DMA == TRUE + if (i2cp->config->rxchar_cb) + { + // Callback in use - use interrupt-driven transfer + i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; + } + else + { + /* Enabling RX DMA.*/ + dmaStreamEnable(i2cp->dmarx); + + /* Transfer complete interrupt enabled.*/ + i2cp->i2c->CR1 |= I2C_CR1_TCIE; + } +#else + + /* Transfer complete and RX interrupts enabled.*/ + i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; +#endif +} + + +/** + * @brief Disable transmit data transfer, whether DMA or interrupt-driven + */ +static inline void i2cDisableTransmitOperation(I2CDriver *i2cp) +{ +#if STM32_I2C_USE_DMA == TRUE + /* Disabling TX DMA channel.*/ + dmaStreamDisable(i2cp->dmatx); +#else + i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE); +#endif +} + + +/** + * @brief Disable receive data transfer, whether DMA or interrupt-driven + */ +static inline void i2cDisableReceiveOperation(I2CDriver *i2cp) +{ +#if STM32_I2C_USE_DMA == TRUE + /* Disabling RX DMA channel.*/ + dmaStreamDisable(i2cp->dmarx); +#else + i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE); +#endif +} + + + +/*===========================================================================*/ +/* Shared ISR Code */ +/*===========================================================================*/ + +/** + * @brief I2C shared ISR code - 'Normal' (non-error) interrupts. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded (no masking applied) + * + * @notapi + */ +static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { + I2C_TypeDef *dp = i2cp->i2c; + + /* Check for received NACK, the transfer is aborted. Do this in all modes */ + if ((isr & I2C_ISR_NACKF) != 0U) + { + qEvt(2, 0); + + i2cDisableReceiveOperation(i2cp); + i2cDisableTransmitOperation(i2cp); + #if HAL_USE_I2C_SLAVE + /* NACK of last byte transmitted in slave response is NORMAL -- not an error! */ + if (i2cp->mode == i2cSlaveReplying) + { + qEvt(0xcc,0); + i2cEndSlaveTxDMA(i2cp, 1); + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + i2cp->targetAdr = i2cInvalidAdr; + stopTimer(i2cp); + return; + } + #endif + + /* Error flag.*/ + i2cp->errors |= I2C_ACK_FAILURE; + + /* Transaction finished, send the STOP. */ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more interrupts.*/ + dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); + + if (i2cp->mode < i2cIsMaster) + { + i2cp->mode = i2cIdle; + } + else + { + /* Master mode - Errors are signalled to the upper layer.*/ + i2cp->mode = i2cIdle; + // Must only wake up thread in master mode. + _i2c_wakeup_isr(i2cp); // This is a normal completion + } + + return; + } + + +#if STM32_I2C_USE_DMA == FALSE + /* Handling of data transfer if the DMA mode is disabled - done character by character. Mode should be irrelevant */ + { + uint32_t cr1 = dp->CR1; + + if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying)) + { + /* Transmission phase.*/ + if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { + dp->TXDR = (uint32_t)*i2cp->txptr; + i2cp->txptr++; + i2cp->txbytes--; + if (i2cp->txbytes == 0U) { + dp->CR1 &= ~I2C_CR1_TXIE; // Last byte sent - stop Tx interrupt + } + } + } + else + { + /* Receive phase.*/ + if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { + uint8_t c; + *i2cp->rxptr = c = (uint8_t)dp->RXDR; + i2cp->rxptr++; + i2cp->rxbytes--; + if (i2cp->config->rxchar_cb) + { + if (i2cp->config->rxchar_cb(i2cp, c) > 0) + { + /* Transaction finished, send the STOP. */ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more interrupts.*/ + dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); + + if (i2cp->mode < i2cIsMaster) + { + i2cp->mode = i2cIdle; + } + else + { + /* Master mode - Errors are signalled to the upper layer.*/ + i2cp->mode = i2cIdle; + // Must only wake up thread in master mode. + _i2c_wakeup_isr(i2cp); // This is a normal completion + } + + return; + } + } + if (i2cp->rxbytes == 0U) { + dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode) + } + } + } + } +#else + /* Receive character phase with callback enabled. */ + if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cMasterRxing)) + { + uint32_t cr1 = dp->CR1; + if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { + uint8_t c; + c = (uint8_t)dp->RXDR; + *i2cp->rxptr = c; + i2cp->rxptr++; + i2cp->rxbytes--; + if (i2cp->config->rxchar_cb) + { + if (i2cp->config->rxchar_cb(i2cp, c) > 0) + { + /* Transaction finished, send the STOP. */ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more interrupts.*/ + dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); + + if (i2cp->mode < i2cIsMaster) + { + i2cp->mode = i2cIdle; + } + else + { + /* Master mode - Errors are signalled to the upper layer.*/ + i2cp->mode = i2cIdle; + // Must only wake up thread in master mode. + _i2c_wakeup_isr(i2cp); // This is a normal completion + } + + return; + } + } + if (i2cp->rxbytes == 0U) { + dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode) + } + } + } +#endif + + + + /* Partial transfer handling, restarting the transfer and returning. */ + if ((isr & I2C_ISR_TCR) != 0U) + { + qEvt(0x06, 0); + if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying)) { + i2c_lld_setup_tx_transfer(i2cp); + } + if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cSlaveRxing)) { + i2c_lld_setup_rx_transfer(i2cp); + } + return; + } + + + + /* The following condition is true if a transfer phase has been completed. */ + if ((isr & I2C_ISR_TC) != 0U) + { + qEvt(3,i2cp->state); +#if HAL_USE_I2C_SLAVE + switch (i2cp->mode) + { + case i2cLockedRxing : /* stretching clock before receiving message - Rx buffer might be full */ + case i2cLockedReplying : + break; // TODO: Two unsupported cases to consider - maybe they can't happen + case i2cSlaveReplying : // Must have just finished sending a reply in slave mode + break; // Just go on to send STOP bit and tidy up + + case i2cSlaveRxing : // Must have just received a message - process if we can + i2cEndSlaveRxDMA(i2cp); + qEvt(0x20, 0); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); + // TODO: Should get a reply message set - if so, start to send it and return + return; // For now, see what happens if we just return + break; + default : // Assume a master mode +#endif + if (i2cp->state == I2C_ACTIVE_TX) { + /* End of the transmit phase.*/ + + i2cDisableTransmitOperation(i2cp); // Disable + + /* Starting receive phase if necessary.*/ + if (i2c_lld_get_rxbytes(i2cp) > 0U) { + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + + #if STM32_I2C_USE_DMA == TRUE + // If receive callback enabled, always transfer using interrupts + if (i2cp->config->rxchar_cb) + { + /* RX interrupt enabled.*/ + dp->CR1 |= I2C_CR1_RXIE; + } + else + { + /* Enabling RX DMA.*/ + dmaStreamEnable(i2cp->dmarx); + } + #else + /* RX interrupt enabled.*/ + dp->CR1 |= I2C_CR1_RXIE; + #endif + + /* Starts the read operation.*/ + dp->CR2 |= I2C_CR2_START; + + /* State change.*/ + i2cp->state = I2C_ACTIVE_RX; + i2cp->mode = i2cMasterRxing; + + /* Note, returning because the transaction is not over yet.*/ + return; + } + } + else + { + /* End of the receive phase.*/ + i2cDisableReceiveOperation(i2cp); + } + +#if HAL_USE_I2C_SLAVE + } +#endif + + /* Transaction finished sending the STOP. */ + dp->CR2 |= I2C_CR2_STOP; + + /* Make sure no more 'Transfer Complete' interrupts. */ + dp->CR1 &= ~I2C_CR1_TCIE; + + /* Normal transaction end.*/ + if (i2cp->mode < i2cIsMaster) + { + // Slave mode - just move to idle state + i2cp->mode = i2cIdle; + } + else + { + i2cp->mode = i2cIdle; + // Must only wake up thread in master mode + _i2c_wakeup_isr(i2cp); + } + } + + +#if HAL_USE_I2C_SLAVE + uint8_t abort = 0; + /* Check for address match - if so, we're slave */ + if ((isr & I2C_ISR_ADDR) != 0U) + { + i2caddr_t targetAdr = (isr & I2C_ISR_ADDCODE) >> 17; // Identify which slave address used + uint8_t xferDir = (isr & I2C_ISR_DIR) ? 0 : 1; // Status bit is 0 for receive, 1 for transmit. xferDir inverts sense + dp->CR1 |= I2C_CR1_STOPIE; // Enable STOP interrupt so we know when slave transaction done + + /* First, tidy up from previous transactions as necessary */ + qEvt(0x04, 0); + switch (i2cp->mode) { + case i2cIdle: + break; + case i2cSlaveRxing: /* Previous transaction not completed properly, or + maybe we were sent a message without being asked for a reply */ + qEvt(0x07, 0); + i2cEndSlaveRxDMA(i2cp); + if (i2cp->slaveRx->processMsg) + i2cp->slaveRx->processMsg(i2cp); // Execute callback if defined + break; + case i2cSlaveReplying: /* Master did not NACK last transmitted byte (most likely picked up by NAK handler) */ + qEvt(0x08, 0); + if (!xferDir) + { + qEvt(0x09, 0); + i2cEndSlaveTxDMA(i2cp, 2); + if (i2cp->slaveReply->processMsg) + i2cp->slaveReply->processMsg(i2cp); + break; + } + // Intentionally don't break if we're addressed to receive + default: + // todo: Does this lot happen in the right order? Is an abort appropriate? Or should we just continue? + qEvt(0x10 + xferDir, 0); + i2cp->slaveErrors = I2C_UNKNOWN_ERROR + i2cp->mode; + i2c_lld_abort_operation(i2cp); /* reset and reinit */ + stopTimer(i2cp); + reportSlaveError(i2cp); // This clears down to idle + abort = 1; + } + if (!abort) + { + qEvt(0x12 + xferDir, (i2cp->slaveNextRx->size)); + if (xferDir) + { + /* Start Receive */ + /* If receive buffer still full, need to extend clock for timeout. Otherwise set up to receive */ + dp->CR1 &= ~I2C_CR1_SBC; // Not needed with receive + i2cStartSlaveAction(i2cp, targetAdr); + + const I2CSlaveMsg *rx = i2cp->slaveNextRx; + if (rx->adrMatched) // Q: Can rx ever be NULL? + rx->adrMatched(i2cp); // Execute callback on address match if specified + rx = i2cp->slaveRx = i2cp->slaveNextRx; // Reload message pointer in case callback changed it + if (rx->body && rx->size) + { + /* Receive buffer available - can receive immediately. Set up slave RX DMA */ + i2c_lld_setup_rx_transfer(i2cp); + #if STM32_I2C_USE_DMA == TRUE + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rx->body); + dmaStreamSetTransactionSize(i2cp->dmarx, rx->size); + #else + i2cp->rxptr = rx->body; + i2cp->rxbytes = rx->size; + #endif + + i2cStartReceive(i2cp); + dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now + i2cp->mode = i2cSlaveRxing; + qEvt(0x14,0); + } + else + { + /* No reply set up - hold clock low and wait (happens automatically) */ + qEvt(0x15,0); + i2cp->mode = i2cLockedRxing; + } + } + else + { + /* Start Transmit */ + i2cStartSlaveAction(i2cp, targetAdr); + const I2CSlaveMsg *reply = i2cp->slaveNextReply; + const I2CSlaveMsg *rx = i2cp->slaveNextRx; // Receive control block + if (rx->adrMatched) // Q: Can rx ever be NULL? + rx->adrMatched(i2cp); // Execute callback on address match if specified + reply = i2cp->slaveReply = i2cp->slaveNextReply; // Reload message pointer in case callback changed it + if (reply->body && reply->size) + { + /* Reply message available - can send immediately. Set up slave TX DMA */ + #if STM32_I2C_USE_DMA == TRUE + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, reply->body); + dmaStreamSetTransactionSize(i2cp->dmatx, reply->size); + /* Start transmission */ + i2c_lld_setup_tx_transfer(i2cp); + + /* Enabling TX DMA.*/ + dmaStreamEnable(i2cp->dmatx); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; + #else + /* Start transmission */ + i2cp->txptr = reply->body; + i2cp->txbytes = reply->size; + i2c_lld_setup_tx_transfer(i2cp); + /* Transfer complete and TX character interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; + #endif + qEvt(0x16,0); + i2cp->mode = i2cSlaveReplying; + dp->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode + dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now + } + else + { + // clock is automatically stretched if we don't clear the status bit + //dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); + qEvt(0x17, 0); + i2cp->mode = i2cLockedReplying; + } + } + } /* if !abort */ + } + if ((isr & I2C_ISR_STOPF) != 0U) { + /* + * STOP received: + * in master mode, if generated by peripheral - can probably just ignore + * in slave mode, if detected on bus (from any source?) + * + * Clear everything down - particularly relevant in slave mode + */ + qEvt(0x05, 0); + dp->CR1 &= ~I2C_CR1_STOPIE; // Disable STOP interrupt + i2cDisableReceiveOperation(i2cp); // These two may not be necessary + i2cDisableTransmitOperation(i2cp); + stopTimer(i2cp); + i2cp->mode = i2cIdle; + } +#endif +} + + + +/** + * @brief I2C error handler. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] isr content of the ISR register to be decoded (no masking applied) + * + * @notapi + */ +static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { + + i2cDisableReceiveOperation(i2cp); + i2cDisableTransmitOperation(i2cp); + stopTimer(i2cp); + +#if HAL_USE_I2C_SLAVE + // In slave mode, just clock errors and return + if (i2cp->mode < i2cIsMaster) + { + reportSlaveError(i2cp); // This clears down to idle + return; + } +#endif + + if (isr & I2C_ISR_BERR) + i2cp->errors |= I2C_BUS_ERROR; + + if (isr & I2C_ISR_ARLO) + i2cp->errors |= I2C_ARBITRATION_LOST; + + if (isr & I2C_ISR_OVR) + i2cp->errors |= I2C_OVERRUN; + + if (isr & I2C_ISR_TIMEOUT) + i2cp->errors |= I2C_TIMEOUT; + + /* If some error has been identified then wake up the waiting thread.*/ + if (i2cp->errors != I2C_NO_ERROR) + { + i2cp->mode = i2cIdle; + _i2c_wakeup_error_isr(i2cp); + } +} + + + + + +#if HAL_USE_I2C_LOCK /* I2C bus locking support */ + +/** + * @brief Handling of expired master bus lock timer + * + * @param[in] i2cv pointer to the @p I2CDriver object + * + * @notapi + */ +static void lockExpired(void *i2cv) { + I2CDriver *i2cp = i2cv; + + if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */ + i2cp->i2c->CR2 |= I2C_CR2_STOP; + i2cp->mode = i2cIdle; + } + i2cp->lockDuration = TIME_IMMEDIATE; +} + + + + +/** + * @brief Lock I2C bus at the beginning of the next message + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] lockDuration max number of ticks to hold bus locked + * - @a TIME_INFINITE no timeout. + * - @a TIME_IMMEDIATE unlock the bus immediately + * . + * + * Lock I2C bus at the beginning of the next message sent + * for a maximum of lockDuration ticks. No other I2C masters will + * be allowed to interrupt until i2cUnlock() is called. + * + * @notapi + **/ +void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration) +{ + i2cp->lockDuration = lockDuration; + if (i2cp->mode >= i2cIsMaster) { + stopTimer(i2cp); + if (lockDuration == TIME_IMMEDIATE) + lockExpired(i2cp); + else if (lockDuration != TIME_INFINITE) + chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); + } +} + +#endif + +/*===========================================================================*/ +/* Driver interrupt handlers. */ +/*===========================================================================*/ + +#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) +#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C1 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & ~I2C_ISR_ADDR; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD1, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_INT_CLEAR_MASK; + + i2c_lld_serve_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { + uint32_t isr = I2CD1.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD1, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C1 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) +#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C2 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & ~I2C_ISR_ADDR; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD2, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_INT_CLEAR_MASK; + + i2c_lld_serve_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { + uint32_t isr = I2CD2.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD2, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C2 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) +#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C3 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & ~I2C_ISR_ADDR; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD3, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_INT_CLEAR_MASK; + + i2c_lld_serve_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { + uint32_t isr = I2CD3.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD3, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C3 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) +#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) +/** + * @brief I2C4 event interrupt handler. + * + * @notapi + */ +OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & ~I2C_ISR_ADDR; + + if (isr & I2C_ERROR_MASK) + i2c_lld_serve_error_interrupt(&I2CD4, isr); + else if (isr & I2C_INT_MASK) + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) +OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_INT_CLEAR_MASK; + + i2c_lld_serve_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { + uint32_t isr = I2CD4.i2c->ISR; + + OSAL_IRQ_PROLOGUE(); + + /* Clearing IRQ bits.*/ + I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; + + i2c_lld_serve_error_interrupt(&I2CD4, isr); + + OSAL_IRQ_EPILOGUE(); +} + +#else +#error "I2C4 interrupt handlers not defined" +#endif +#endif /* STM32_I2C_USE_I2C4 */ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief Low level I2C driver initialization. + * + * @notapi + */ +void i2c_lld_init(void) { + +#if STM32_I2C_USE_I2C1 + i2cObjectInit(&I2CD1); + I2CD1.thread = NULL; + I2CD1.i2c = I2C1; +#if STM32_I2C_USE_DMA == TRUE + I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); + I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); +#endif +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + i2cObjectInit(&I2CD2); + I2CD2.thread = NULL; + I2CD2.i2c = I2C2; +#if STM32_I2C_USE_DMA == TRUE + I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); + I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); +#endif +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + i2cObjectInit(&I2CD3); + I2CD3.thread = NULL; + I2CD3.i2c = I2C3; +#if STM32_I2C_USE_DMA == TRUE + I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); + I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); +#endif +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + i2cObjectInit(&I2CD4); + I2CD4.thread = NULL; + I2CD4.i2c = I2C4; +#if STM32_I2C_USE_DMA == TRUE + I2CD4.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM); + I2CD4.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM); +#endif +#endif /* STM32_I2C_USE_I2C4 */ +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_start(I2CDriver *i2cp) { + I2C_TypeDef *dp = i2cp->i2c; + +#if STM32_I2C_USE_DMA == TRUE + /* Common DMA modes.*/ + i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; + i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; +#endif + + /* Make sure I2C peripheral is disabled */ + dp->CR1 &= ~I2C_CR1_PE; + i2cp->mode = i2cStopped; + + /* If in stopped state then enables the I2C and DMA clocks.*/ + if (i2cp->state == I2C_STOP) { + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { + + rccResetI2C1(); + rccEnableI2C1(FALSE); +#if STM32_I2C_USE_DMA == TRUE + { + bool b; + + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C1_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); + } +#endif /* STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); +#else +#error "I2C1 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C1 */ + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { + + rccResetI2C2(); + rccEnableI2C2(FALSE); +#if STM32_I2C_USE_DMA == TRUE + { + bool b; + + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C2_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); + } +#endif /*STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); +#else +#error "I2C2 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C2 */ + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { + + rccResetI2C3(); + rccEnableI2C3(FALSE); +#if STM32_I2C_USE_DMA == TRUE + { + bool b; + + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C3_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); + } +#endif /*STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) + nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); +#else +#error "I2C3 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C3 */ + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { + + rccResetI2C4(); + rccEnableI2C4(FALSE); +#if STM32_I2C_USE_DMA == TRUE + { + bool b; + + b = dmaStreamAllocate(i2cp->dmarx, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + b = dmaStreamAllocate(i2cp->dmatx, + STM32_I2C_I2C4_IRQ_PRIORITY, + NULL, + (void *)i2cp); + osalDbgAssert(!b, "stream already allocated"); + + i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) | + STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); + } +#endif /*STM32_I2C_USE_DMA == TRUE */ + +#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) + nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); + nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); +#else +#error "I2C4 interrupt numbers not defined" +#endif + } +#endif /* STM32_I2C_USE_I2C4 */ + } + +#if STM32_I2C_USE_DMA == TRUE + /* I2C registers pointed by the DMA.*/ + dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); + dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); + /* Reset i2c peripheral, the TCIE bit will be handled separately. */ + // TODO: Mask out config bits which user mustn't fiddle with + dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE | + I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN); +#else + /* Reset i2c peripheral, the TCIE bit will be handled separately. No DMA interrupts */ + dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE); +#endif + + /* Setup I2C parameters.*/ + dp->TIMINGR = i2cp->config->timingr; + + /* Ready to go.*/ + i2cp->mode = i2cIdle; +#if HAL_USE_I2C_LOCK + i2cp->lockDuration = TIME_IMMEDIATE; +#endif +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg; + i2cp->targetAdr = i2cInvalidAdr; + i2cp->slaveTimeout = TIME_INFINITE; +#endif + + dp->CR1 |= I2C_CR1_PE; // Enable peripheral +} + + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +void i2c_lld_stop(I2CDriver *i2cp) { + + /* If not in stopped state then disables the I2C clock.*/ + if (i2cp->state != I2C_STOP) { + i2cp->mode = i2cStopped; + + /* I2C disable.*/ + stopTimer(i2cp); + i2c_lld_abort_operation(i2cp); +#if STM32_I2C_USE_DMA == TRUE + dmaStreamRelease(i2cp->dmatx); + dmaStreamRelease(i2cp->dmarx); +#endif + +#if STM32_I2C_USE_I2C1 + if (&I2CD1 == i2cp) { +#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); +#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) + nvicDisableVector(STM32_I2C1_EVENT_NUMBER); + nvicDisableVector(STM32_I2C1_ERROR_NUMBER); +#else +#error "I2C1 interrupt numbers not defined" +#endif + + rccDisableI2C1(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C2 + if (&I2CD2 == i2cp) { +#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); +#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) + nvicDisableVector(STM32_I2C2_EVENT_NUMBER); + nvicDisableVector(STM32_I2C2_ERROR_NUMBER); +#else +#error "I2C2 interrupt numbers not defined" +#endif + + rccDisableI2C2(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C3 + if (&I2CD3 == i2cp) { +#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER); +#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) + nvicDisableVector(STM32_I2C3_EVENT_NUMBER); + nvicDisableVector(STM32_I2C3_ERROR_NUMBER); +#else +#error "I2C3 interrupt numbers not defined" +#endif + + rccDisableI2C3(FALSE); + } +#endif + +#if STM32_I2C_USE_I2C4 + if (&I2CD4 == i2cp) { +#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) + nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER); +#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) + nvicDisableVector(STM32_I2C4_EVENT_NUMBER); + nvicDisableVector(STM32_I2C4_ERROR_NUMBER); +#else +#error "I2C4 interrupt numbers not defined" +#endif + + rccDisableI2C4(FALSE); + } +#endif + } +} + + + +#if HAL_USE_I2C_MASTER == TRUE +/** + * Utility routine brings out common code for master timeout + */ +static msg_t calcMasterTimeout(I2CDriver *i2cp) +{ + systime_t start, end; + + osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); + + /* Calculating the time window for the timeout on the busy bus condition.*/ + start = osalOsGetSystemTimeX(); + end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); + + /* Waits until BUSY flag is reset or, alternatively, for a timeout + condition.*/ + while (true) { + osalSysLock(); + + /* If the bus is not busy then the operation can continue, note, the + loop is exited in the locked state.*/ +// if (!(i2cp->i2c->ISR & I2C_ISR_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP)) + if (!(i2cp->i2c->ISR & I2C_ISR_BUSY)) + break; + + /* If the system time went outside the allowed window then a timeout + condition is returned.*/ + if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) + return MSG_TIMEOUT; + + osalSysUnlock(); + // TODO: Should we relinquish thread here for a while? + chThdSleepMilliseconds(2); + } + i2cp->mode = i2cIsMaster; // We can set master mode now + return MSG_OK; +} + + +/** + * Start a master mode transaction + * + * Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout() + */ +static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) +{ +#if STM32_I2C_USE_DMA == TRUE +#else +#endif + msg_t msg; + + /* Starts the operation.*/ + i2cp->i2c->CR2 |= I2C_CR2_START; + + /* Waits for the operation completion or a timeout.*/ + msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); + + /* In case of a software timeout a STOP is sent as an extreme attempt + to release the bus.*/ + if (msg == MSG_TIMEOUT) { + i2cp->i2c->CR2 |= I2C_CR2_STOP; + i2cp->mode = i2cIdle; // TODO: Is this enough? + } + return msg; +} + + +/** + * @brief Receives data via the I2C bus as master. + * @details Number of receiving bytes must be more than 1 on STM32F1x. This is + * hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { +// I2C_TypeDef *dp = i2cp->i2c; + + osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection + + +#if STM32_I2C_USE_DMA == TRUE + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#endif + // Always set up the receive buffer in case callbacks enabled + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Setting up the peripheral.*/ + i2c_lld_setup_rx_transfer(i2cp); + + i2cStartReceive(i2cp); + i2cp->mode = i2cMasterRxing; + + return startMasterAction(i2cp, timeout); +} + + + +/** + * @brief Transmits data via the I2C bus as master. + * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. + * This is hardware restriction. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address + * @param[in] txbuf pointer to the transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to the receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a + * timeout the driver must be stopped and restarted + * because the bus is in an uncertain state. + * + * @notapi + */ +msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout) { + I2C_TypeDef *dp = i2cp->i2c; + + osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); + + /* Resetting error flags for this transfer.*/ + i2cp->errors = I2C_NO_ERROR; + + /* Releases the lock from high level driver.*/ + osalSysUnlock(); + + calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection + + +#if STM32_I2C_USE_DMA == TRUE + /* TX DMA setup.*/ + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, txbuf); + dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); + + /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxbuf); + dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); +#else + i2cp->txptr = txbuf; + i2cp->txbytes = txbytes; +#endif + // Always set up the receive buffer in case callbacks enabled + i2cp->rxptr = rxbuf; + i2cp->rxbytes = rxbytes; + + /* Setting up the slave address.*/ + i2c_lld_set_address(i2cp, addr); + + /* Preparing the transfer.*/ + i2c_lld_setup_tx_transfer(i2cp); + +#if STM32_I2C_USE_DMA == TRUE + /* Enabling TX DMA.*/ + dmaStreamEnable(i2cp->dmatx); + + /* Transfer complete interrupt enabled.*/ + dp->CR1 |= I2C_CR1_TCIE; +#else + /* Transfer complete and TX interrupts enabled.*/ + dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; +#endif + + i2cp->mode = i2cMasterTxing; + + return startMasterAction(i2cp, timeout); +} +#endif /* #if HAL_USE_I2C_MASTER == TRUE */ + + + + +#if HAL_USE_I2C_SLAVE +/************************************************************************/ +/* SLAVE MODE SUPPORT */ +/************************************************************************/ + +/** + * @brief Reconfigure I2C channel to respond to passed address + * in addition to those previously made active + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C network address + * + * @return Length of message OR the type of event received + * @retval I2C_OK Success + * @retval I2C_ERROR Cannot match address in addition of those already + * + * @details MatchAddress calls are cumulative. + * Specify address zero to match I2C "all call" + * Does not support 10-bit addressing. + * Number of supported addresses is chip-dependent - 2+general call on I2CV2 + * Address masking capabilities of OAR2 not supported + * + * @notapi + **/ +msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + I2C_TypeDef *dp = i2cp->i2c; + if (i2cadr == 0) { + dp->CR1 |= I2C_CR1_GCEN; // Just enable General Call + dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled + } + else + { + uint32_t adr = i2cadr << 1; + if ((dp->OAR1 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR1 + if ((dp->OAR2 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR2 + + if (!(dp->OAR1 & I2C_OAR1_OA1EN)) { + dp->OAR1 = adr | I2C_OAR1_OA1EN; // OAR1 previously unused + dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled + } + else + if (!(dp->OAR2 & I2C_OAR2_OA2EN)) { + dp->OAR2 = adr | I2C_OAR2_OA2EN; // OAR2 previously unused + dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled + } + else + return I2C_ERROR; /* cannot add this address to set of those matched */ + } + return I2C_OK; +} + + +/** + * @brief Reconfigure I2C channel to no longer match specified address + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C network address + * + * @details A message being transferred that has already matched the + * specified address will continue being processed. + * Requests to unmatch an address that is not currently being matched + * are ignored. + * Does not support 10-bit addressing. + * + * @notapi + **/ +void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + I2C_TypeDef *dp = i2cp->i2c; + if (i2cadr == 0) { + dp->CR1 &= (uint32_t)~I2C_CR1_GCEN; // Disable General Call + } + else { + uint32_t adr = i2cadr << 1; + if ((dp->OAR1 & (0x7f<<1)) == adr) { + // Matched in OAR1 + dp->OAR1 &= ~I2C_OAR1_OA1EN; // Just disable - OAR2 is a bit different + } + else + if ((dp->OAR2 & I2C_OAR2_OA2EN) && (dp->OAR2 & (0x7f<<1)) == adr) + dp->OAR2 &= ~I2C_OAR2_OA2EN; + } + if (!((dp->CR1 & (uint32_t)I2C_CR1_GCEN) || (dp->OAR1 & I2C_OAR1_OA1EN) || (dp->OAR2 & I2C_OAR2_OA2EN))) { + dp->CR1 &= (uint32_t)~(I2C_CR1_ADDRIE); // Disable Address match interrupts if nothing can generate them (strictly necessary??) + } +} + + +/** + * @brief Reconfigure I2C channel to no longer match any address + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details Causes all subsequent messages to be ignored. + * A message being transferred that has already matched a + * slave address will continue being processed. + * + * @notapi + **/ +void i2c_lld_unmatchAll(I2CDriver *i2cp) +{ + I2C_TypeDef *dp = i2cp->i2c; + dp->CR1 &= (uint32_t)~(I2C_CR1_GCEN | I2C_CR1_ADDRIE); // Disable General Call + dp->OAR1 = 0; + dp->OAR2 = 0; +} + + +/** + * @brief Configure callbacks & buffers to receive messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @notapi + */ +void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) +{ + osalDbgCheck((rxMsg && rxMsg->size <= 0xffff)); + qEvt(0x82, rxMsg->size); + i2cp->slaveNextRx = rxMsg; + if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) { + /* We can receive now! */ + i2cp->slaveRx = rxMsg; + /* slave RX DMA setup */ +#if STM32_I2C_USE_DMA == TRUE + /* RX DMA setup.*/ + dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); + dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body); + dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size); +#else + i2cp->rxptr = rxMsg->body; + i2cp->rxbytes = rxMsg->size; +#endif + + i2cp->mode = i2cSlaveRxing; + i2c_lld_setup_rx_transfer(i2cp); // Set up the transfer + qEvt(0x83, 0); + i2cStartReceive(i2cp); + i2cp->i2c->CR1 &= ~I2C_CR1_SBC; // Not needed with receive + i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now + } +} + + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @notapi + */ +void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) +{ + osalDbgCheck((replyMsg && replyMsg->size <= 0xffff)); + qEvt(0x80, replyMsg->size); + i2cp->slaveNextReply = replyMsg; + if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size) + { + i2cp->slaveReply = replyMsg; + /* slave TX setup -- we can reply now! */ + #if STM32_I2C_USE_DMA == TRUE + dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); + dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body); + dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size); + i2cp->mode = i2cSlaveReplying; + /* Start transmission */ + i2c_lld_setup_tx_transfer(i2cp); + + /* Enabling TX DMA.*/ + dmaStreamEnable(i2cp->dmatx); + + /* Transfer complete interrupt enabled.*/ + i2cp->i2c->CR1 |= I2C_CR1_TCIE; + #else + /* Start transmission */ + i2cp->txptr = replyMsg->body; + i2cp->txbytes = replyMsg->size; + i2c_lld_setup_tx_transfer(i2cp); + /* Transfer complete and TX character interrupts enabled.*/ + i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; + #endif + qEvt(0x81, 0); + i2cp->i2c->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode + i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now + } +} + +#endif /* HAL_USE_I2C_SLAVE */ + + +#endif /* HAL_USE_I2C */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h new file mode 100644 index 0000000000..c4df28fb2e --- /dev/null +++ b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h @@ -0,0 +1,806 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. I2C Slave API for Chibios V2.x V1 I2C originally contributed + by Brent Roman (brent@mbari.org), ported to Chibios V3, V2 I2C by steved + */ + +/** + * @file STM32/I2Cv2/i2c_lld.h + * @brief STM32 I2C subsystem low level driver header. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_LLD_H_ +#define _I2C_LLD_H_ + +#if HAL_USE_I2C || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name TIMINGR register definitions + * @{ + */ +#define STM32_TIMINGR_PRESC_MASK (15U << 28) +#define STM32_TIMINGR_PRESC(n) ((n) << 28) +#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) +#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) +#define STM32_TIMINGR_SDADEL_MASK (15U << 16) +#define STM32_TIMINGR_SDADEL(n) ((n) << 16) +#define STM32_TIMINGR_SCLH_MASK (255U << 8) +#define STM32_TIMINGR_SCLH(n) ((n) << 8) +#define STM32_TIMINGR_SCLL_MASK (255U << 0) +#define STM32_TIMINGR_SCLL(n) ((n) << 0) +/** @} */ + + +/** + * Driver clears down tidily after a timeout + */ +#define I2C_SUPPORT_BUS_CLEAR TRUE + +/** + * @brief Invalid I2C bus address + */ +#define i2cInvalidAdr ((i2caddr_t) -1) + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @name Configuration options + * @{ + */ +/** + * @brief I2C1 driver enable switch. + * @details If set to @p TRUE the support for I2C1 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C1 FALSE +#endif + +/** + * @brief I2C2 driver enable switch. + * @details If set to @p TRUE the support for I2C2 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C2 FALSE +#endif + +/** + * @brief I2C3 driver enable switch. + * @details If set to @p TRUE the support for I2C3 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C3 FALSE +#endif + +/** + * @brief I2C4 driver enable switch. + * @details If set to @p TRUE the support for I2C4 is included. + * @note The default is @p FALSE. + */ +#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) +#define STM32_I2C_USE_I2C4 FALSE +#endif + + +/** + * @brief Enables support for I2C slave mode operation + */ +#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) +#define HAL_USE_I2C_SLAVE FALSE +#endif + + +/** + * @brief Turns on some debugging options + */ +#if !defined(STM32_I2C_DEBUG_ENABLE) || defined(__DOXYGEN__) +#define STM32_I2C_DEBUG_ENABLE FALSE +#endif + + +/** + * @brief I2C timeout on busy condition in milliseconds. + */ +#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) +#define STM32_I2C_BUSY_TIMEOUT 50 +#endif + +/** + * @brief I2C1 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C2 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C3 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_IRQ_PRIORITY 10 +#endif + +/** + * @brief I2C4 interrupt priority level setting. + */ +#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_IRQ_PRIORITY 10 +#endif + +/** + * @brief DMA use switch. + */ +#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) +#define STM32_I2C_USE_DMA TRUE +#endif + +/** + * @brief I2C1 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C1_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C2 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C2_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C3 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C3_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C4 DMA priority (0..3|lowest..highest). + * @note The priority level is used for both the TX and RX DMA streams but + * because of the streams ordering the RX stream has always priority + * over the TX stream. + */ +#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) +#define STM32_I2C_I2C4_DMA_PRIORITY 1 +#endif + +/** + * @brief I2C DMA error hook. + * @note The default action for DMA errors is a system halt because DMA + * error can only happen because programming errors. + */ +#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) +#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") +#endif +/** @} */ + + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +/** @brief error checks */ +#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 +#error "I2C1 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 +#error "I2C2 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 +#error "I2C3 not present in the selected device" +#endif + +#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 +#error "I2C4 not present in the selected device" +#endif + +#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ + !STM32_I2C_USE_I2C4 +#error "I2C driver activated but no I2C peripheral assigned" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) +#error "Invalid IRQ priority assigned to I2C4" +#endif + +#if STM32_I2C_USE_DMA == TRUE +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C1" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C2" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C3" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) +#error "Invalid DMA priority assigned to I2C4" +#endif + +/* The following checks are only required when there is a DMA able to + reassign streams to different channels.*/ +#if STM32_ADVANCED_DMA +/* Check on the presence of the DMA streams settings in mcuconf.h.*/ +#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) +#error "I2C1 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) +#error "I2C2 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C3_TX_DMA_STREAM)) +#error "I2C3 DMA streams not defined" +#endif + +#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \ + !defined(STM32_I2C_I2C4_TX_DMA_STREAM)) +#error "I2C4 DMA streams not defined" +#endif + +/* Check on the validity of the assigned DMA channels.*/ +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ + STM32_I2C1_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 RX" +#endif + +#if STM32_I2C_USE_I2C1 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ + STM32_I2C1_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C1 TX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ + STM32_I2C2_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 RX" +#endif + +#if STM32_I2C_USE_I2C2 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ + STM32_I2C2_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C2 TX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ + STM32_I2C3_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 RX" +#endif + +#if STM32_I2C_USE_I2C3 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ + STM32_I2C3_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C3 TX" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \ + STM32_I2C4_RX_DMA_MSK) +#error "invalid DMA stream associated to I2C4 RX" +#endif + +#if STM32_I2C_USE_I2C4 && \ + !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \ + STM32_I2C4_TX_DMA_MSK) +#error "invalid DMA stream associated to I2C4 TX" +#endif +#endif /* STM32_ADVANCED_DMA */ + +#if !defined(STM32_DMA_REQUIRED) +#define STM32_DMA_REQUIRED +#endif +#endif /* STM32_I2C_USE_DMA == TRUE */ + + + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Type representing an I2C address. + * @note For a 7-bit address, this takes values 0..0x7f, which are then + * shifted left one and the R/W bit added when required + */ +typedef uint16_t i2caddr_t; + +/** + * @brief Type of I2C driver condition flags. + */ +typedef uint32_t i2cflags_t; + + +/** + * @brief Type of a structure representing an I2C driver. + */ +typedef struct I2CDriver I2CDriver; + + +/** + * @brief Supported modes for the I2C bus. + * @note Currently not used; retained for future enhancements + */ +typedef enum { + OPMODE_I2C = 1, + OPMODE_SMBUS_DEVICE = 2, + OPMODE_SMBUS_HOST = 3, +} i2copmode_t; + + + +/** + * @brief Character received I2C notification callback type. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] c received character + * + * @param[out] Return 0 if transfer to continue. 1 if transfer to be stopped + * + * @note Use only in master mode, to stop a read transaction + * once a particular character (or sequence of characters) has been received + */ +typedef uint8_t (*i2cccb_t)(I2CDriver *i2cp, uint16_t c); + + + +/** + * @brief Type of I2C driver configuration structure. + */ +typedef struct { + /** + * @brief TIMINGR register initialization. + * @note Refer to the STM32 reference manual, the values are affected + * by the system clock settings in mcuconf.h. + */ + uint32_t timingr; + /** + * @brief CR1 register initialization. + * @note Leave to zero unless you know what you are doing. + */ + uint32_t cr1; + /** + * @brief CR2 register initialization. + * @note Leave at zero except in special circumstances - most bits controlled via API + */ + uint32_t cr2; + /** + * @brief Character received callback. Return 0 if transfer to continue. 1 if transfer to be stopped + * @note Use only in master mode. Set to NULL if not used. + */ + i2cccb_t rxchar_cb; +} I2CConfig; + + + + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +typedef struct I2CSlaveMsg I2CSlaveMsg; + +/* + returns the current I2C slave message receive configuration +*/ +I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp); + + +/* + returns the current I2C slave message reply configuration +*/ +I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp); + + +/* + I2C Slave Message Call Back. + Invoked from interrupt context just after + the last byte of the message is transferred or slaveAdr is matched. + + Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access + the relevant message handling configuration +*/ +typedef void I2CSlaveMsgCB(I2CDriver *i2cp); + + +/* + I2CSlaveMsg message handling configurations are normally + stored in read-only memory. + They describe either a buffer to contain incoming messages from + a bus master and associated callback functions, or one + preloaded with an outgoing reply to a read request and its callbacks. +*/ + +struct I2CSlaveMsg { + size_t size; /* sizeof(body) -- zero if master must wait */ + uint8_t *body; /* message contents -- or NULL if master must wait */ + I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */ + I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */ + I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */ +}; + + +/* + dummy callback -- placeholder to ignore event +*/ +I2CSlaveMsgCB I2CSlaveDummyCB; + + /* lock bus on receive or reply -- force master to wait */ +extern const I2CSlaveMsg I2CSlaveLockOnMsg; + +#endif /* HAL_USE_I2C_SLAVE */ + + + + +/** + * @brief Structure representing an I2C driver. + */ +struct I2CDriver { + /** + * @brief Driver state. + */ + i2cstate_t state; + /** + * @brief Current configuration data. + */ + const I2CConfig *config; + /** + * @brief Error flags. + */ + i2cflags_t errors; +#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) + mutex_t mutex; +#endif /* I2C_USE_MUTUAL_EXCLUSION */ +#if defined(I2C_DRIVER_EXT_FIELDS) + I2C_DRIVER_EXT_FIELDS +#endif + /* End of the mandatory fields.*/ + /** + * @brief Thread waiting for I/O completion. + */ + thread_reference_t thread; + + +#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) + /** + * @brief RX DMA mode bit mask. + */ + uint32_t rxdmamode; + /** + * @brief TX DMA mode bit mask. + */ + uint32_t txdmamode; + /** + * @brief Receive DMA channel. + */ + const stm32_dma_stream_t *dmarx; + /** + * @brief Transmit DMA channel. + */ + const stm32_dma_stream_t *dmatx; +#else /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the next TX buffer location. + */ + const uint8_t *txptr; + /** + * @brief Number of bytes in TX phase. + */ + size_t txbytes; +#endif /* STM32_I2C_USE_DMA == FALSE */ + /** + * @brief Pointer to the next RX buffer location. + */ + uint8_t *rxptr; + /** + * @brief Number of bytes in RX phase. + */ + size_t rxbytes; + /** + * @brief Pointer to the I2Cx registers block. + */ + I2C_TypeDef *i2c; + + + /** + * @brief low level I2C interface / protocol state + */ + enum i2cMode { + i2cStopped = 0, /* Port not initialised, or not started */ + i2cIdle=1, /* awaiting address or inactive */ + i2cSlaveRxing, /* receiving message */ + i2cLockedRxing, /* stretching clock before receiving message - Rx buffer might be full */ + i2cSlaveReplying, /* replying to query (transmitting, slave mode) */ + i2cLockedReplying, /* stretching clock before replying to query (no response available from main code) */ + + i2cIsMaster=0x11, /* sent start bit (mastering bus) */ + i2cMasterStarted, /* repeated start after write */ + i2cMasterSelecting, /* sending slave address */ + i2cMasterRxing, /* receiving reply from slave */ + i2cMasterTxing /* sending message to slave */ + } mode; + +#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE + /** + * @brief I2C transaction timer + * @note USed for slave mode, lock + */ + virtual_timer_t timer; +#endif +#if HAL_USE_I2C_LOCK + /** + * @brief I2C bus lock duration + */ + systime_t lockDuration; +#endif +#if HAL_USE_I2C_SLAVE + /* additional fields to support I2C slave transactions */ + + /** + * @brief slave address of message being processed + */ + i2caddr_t targetAdr; + /** + * @brief Error Mask for last slave message + */ + i2cflags_t slaveErrors; + /** + * @brief Length of most recently transferred slave message + */ + size_t slaveBytes; + /** + * @brief Maximum # of ticks slave may stretch the I2C clock + */ + systime_t slaveTimeout; + /** + * @brief Pointer to slave message reception handler + */ + const I2CSlaveMsg *slaveRx; + /** + * @brief Pointer to slave message Reply (transmit) handler + * + * @note This is the currently active/just completed reply + */ + const I2CSlaveMsg *slaveReply; + /** + * @brief Pointer to handler for next slave received message + */ + const I2CSlaveMsg *slaveNextRx; + /** + * @brief Pointer to handler for next slave reply (transmit) message + * + * @note This is used for a reply if no message received first + */ + const I2CSlaveMsg *slaveNextReply; +#endif +}; + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Get errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) + + + +#if HAL_USE_I2C_LOCK +/** + * @brief Unlock I2C bus after the end of the next transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + **/ +#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE) +#endif + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ +/** + * @brief Get slave errors from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors) + +/** + * @brief Get slave message bytes transferred from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes) + + +/** + * @brief Get slave timeout in ticks from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout) + +/** + * @brief Set slave timeout in ticks for I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks)) + +/** + * @brief Get slave target address from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr) + +/** + * @brief Get slave receive message descriptor from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx) + +/** + * @brief Get slave reply message descriptor from I2C driver. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply) + + +#endif + + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#if !defined(__DOXYGEN__) +#if STM32_I2C_USE_I2C1 +extern I2CDriver I2CD1; +#endif + +#if STM32_I2C_USE_I2C2 +extern I2CDriver I2CD2; +#endif + +#if STM32_I2C_USE_I2C3 +extern I2CDriver I2CD3; +#endif + +#if STM32_I2C_USE_I2C4 +extern I2CDriver I2CD4; +#endif + +#endif /* !defined(__DOXYGEN__) */ + +#ifdef __cplusplus +extern "C" { +#endif + void i2c_lld_init(void); + void i2c_lld_start(I2CDriver *i2cp); + void i2c_lld_stop(I2CDriver *i2cp); + msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + +#if HAL_USE_I2C_LOCK /* I2C slave mode support */ + void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration); +#endif +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + void i2c_lld_unmatchAll(I2CDriver *i2cp); + void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); + void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); + +#if STM32_I2C_DEBUG_ENABLE + void i2cPrintQ(BaseSequentialStream *chp); // Debugging routine +#endif /* STM32_I2C_DEBUG_ENABLE */ + +#endif /* HAL_USE_I2C_SLAVE */ + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C */ + +#endif /* _I2C_LLD_H_ */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2c.c b/drivers/chibios/i2cslave/hal_i2c.c new file mode 100644 index 0000000000..5e4e6438c2 --- /dev/null +++ b/drivers/chibios/i2cslave/hal_i2c.c @@ -0,0 +1,480 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file i2c.c + * @brief I2C Driver code. + * + * @addtogroup I2C + * @{ + */ +#include "hal.h" + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver local definitions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported variables. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local variables and types. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver local functions. */ +/*===========================================================================*/ + +/*===========================================================================*/ +/* Driver exported functions. */ +/*===========================================================================*/ + +/** + * @brief I2C Driver initialization. + * @note This function is implicitly invoked by @p halInit(), there is + * no need to explicitly initialize the driver. + * + * @init + */ +void i2cInit(void) { + + i2c_lld_init(); +} + +/** + * @brief Initializes the standard part of a @p I2CDriver structure. + * + * @param[out] i2cp pointer to the @p I2CDriver object + * + * @init + */ +void i2cObjectInit(I2CDriver *i2cp) { + + i2cp->state = I2C_STOP; + i2cp->config = NULL; + +#if I2C_USE_MUTUAL_EXCLUSION == TRUE +#if CH_CFG_USE_MUTEXES + osalMutexObjectInit(&i2cp->mutex); +#else + osalSemObjectInit(&i2cp->semaphore, 1); +#endif /* CH_CFG_USE_MUTEXES */ +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + +#if defined(I2C_DRIVER_EXT_INIT_HOOK) + I2C_DRIVER_EXT_INIT_HOOK(i2cp); +#endif +} + +/** + * @brief Configures and activates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] config pointer to the @p I2CConfig object + * + * @api + */ +void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { + + osalDbgCheck((i2cp != NULL) && (config != NULL)); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2cp->config = config; + i2c_lld_start(i2cp); + i2cp->state = I2C_READY; + osalSysUnlock(); +} + +/** + * @brief Deactivates the I2C peripheral. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cStop(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || + (i2cp->state == I2C_LOCKED), "invalid state"); + + osalSysLock(); + i2c_lld_stop(i2cp); + i2cp->state = I2C_STOP; + osalSysUnlock(); +} + +/** + * @brief Returns the errors mask associated to the previous operation. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @return The errors mask. + * + * @api + */ +i2cflags_t i2cGetErrors(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + + return i2c_lld_get_errors(i2cp); +} + +/** + * @brief Sends data via the I2C bus. + * @details Function designed to realize "read-through-write" transfer + * paradigm. If you want transmit data without any further read, + * than set @b rxbytes field to 0. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address (7 bits) without R/W bit + * @param[in] txbuf pointer to transmit buffer + * @param[in] txbytes number of bytes to be transmitted + * @param[out] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received, set it to 0 if + * you want transmit only + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, + i2caddr_t addr, + const uint8_t *txbuf, + size_t txbytes, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout) { + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0U) && + (txbytes > 0U) && (txbuf != NULL) && + ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_TX; + rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, + rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + osalSysUnlock(); + return rdymsg; +} + +/** + * @brief Receives data from the I2C bus. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] addr slave device address (7 bits) without R/W bit + * @param[out] rxbuf pointer to receive buffer + * @param[in] rxbytes number of bytes to be received + * @param[in] timeout the number of ticks before the operation timeouts, + * the following special values are allowed: + * - @a TIME_INFINITE no timeout. + * . + * + * @return The operation status. + * @retval MSG_OK if the function succeeded. + * @retval MSG_RESET if one or more I2C errors occurred, the errors can + * be retrieved using @p i2cGetErrors(). + * @retval MSG_TIMEOUT if a timeout occurred before operation end. + * + * @api + */ +msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, + i2caddr_t addr, + uint8_t *rxbuf, + size_t rxbytes, + systime_t timeout){ + + msg_t rdymsg; + + osalDbgCheck((i2cp != NULL) && (addr != 0U) && + (rxbytes > 0U) && (rxbuf != NULL) && + (timeout != TIME_IMMEDIATE)); + + osalDbgAssert(i2cp->state == I2C_READY, "not ready"); + + osalSysLock(); + i2cp->errors = I2C_NO_ERROR; + i2cp->state = I2C_ACTIVE_RX; + rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); + if (rdymsg == MSG_TIMEOUT) { + i2cp->state = I2C_LOCKED; + } + else { + i2cp->state = I2C_READY; + } + osalSysUnlock(); + return rdymsg; +} + + +#if HAL_USE_I2C_LOCK /* I2C slave mode support */ + +/** + * @brief Lock I2C bus at the beginning of the next message sent + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] lockDuration max number of ticks to hold bus locked + * - @a TIME_INFINITE no timeout. + * - @a TIME_IMMEDIATE unlock the bus immediately + * . + * + * @api + */ +void i2cLock(I2CDriver *i2cp, systime_t lockDuration) +{ + chDbgCheck((i2cp != NULL), "i2cLock"); + chSysLock(); + i2c_lld_lock(i2cp, lockDuration); + chSysUnlock(); +} + +/** + * @brief Unlock I2C bus after the end of the next transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + **/ +void i2cUnlock(I2CDriver *i2cp) +{ + chDbgCheck((i2cp != NULL), "i2cUnlock"); + chSysLock(); + i2c_lld_unlock(i2cp); + chSysUnlock(); +} +#endif + + +#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ + +/** + * @brief Reconfigure I2C channel to respond to indicated address + * in addition to those already matched + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C network address + * + * @return Length of message OR the type of event received + * @retval I2C_OK Success + * @retval I2C_ERROR Cannot match address in addition of those already + * + * @details MatchAddress calls are cumulative. + * Specify address zero to match I2C "all call" + * Does not support 10-bit addressing. + * + * @api + **/ +msg_t i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + osalDbgCheck((i2cp != NULL)); + chSysLock(); + msg_t result = i2c_lld_matchAddress(i2cp, i2cadr); + chSysUnlock(); + return result; +} + + +/** + * @brief Configure to ignore messages directed to the given i2cadr + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C bus address + * - @a 0 matches "all call" + * . + * @details A message being transferred that has already matched the + * specified address will continue being processed. + * Requests to unmatch an address that is not currently being matched + * are ignored. + * + * @api + */ +void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + osalDbgCheck((i2cp != NULL)); + chSysLock(); + i2c_lld_unmatchAddress(i2cp, i2cadr); + chSysUnlock(); +} + + +/** + * @brief Reconfigure I2C channel to no longer match any address + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details Causes all subsequent messages to be ignored. + * A message being transferred that has already matched a + * slave address will continue being processed. + * + * @api + **/ +void i2cUnmatchAll(I2CDriver *i2cp) +{ + osalDbgCheck((i2cp != NULL)); + chSysLock(); + i2c_lld_unmatchAll(i2cp); + chSysUnlock(); +} + + +/** + * @brief Configure callbacks & buffers for message reception & query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Must be called from a thread + * Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveConfigure(I2CDriver *i2cp, + const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg) +{ + osalDbgCheck((i2cp != NULL)); + chSysLock(); + i2c_lld_slaveReceive(i2cp, rxMsg); + i2c_lld_slaveReply(i2cp, replyMsg); + chSysUnlock(); +} + + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) +{ + osalDbgCheck((i2cp != NULL && rxMsg != NULL)); + chSysLock(); + i2c_lld_slaveReceive(i2cp, rxMsg); + chSysUnlock(); +} + + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) +{ + osalDbgCheck((i2cp != NULL && replyMsg != NULL)); + chSysLock(); + i2c_lld_slaveReply(i2cp, replyMsg); + chSysUnlock(); +} + +#endif /* HAL_USE_I2C_SLAVE */ + + +#if I2C_USE_MUTUAL_EXCLUSION == TRUE || defined(__DOXYGEN__) +/** + * @brief Gains exclusive access to the I2C bus. + * @details This function tries to gain ownership to the I2C bus, if the bus + * is already being used then the invoking thread is queued. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cAcquireBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + +#if CH_CFG_USE_MUTEXES + osalMutexLock(&i2cp->mutex); +#elif CH_CFG_USE_SEMAPHORES + osalSemWait(&i2cp->semaphore); +#endif /* CH_CFG_USE_MUTEXES */ +} + + +/** + * @brief Releases exclusive access to the I2C bus. + * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION + * must be enabled. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @api + */ +void i2cReleaseBus(I2CDriver *i2cp) { + + osalDbgCheck(i2cp != NULL); + +#if CH_CFG_USE_MUTEXES + osalMutexUnlock(&i2cp->mutex); +#elif CH_CFG_USE_SEMAPHORES + osalSemSignal(&i2cp->semaphore); +#endif /* CH_CFG_USE_MUTEXES */ +} + +#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */ + +#endif /* HAL_USE_I2C == TRUE */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2c.h b/drivers/chibios/i2cslave/hal_i2c.h new file mode 100644 index 0000000000..325941b953 --- /dev/null +++ b/drivers/chibios/i2cslave/hal_i2c.h @@ -0,0 +1,212 @@ +/* + ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +*/ +/* + Concepts and parts of this file have been contributed by Uladzimir Pylinsky + aka barthess. + */ + +/** + * @file i2c.h + * @brief I2C Driver macros and structures. + * + * @addtogroup I2C + * @{ + */ + +#ifndef _I2C_H_ +#define _I2C_H_ + +#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) + +/*===========================================================================*/ +/* Driver constants. */ +/*===========================================================================*/ + +/** + * @name I2C bus error conditions + * @{ + */ +#define I2C_NO_ERROR 0x00 /**< @brief No error. */ +#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */ +#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */ +#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */ +#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */ +#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in + reception. */ +#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */ +#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */ +#define I2C_UNKNOWN_ERROR 0x80 /**< @brief internal error (base value - current mode value added) */ + +#define I2C_STOPPED ((i2cflags_t)(-1)) + /**< @brief stop condition or i2cStop() called */ +/** @} */ + +/** + * @name I2C function return codes + * @{ + */ +#define I2C_OK (MSG_OK) +#define I2C_ERR_TIMEOUT (MSG_TIMEOUT) +#define I2C_ERROR (MSG_RESET) +/** @} */ + + +/*===========================================================================*/ +/* Driver pre-compile time settings. */ +/*===========================================================================*/ + +/** + * @brief Enables the mutual exclusion APIs on the I2C bus. + */ +#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) +#define I2C_USE_MUTUAL_EXCLUSION TRUE +#endif + +/** + * @brief Enables 'lock' capability needed in I2C slave mode + */ +#if !defined(HAL_USE_I2C_LOCK) || defined(__DOXYGEN__) +#define HAL_USE_I2C_LOCK FALSE +#endif + +/** + * @brief Determines whether master mode required to be supported + */ + #if !defined(HAL_USE_I2C_MASTER) || defined(__DOXYGEN__) + #define HAL_USE_I2C_MASTER TRUE + #endif + +/** + * @brief Determines whether slave mode required to be supported + */ + #if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) + #define HAL_USE_I2C_SLAVE FALSE + #endif + +/*===========================================================================*/ +/* Derived constants and error checks. */ +/*===========================================================================*/ + +#if I2C_USE_MUTUAL_EXCLUSION && !CH_CFG_USE_MUTEXES && !CH_CFG_USE_SEMAPHORES +#error "I2C_USE_MUTUAL_EXCLUSION requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" +#endif + +/*===========================================================================*/ +/* Driver data structures and types. */ +/*===========================================================================*/ + +/** + * @brief Driver state machine possible states. + */ +typedef enum { + I2C_UNINIT = 0, /**< Not initialized. */ + I2C_STOP = 1, /**< Stopped. */ + I2C_READY = 2, /**< Ready. */ + I2C_ACTIVE_TX = 3, /**< Transmitting. */ + I2C_ACTIVE_RX = 4, /**< Receiving. */ + I2C_LOCKED = 5 /**> Bus or driver locked. */ +} i2cstate_t; + +#include "hal_i2c_lld.h" + +/*===========================================================================*/ +/* Driver macros. */ +/*===========================================================================*/ + +/** + * @brief Wakes up the waiting thread notifying no errors. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wakeup_isr(i2cp) do { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(i2cp)->thread, MSG_OK); \ + osalSysUnlockFromISR(); \ +} while(0) + +/** + * @brief Wakes up the waiting thread notifying errors. + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @notapi + */ +#define _i2c_wakeup_error_isr(i2cp) do { \ + osalSysLockFromISR(); \ + osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \ + osalSysUnlockFromISR(); \ +} while(0) + +/** + * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout. + * @api + */ +#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \ + (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \ + TIME_INFINITE)) + +/** + * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout. + * @api + */ +#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \ + (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE)) + + +/*===========================================================================*/ +/* External declarations. */ +/*===========================================================================*/ + +#ifdef __cplusplus +extern "C" { +#endif + void i2cInit(void); + void i2cObjectInit(I2CDriver *i2cp); + void i2cStart(I2CDriver *i2cp, const I2CConfig *config); + void i2cStop(I2CDriver *i2cp); + i2cflags_t i2cGetErrors(I2CDriver *i2cp); + msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, + i2caddr_t addr, + const uint8_t *txbuf, size_t txbytes, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, + i2caddr_t addr, + uint8_t *rxbuf, size_t rxbytes, + systime_t timeout); + +#if HAL_USE_I2C_LOCK /* I2C slave mode support */ + void i2cLock(I2CDriver *i2cp, systime_t lockDuration); + void i2cUnlock(I2CDriver *i2cp); +#endif + +#if I2C_USE_MUTUAL_EXCLUSION == TRUE + void i2cAcquireBus(I2CDriver *i2cp); + void i2cReleaseBus(I2CDriver *i2cp); +#endif /* I2C_USE_MUTUAL_EXCLUSION */ + + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C == TRUE */ + +#endif /* _I2C_H_ */ + +/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2cslave.h b/drivers/chibios/i2cslave/hal_i2cslave.h new file mode 100644 index 0000000000..955b41e25c --- /dev/null +++ b/drivers/chibios/i2cslave/hal_i2cslave.h @@ -0,0 +1,423 @@ +/* + ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, + 2011,2012,2013 Giovanni Di Sirio. + + This file is part of ChibiOS/RT. + + ChibiOS/RT is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + ChibiOS/RT is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + + --- + + A special exception to the GPL can be applied should you wish to distribute + a combined work that includes ChibiOS/RT, without being obliged to provide + the source code for any proprietary components. See the file exception.txt + for full details of how and when the exception can be applied. +*/ +/* + Slave I2C support contributed by Brent Roman of the + Monterey Bay Aquarium Research Institute + */ + +/** + * @file i2cslave.h + * @brief Slave Mode for the I2C Driver. + * + * @addtogroup I2C + * @{ + */ +#ifndef _I2CSLAVE_H_ +#define _I2CSLAVE_H_ + +#if HAL_USE_I2C_SLAVE || defined(__DOXYGEN__) + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * @brief Configure to respond to messages directed to the given i2cadr + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C bus address + * - @a 0 matches "all call" + * . + * @return Length of message OR the type of event received + * @retval I2C_OK Success + * @retval I2C_ERROR Cannot match address in addition of those already + * + * @details MatchAddress calls are cumulative. + * Specify address zero to match I2C "all call" + * Most hardware supports matching only a signle nonzero address. + * + * @api + */ +int i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + + +/** + * @brief Configure to ignore messages directed to the given i2cadr + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C bus address + * - @a 0 matches "all call" + * . + * @details A message being transferred that has already matched the + * specified address will continue being processed. + * Requests to unmatch an address that is not currently being matched + * are ignored. + * + * @api + */ +void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); + + +/** + * @brief Configure to ignore all messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details A message being transferred that has already matched the + * specified address will continue being processed. + * + * @api + */ +void i2cUnmatchAll(I2CDriver *i2cp); + + +/** + * @brief Configure to respond to messages directed to the given i2cadr + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C bus address + * - @a 0 matches "all call" + * . + * @return non-zero implies failure. + * + * @details Identical to i2cMatchAddress(), but called from interrupt context + * + * @api + */ +static inline msg_t + i2cMatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_matchAddress(i2cp, i2cadr); +} + + +/** + * @brief Configure to ignore messages directed to the given i2cadr + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] i2cadr I2C bus address + * - @a 0 matches "all call" + * . + * @details Identical to i2cUnmatchAddress(), but called from interrupt context + * + * @api + */ +static inline void + i2cUnmatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr) +{ + osalDbgCheck(i2cp != NULL); + i2c_lld_unmatchAddress(i2cp, i2cadr); +} + + +/** + * @brief Configure to ignore all messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @details Identical to i2cUnmatchAll(), but called from interrupt context + * + * @api + */ +static inline void + i2cUnmatchAllI(I2CDriver *i2cp) +/* + Notes: + Must be called from interrupt context + Does not affect the processing of any message currently being received +*/ +{ + osalDbgCheck(i2cp != NULL); + i2c_lld_unmatchAll(i2cp); +} + + +/* I2C Bus activity timeout configuration */ + +/** + * @brief return maximum number of ticks a slave bus transaction may last + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @return maximum number of ticks a slave bus transaction my last + * + * @details initialized to TIME_INFINITE (disabling slave mode bus timeouts) + * + * @api + */ +static inline + systime_t i2cSlaveTimeout(I2CDriver *i2cp) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveTimeout(i2cp); +} + + +/** + * @brief set the maximum number of ticks a slave bus transaction may last + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] ticks maximum number of ticks a slave bus transaction my last + * - @a TIME_INFINITE disables slave mode bus timeouts + * - @a TIME_IMMEDIATE is invalid + * . + * + * @api + */ +static inline + void i2cSlaveSetTimeout(I2CDriver *i2cp, systime_t ticks) +{ + osalDbgCheck(i2cp != NULL && ticks != TIME_IMMEDIATE); + i2c_lld_set_slaveTimeout(i2cp, ticks); +} + + +/* bus transaction attributes */ + +/** + * @brief return bit mask of errors associated with this slave transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @return I2C bus error conditions described in i2c.h + * + * @api + */ +static inline + i2cflags_t i2cSlaveErrors(I2CDriver *i2cp) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveErrors(i2cp); +} + +/** + * @brief return number of bytes transferred during this slave transaction + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @return number of bytes actually transferred on the bus + * + * @api + */ +static inline + size_t i2cSlaveBytes(I2CDriver *i2cp) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveBytes(i2cp); +} + +/** + * @brief return i2c address to which this message was targetted + * + * @param[in] i2cp pointer to the @p I2CDriver object + * + * @return i2c address to which this message was targetted + * + * @details The address returns will be one of those + * specified earlier as an argument to i2cMatchAddress() + * + * @api + */ +static inline + i2caddr_t i2cSlaveTargetAdr(I2CDriver *i2cp) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveTargetAdr(i2cp); +} + + +/* + An event service thread based API library called i2cevent supports processing + slave messages on a dedicated thread. This facility is built upon the + low-level driver's asynchronous callback functions described below: + + Each callback function may alter the processing of subsequent I2C + messages and read requests by calling i2cSlaveReceive() and + i2cSlaveReply(), respectively. Further, callbacks may alter their + i2cSlaveMsg structs in RAM, but only those for their own channel. + Such changes take immediate affect. This facility can be used to + avoid copying message buffers. + + If receive buffers become full or a reply to a read request cannot be + generated immediately, the relevant I2CSlaveMsg struct may be substituted + for another whose body pointer is NULL or whose body size is zero. + Note that, I2CSlaveMsg structs may be modified + in place within a channel's callbacks to the same effect. + + A NULL body pointer or zero size causes the slave to signal the master node + to wait by holding the I2C clock signal low, "stretching it", during the next + transaction to which that I2CSlaveMsg applies. + The I2C clock resumes only after a i2cSlaveSetReceive() or SetReply() is + called with an I2CSlaveMsg containing a non-NULL body, + or after the transaction timeout expires. + + Therefore, if a NULL body pointer is replaced with a non-NULL one or + a zero length is replaced with a non-zero one, i2cSlaveReceive() or + i2cSlaveReply() MUST be called -- even if with the same pointer values -- + to inform the i2c driver that the transaction may resume. + + Note that Receive and Reply processing is initially "locked". +*/ + +/** + * @brief Configure callbacks & buffers for message reception & query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Must be called from a thread + * Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveConfigure(I2CDriver *i2cp, + const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg); + + +/** + * @brief Configure callbacks & buffers for message reception + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Must be called from a thread + * Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); + +/** + * @brief return @p I2CSlaveMsg for processing received messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @returns @p I2CSlaveMsg struct for processing subsequent messages + * + * @api + */ +static inline + const I2CSlaveMsg *i2cSlaveReceiveMsg(I2CDriver *i2cp) +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveReceive(i2cp); +} + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries + * + * @details Must be called from a thread + * Call i2cMatchAddress() after this to start processing + * Enabling match addresses before installing handler callbacks can + * result in locking the I2C bus when a master accesses those + * unconfigured slave addresses + * + * @api + */ +void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); + + +/** + * @brief return @p I2CSlaveMsg for processing received messages + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @returns @p I2CSlaveMsg struct for processing subsequent messages + * + * @api + */ +static inline + const I2CSlaveMsg *i2cSlaveReplyMsg(I2CDriver *i2cp) +/* + processing descriptor for the next reply message +*/ +{ + osalDbgCheck(i2cp != NULL); + return i2c_lld_get_slaveReply(i2cp); +} + +/** + * @brief Configure callbacks & buffers for message reception + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages + * + * @details Must be called from an interrupt context + * + * @api + */ +static inline void + i2cSlaveReceiveI(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) +{ + osalDbgCheck(i2cp != NULL && rxMsg != NULL); + i2c_lld_slaveReceive(i2cp, rxMsg); +} + +/** + * @brief Configure callbacks & buffers for query reply + * + * @param[in] i2cp pointer to the @p I2CDriver object + * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent messages + * + * @details Must be called from an interrupt context + * + * @api + */ +static inline void + i2cSlaveReplyI(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) +/* + Prepare to reply to I2C read requests from bus masters + according to the replyMsg configuration. + + Notes: + Must be called from interrupt context + Does not affect the processing of any message reply being sent +*/ +{ + osalDbgCheck(i2cp != NULL && replyMsg != NULL); + i2c_lld_slaveReply(i2cp, replyMsg); +} + +#ifdef __cplusplus +} +#endif + +#endif /* HAL_USE_I2C_SLAVE */ + +#endif /* _I2CSLAVE_H_ */ From 58c4ba096a8c7c9c7b452375cce6ce97c1bdda3c Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 7 Jun 2018 18:46:35 -0400 Subject: [PATCH 45/59] update chibios --- lib/chibios | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/chibios b/lib/chibios index 587968d6cb..84a65901f0 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit 587968d6cbc2b0e1c7147540872f2a67e59ca18b +Subproject commit 84a65901f0d4784f10210637478c769e0ee6c415 From 5bb1e7869c3c5461c9c789d7e59b31c98bd20420 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 7 Jun 2018 19:00:10 -0400 Subject: [PATCH 46/59] update chibios, remove extra files --- drivers/chibios/i2cslave/I2Cv1/driver.mk | 21 - drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c | 1745 --------------- drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h | 777 ------- drivers/chibios/i2cslave/I2Cv2/driver.mk | 21 - drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c | 2065 ------------------ drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h | 806 ------- drivers/chibios/i2cslave/hal_i2c.c | 480 ---- drivers/chibios/i2cslave/hal_i2c.h | 212 -- drivers/chibios/i2cslave/hal_i2cslave.h | 423 ---- lib/chibios | 2 +- 10 files changed, 1 insertion(+), 6551 deletions(-) delete mode 100644 drivers/chibios/i2cslave/I2Cv1/driver.mk delete mode 100644 drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c delete mode 100644 drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h delete mode 100644 drivers/chibios/i2cslave/I2Cv2/driver.mk delete mode 100644 drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c delete mode 100644 drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h delete mode 100644 drivers/chibios/i2cslave/hal_i2c.c delete mode 100644 drivers/chibios/i2cslave/hal_i2c.h delete mode 100644 drivers/chibios/i2cslave/hal_i2cslave.h diff --git a/drivers/chibios/i2cslave/I2Cv1/driver.mk b/drivers/chibios/i2cslave/I2Cv1/driver.mk deleted file mode 100644 index f8cca018e9..0000000000 --- a/drivers/chibios/i2cslave/I2Cv1/driver.mk +++ /dev/null @@ -1,21 +0,0 @@ -ifeq ($(USE_HAL_I2C_FALLBACK),yes) - # Fallback SW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C -else - # Default HW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv1 -endif diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c deleted file mode 100644 index e62e6db1f3..0000000000 --- a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.c +++ /dev/null @@ -1,1745 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - - I2C Slave mode support added by Brent Roman (brent@mbari.org) - Ported to ChibiOs V3 by steved - Latest updates from original code applied 18.12.15 - - Note that all I2C registers are 16-bit (not 32-bit, as on the later devices in the series) - */ - -/** - * @file STM32/I2Cv1/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -// Some master code has been brought in line with V3 - set next define to zero to stick with original code -#define USE_OLD_MASTER_STARTUP 0 - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -#define I2C3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_CHN) - -#define I2C3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_CHN) - -/*===========================================================================*/ -/* Driver constants -- see ST document RM0038 figure 208 */ -/*===========================================================================*/ -#define I2C_EV5_MASTER_MODE_SELECT \ - (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_SB) - -#define I2C_EV6_MASTER_TRA_MODE_SELECTED \ - (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_ADDR) - -#define I2C_EV6_MASTER_REC_MODE_SELECTED \ - (((uint32_t)I2C_SR2_MSL << 16) | I2C_SR1_ADDR) - -#define I2C_EV8_2_MASTER_BYTE_TRANSMITTED \ - (((uint32_t)(I2C_SR2_MSL | I2C_SR2_TRA) << 16) | I2C_SR1_BTF) - -#define I2C_EV9_MASTER_ADD10 \ - ((uint32_t)(((I2C_SR2_MSL | I2C_SR2_BUSY) << 16) | I2C_SR1_ADD10)) - -#if HAL_USE_I2C_SLAVE -#define I2C_EV1_SLAVE_RXADRMATCH \ - ((uint32_t)I2C_SR1_ADDR) - -#define I2C_EV1_SLAVE_TXADRMATCH \ - (((uint32_t)I2C_SR2_TRA << 16) | I2C_SR1_ADDR) - -#define I2C_EV2_SLAVE_RXSTOP \ - (I2C_SR1_STOPF) -#endif - -#define I2C_EV_MASK ( \ - ((uint32_t)(I2C_SR2_MSL|I2C_SR2_TRA)<<16) | \ - (I2C_SR1_SB|I2C_SR1_ADDR|I2C_SR1_STOPF|I2C_SR1_BTF)) - -#define I2C_ERROR_MASK \ - ((uint16_t)(I2C_SR1_BERR | I2C_SR1_ARLO | I2C_SR1_AF | I2C_SR1_OVR | \ - I2C_SR1_PECERR | I2C_SR1_TIMEOUT | I2C_SR1_SMBALERT)) - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/* quick and dirty queue to record event interrupts */ -#define QEVENTS 32 -#if QEVENTS > 0 -typedef struct i2cQ_t { - uint8_t code; - uint8_t state; - uint16_t param; -} i2cQ_t; -i2cQ_t i2cQ[QEVENTS]; -unsigned i2cI = QEVENTS; -#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \ - i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->mode); i2cQ[i2cI].param=(info); } -#else -#define qEvt(posn,info) -#endif - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -void I2CSlaveDummyCB(I2CDriver *i2cp) -/* - dummy callback -- placeholder to ignore event -*/ -{(void)i2cp;} - - /* lock bus on receive or reply message */ -const I2CSlaveMsg I2CSlaveLockOnMsg = { - 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB -}; - -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/** - * @brief Resets and disables the I2C channel - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2cReset(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - /* reset the I2C registers.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - dp->CR2 = 0; - dp->SR1 = 0; - - /* Stop the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -} - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2cAbortOperation(I2CDriver *i2cp) { - /* save control registers */ - I2C_TypeDef *dp = i2cp->i2c; - uint16_t cr2 = dp->CR2, cr1 = dp->CR1; -#if HAL_USE_I2C_SLAVE - uint16_t oar1 = dp->OAR1, oar2 = dp->OAR2; -#endif - uint16_t ccr = dp->CCR, trise = dp->TRISE; - - /* reset the I2C channel */ - i2cReset(i2cp); - - /* restore control registers */ - dp->TRISE = trise; dp->CCR = ccr; -#if HAL_USE_I2C_SLAVE - /* restore address mataching */ - dp->OAR1 = oar1; dp->OAR2 = oar2; -#endif - - /* Enable interrrupts */ - dp->CR2 = (cr2 & 0x3F) | I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN; - - /* Finish restoring and enable pheripheral */ - dp->CR1 = I2C_CR1_ACK | I2C_CR1_PE | (cr1 & (I2C_CR1_SMBUS | I2C_CR1_SMBTYPE)) -#if HAL_USE_I2C_SLAVE - | (cr1 & I2C_CR1_ENGC) -#endif - ; -} - - -#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK -/** - * @brief stop transaction timeout countdown - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static inline void stopTimer(I2CDriver *i2cp) -{ - osalSysLockFromISR(); - chVTResetI(&i2cp->timer); - osalSysUnlockFromISR(); -} -#else -#define stopTimer(ignored) {} -#endif - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -/** - * @brief return the address matched - * - * @param[in] dp pointer to the @p I2C registers object - * @param[in] sr2 I2C SR2 register contents - * - * @notapi - * Only supports 7-bit addressing for now - */ -static inline i2caddr_t matchedAdr(I2C_TypeDef *dp, uint32_t sr2) { - if (sr2 & I2C_SR2_GENCALL) - return 0; - if (sr2 & I2C_SR2_DUALF) - return (dp->OAR2>>1) & 0x7f; - return (dp->OAR1>>1) & 0x7f; -} - - -/** - * @brief report error via slave exception callback - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @note moves back to the idle mode - * @notapi - */ -static inline void reportSlaveError(I2CDriver *i2cp) { -#if HAL_USE_I2C_STARTFIX - i2cp->config->disarmStartDetect(); -#endif - { - const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ? - i2cp->slaveReply : i2cp->slaveRx; - if (xfer->exception) - xfer->exception(i2cp); /* in this case, i2cp->slaveErrors == 0 */ - } - i2cp->mode = i2cIdle; - i2cp->targetAdr = i2cInvalidAdr; -} - - -/** - * @brief Handling of stalled slave mode I2C transactions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void slaveTimeExpired(void *i2cv) { - I2CDriver *i2cp = i2cv; - - if (i2cp->mode < i2cIsMaster) - { - i2cAbortOperation(i2cp); - reportSlaveError(i2cp); - } -} - - -/** - * @brief start or restart slave mode transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static inline void startSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr) -{ - stopTimer(i2cp); - i2cp->targetAdr = targetAdr; - i2cp->slaveBytes = 0; - i2cp->slaveErrors = 0; - if (i2cp->slaveTimeout != TIME_INFINITE) - { - osalSysLockFromISR(); - chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp); - osalSysUnlockFromISR(); - } -} - -/** - * @brief end slave receive message DMA - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static inline void endSlaveRxDMA(I2CDriver *i2cp) -{ - size_t bytesRemaining = dmaStreamGetTransactionSize(i2cp->dmarx); - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff - bytesRemaining; - else - i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining; - dmaStreamDisable(i2cp->dmarx); -} - -/** - * @brief end slave transmit DMA - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] bytesRemaining bytes lost in output queue - * - * @notapi - */ -static inline void endSlaveReplyDMA(I2CDriver *i2cp, size_t bytesRemaining) -{ - bytesRemaining += dmaStreamGetTransactionSize(i2cp->dmatx); - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff - bytesRemaining; - else - i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining; - dmaStreamDisable(i2cp->dmatx); -} - -#endif - - -/** - * @brief Wakes up a waiting thread. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] msg wakeup message - * - * @notapi - */ -static inline void wakeup_isr(I2CDriver *i2cp, msg_t msg) -{ - do { - osalSysLockFromISR(); - osalThreadResumeI(&(i2cp)->thread, msg); - osalSysUnlockFromISR(); - } while(0); - -#if 0 - chSysLockFromISR(); - thread_t *tp = i2cp->thread; - if (tp != NULL) { - i2cp->thread = NULL; - tp->p_u.rdymsg = msg; - chSchReadyI(tp); - } - chSysUnlockFromISR(); -#endif -} - - -/** - * @brief Set clock speed. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_clock(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint16_t regCCR, clock_div; - int32_t clock_speed = i2cp->config->clock_speed; - i2cdutycycle_t duty = i2cp->config->duty_cycle; - - osalDbgCheck((i2cp != NULL) && - (clock_speed > 0) && - (clock_speed <= 4000000)); - - /* CR2 Configuration.*/ - dp->CR2 &= (uint16_t)~I2C_CR2_FREQ; - dp->CR2 |= (uint16_t)I2C_CLK_FREQ; - - /* CCR Configuration.*/ - regCCR = 0; - clock_div = I2C_CCR_CCR; - - switch (duty) { - case STD_DUTY_CYCLE: - /* Standard mode clock_div calculate: Tlow/Thigh = 1/1.*/ -#ifndef STM32_I2C_LOOSE_CLK - /* Configure clock_div in standard mode.*/ - osalDbgAssert(clock_speed <= 100000, - "#1 - STD_DUTY_CYCLE limited to 100khz"); - osalDbgAssert(STM32_PCLK1 % (clock_speed * 2) == 0, - "#2 - PCLK1 not divisible by 2*I2Cclk"); -#endif - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 2)); - - - osalDbgAssert(clock_div >= 0x04, - "clock divider less then 0x04 not allowed"); - regCCR |= (clock_div & I2C_CCR_CCR); - - /* Sets the Maximum Rise Time for standard mode.*/ - dp->TRISE = (uint16_t)(I2C_CLK_FREQ + 1); - break; - - case FAST_DUTY_CYCLE_2: - case FAST_DUTY_CYCLE_16_9: - /* Configure clock_div in fast mode.*/ -#ifndef STM32_I2C_LOOSE_CLK - osalDbgAssert(clock_speed > 100000 && clock_speed <= 400000, - "#4 - I2Cclk out of range for FAST_DUTY_CYCLE"); -#endif - if (duty == FAST_DUTY_CYCLE_2) { - /* Fast mode clock_div calculate: Tlow/Thigh = 2/1.*/ -#ifndef STM32_I2C_LOOSE_CLK - osalDbgAssert((STM32_PCLK1 % (clock_speed * 3)) == 0, - "#6 - PCLK1 not divisible by 3*I2Cclk"); -#endif - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 3)); - }else{ /* FAST_DUTY_CYCLE_16_9 */ - /* Fast mode clock_div calculate: Tlow/Thigh = 16/9.*/ -#ifndef STM32_I2C_LOOSE_CLK - osalDbgAssert(STM32_PCLK1 % (clock_speed * 25) == 0, - "#7 - PCLK1 not divisible by 25*I2Cclk"); -#endif - clock_div = (uint16_t)(STM32_PCLK1 / (clock_speed * 25)); - regCCR |= I2C_CCR_DUTY; - } - - osalDbgAssert(clock_div >= 0x01, - "clock divider less then 0x04 not allowed"); - regCCR |= (I2C_CCR_FS | (clock_div & I2C_CCR_CCR)); - - /* Sets the Maximum Rise Time for fast mode.*/ - dp->TRISE = (uint16_t)((I2C_CLK_FREQ * 300 / 1000) + 1); - break; - - default: - osalSysHalt("Invalid I2C duty_cycle"); - } - - osalDbgAssert((clock_div <= I2C_CCR_CCR), "the selected clock is too low"); - - dp->CCR = (uint16_t)regCCR; -} - - -/** - * @brief Set operation mode of I2C hardware. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_set_opmode(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - i2copmode_t opmode = i2cp->config->op_mode; - uint16_t regCR1; - - regCR1 = dp->CR1; - switch (opmode) { - case OPMODE_I2C: - regCR1 &= (uint16_t)~(I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_DEVICE: - regCR1 |= I2C_CR1_SMBUS; - regCR1 &= (uint16_t)~(I2C_CR1_SMBTYPE); - break; - case OPMODE_SMBUS_HOST: - regCR1 |= (I2C_CR1_SMBUS|I2C_CR1_SMBTYPE); - } - dp->CR1 = (uint16_t)regCR1; -} - - - -#if USE_OLD_MASTER_STARTUP -/** - * @brief Handling of stalled master mode I2C transactions. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_safety_timeout(void *p) { - I2CDriver *i2cp = p; - - stopTimer(i2cp); -#if HAL_USE_I2C_SLAVE /* abort any slave operation in progress */ - if (!(i2cp->i2c->SR2 & I2C_SR2_MSL)) - slaveTimeExpired(i2cp); /* in case slave preventing master bus access */ - else -#endif - { - i2cAbortOperation(i2cp); - i2cp->mode = i2cIdle; - } - wakeup_isr(i2cp, I2C_ERR_TIMEOUT); -} -#endif - - -#if HAL_USE_I2C_LOCK /* I2C bus locking support */ - -/** - * @brief Handling of expired master bus lock timer - * - * @param[in] i2cv pointer to the @p I2CDriver object - * - * @notapi - */ -static void lockExpired(void *i2cv) { - I2CDriver *i2cp = i2cv; - - if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */ - i2cp->i2c->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); - i2cp->mode = i2cIdle; - } - i2cp->lockDuration = TIME_IMMEDIATE; -} - - -/** - * @brief Lock I2C bus at the beginning of the next message - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] lockDuration max number of ticks to hold bus locked - * - @a TIME_INFINITE no timeout. - * - @a TIME_IMMEDIATE unlock the bus immediately - * . - * - * Lock I2C bus at the beginning of the next message sent - * for a maximum of lockDuration ticks. No other I2C masters will - * be allowed to interrupt until i2cUnlock() is called. - * - * @notapi - **/ -void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration) -{ - i2cp->lockDuration = lockDuration; - if (i2cp->mode >= i2cIsMaster) { - stopTimer(i2cp); - if (lockDuration == TIME_IMMEDIATE) - lockExpired(i2cp); - else if (lockDuration != TIME_INFINITE) - chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); - } -} - -#endif - - - -/** - * @brief report error waking thread or invoking callback as appropriate - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] errCode error bit mask or code - * - * @notapi - */ -static void reportErrs(I2CDriver *i2cp, i2cflags_t errCode) -{ -qEvt(0xee,errCode); - I2C_TypeDef *dp = i2cp->i2c; - if (i2cp->mode <= i2cIdle) /* failing to master bus */ - i2cAbortOperation(i2cp); - else if (dp->SR2 & I2C_SR2_MSL) { -#if HAL_USE_I2C_LOCK /* I2C bus locking support */ - i2cp->mode = i2cIsMaster; - switch (i2cp->lockDuration) { - case TIME_INFINITE: - break; - case TIME_IMMEDIATE: - stopTimer(i2cp); - default: - if (!chVTIsArmedI(&i2cp->timer)) { - dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); - i2cp->mode = i2cIdle; - i2cp->lockDuration = TIME_IMMEDIATE; - } - } -#else /* signal stop condition on any error */ - dp->CR1 |= (uint16_t)(I2C_CR1_STOP | I2C_CR1_ACK); - i2cp->mode = i2cIdle; -#endif - } -#if HAL_USE_I2C_SLAVE - else if (i2cp->mode < i2cIsMaster) { - i2cp->slaveErrors = errCode; - i2cAbortOperation(i2cp); - stopTimer(i2cp); - reportSlaveError(i2cp); - return; - } -#endif - /* wake any waiting master mode handling thread. */ - i2cp->errors = errCode; - wakeup_isr(i2cp, I2C_ERROR); -} - - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] sr content of the SR1 register to be decoded - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint16_t sr) { -#if HAL_USE_I2C_SLAVE -/* NACK of last byte transmitted in slave response is NORMAL -- not an error! */ - if (i2cp->mode == i2cSlaveReplying && (sr & I2C_ERROR_MASK) == I2C_SR1_AF) { -qEvt(0xcc,sr); - endSlaveReplyDMA(i2cp, 1); -#if HAL_USE_I2C_STARTFIX - i2cp->config->disarmStartDetect(); -#endif - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - i2cp->targetAdr = i2cInvalidAdr; - stopTimer(i2cp); - i2cp->mode = i2cIdle; - return; - } -#endif - i2cflags_t errs = 0; - - if (sr & I2C_SR1_BERR) /* Bus error. */ - errs = I2C_BUS_ERROR; - - if (sr & I2C_SR1_ARLO) /* Arbitration lost. */ - errs |= I2C_ARBITRATION_LOST; - - if (sr & I2C_SR1_AF) /* Acknowledge fail. */ - errs |= I2C_ACK_FAILURE; - - if (sr & I2C_SR1_OVR) /* Overrun. */ - errs |= I2C_OVERRUN; - - if (sr & I2C_SR1_TIMEOUT) /* SMBus Timeout. */ - errs |= I2C_TIMEOUT; - - if (sr & I2C_SR1_PECERR) /* PEC error. */ - errs |= I2C_PEC_ERROR; - - if (sr & I2C_SR1_SMBALERT) /* SMBus alert. */ - errs |= I2C_SMB_ALERT; - - if (!errs) - errs = I2C_UNKNOWN_ERROR; -qEvt(0xcb,errs); - - /* Disable any active DMA */ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); - - reportErrs(i2cp, errs); -} - - -static inline void endMasterAction(I2CDriver *i2cp, uint32_t regCR1) -{ -#if HAL_USE_I2C_LOCK - if (i2cp->lockDuration != TIME_IMMEDIATE && ( - chVTIsArmedI(&i2cp->timer) || i2cp->lockDuration == TIME_INFINITE)) { - i2cp->mode = i2cIsMaster; - return; - } - stopTimer(i2cp); -#endif - i2cp->i2c->CR1 = (regCR1 | I2C_CR1_STOP | I2C_CR1_ACK); - i2cp->mode = i2cIdle; -} - - -/** - * @brief I2C event handler ISR - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_event_interrupt(I2CDriver *i2cp) -{ - I2C_TypeDef *dp = i2cp->i2c; - uint16_t regCR1 = dp->CR1; - uint32_t regSR2 = dp->SR2; - uint32_t event = dp->SR1 | (regSR2 << 16); - - - switch (event & I2C_EV_MASK) { - -#define chkTransition(expectedMode) { \ - if (i2cp->mode != (expectedMode)) goto invalidTransition;} - - invalidTransition: /* error on known event out of expected sequence */ - i2cAbortOperation(i2cp); /* reset and reinit */ - qEvt(0x10, (event & 0xffff)); - reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode); - break; - -#if HAL_USE_I2C_SLAVE - case I2C_EV1_SLAVE_RXADRMATCH : /* Slave mode - receive a message */ -qEvt(0x11,0); - { - i2caddr_t targetAdr = matchedAdr(dp, regSR2); - switch (i2cp->mode) { - case i2cIdle: -#if HAL_USE_I2C_STARTFIX - i2cp->config->armStartDetect(); -#endif - break; - case i2cSlaveRxing: - endSlaveRxDMA(i2cp); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); - break; - case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ - endSlaveReplyDMA(i2cp, 2); - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - break; - default: - goto invalidTransition; - } - startSlaveAction(i2cp, targetAdr); - } - { - const I2CSlaveMsg *rx = i2cp->slaveNextRx; - if (rx->adrMatched) // Q: Can rx ever be NULL? - rx->adrMatched(i2cp); // Execute callback on address match if specified - rx = i2cp->slaveRx = i2cp->slaveNextRx; - if (rx->body && rx->size) { - (void)dp->SR2; /* clear I2C_SR1_ADDR */ - /* Receive buffer available - can receive immediately. Set up slave RX DMA */ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rx->body); - dmaStreamSetTransactionSize(i2cp->dmarx, rx->size); - dmaStreamEnable(i2cp->dmarx); - i2cp->mode = i2cSlaveRxing; - }else{ - dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); /* No reply set up - hold clock low and wait */ - i2cp->mode = i2cLockedRxing; - } - } - break; - - case I2C_EV2_SLAVE_RXSTOP: /* STOP received - possibly without NAK */ -qEvt(0x22,0); - dp->CR1 = (uint16_t)regCR1; /* clear STOPF */ - i2cp->slaveErrors = I2C_STOPPED; /* indicate that bus has been released */ - switch (i2cp->mode) { - case i2cSlaveRxing: - endSlaveRxDMA(i2cp); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); - break; - case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ - endSlaveReplyDMA(i2cp, 2); - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - break; - default: - goto invalidTransition; - } -#if HAL_USE_I2C_STARTFIX - i2cp->config->disarmStartDetect(); -#endif - i2cp->targetAdr = i2cInvalidAdr; - stopTimer(i2cp); - i2cp->mode = i2cIdle; - break; - - case I2C_EV1_SLAVE_TXADRMATCH: /* Slave mode - reply */ -qEvt(0x33,0); - { - i2caddr_t targetAdr = matchedAdr(dp, regSR2); - (void)dp->SR2; /* clear I2C_SR1_ADDR */ // TODO: Check - switch (i2cp->mode) { - case i2cIdle: -#if HAL_USE_I2C_STARTFIX - i2cp->config->armStartDetect(); -#endif - break; - case i2cSlaveRxing: /* Previous transaction not completed properly */ - endSlaveRxDMA(i2cp); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); - break; - default: - goto invalidTransition; - } - startSlaveAction(i2cp, targetAdr); - } - { - const I2CSlaveMsg *reply = i2cp->slaveNextReply; - if (reply->adrMatched) // Q: Can reply be NULL? - reply->adrMatched(i2cp); - reply = i2cp->slaveReply = i2cp->slaveNextReply; // Q: Duplicate action? - if (reply->body && reply->size) { - /* Reply message available - can send immediately. Set up slave TX DMA */ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, reply->body); - dmaStreamSetTransactionSize(i2cp->dmatx, reply->size); - dmaStreamEnable(i2cp->dmatx); - i2cp->mode = i2cSlaveReplying; - }else{ - dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); - i2cp->mode = i2cLockedReplying; - } - } - break; -#endif /* HAL_USE_I2C_SLAVE */ - - case I2C_EV5_MASTER_MODE_SELECT: -qEvt(0x55,0); - dp->DR = (uint16_t)i2cp->addr; - switch (i2cp->mode) { - case i2cIdle: -#if HAL_USE_I2C_LOCK - { - systime_t lockDuration = i2cp->lockDuration; - if (lockDuration != TIME_IMMEDIATE && lockDuration != TIME_INFINITE) - { - osalSysLockFromISR(); - chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); - osalSysUnlockFromISR(); - } - } -#endif - break; - case i2cIsMaster: - case i2cMasterStarted: - break; - default: - goto invalidTransition; - } - i2cp->mode = i2cMasterSelecting; - break; - - case I2C_EV6_MASTER_REC_MODE_SELECTED: -qEvt(0x66,0); - chkTransition(i2cMasterSelecting); - if (!i2cp->masterRxbytes) { /* 0-length SMBus style quick read */ - endMasterAction(i2cp, regCR1); - (void)dp->SR2; /* clear I2C_SR1_ADDR */ - wakeup_isr(i2cp, I2C_OK); - break; - } - (void)dp->SR2; /* clear I2C_SR1_ADDR */ - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, i2cp->masterRxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, i2cp->masterRxbytes); - dmaStreamEnable(i2cp->dmarx); - dp->CR2 |= I2C_CR2_LAST; /* Needed in receiver mode. */ - if (i2cp->masterRxbytes < 2) - dp->CR1 = (uint16_t)(regCR1 & ~I2C_CR1_ACK); - i2cp->mode = i2cMasterRxing; - break; - - case I2C_EV6_MASTER_TRA_MODE_SELECTED: -qEvt(0x77,0); - (void)dp->SR2; /* clear I2C_SR1_ADDR */ - chkTransition(i2cMasterSelecting); - switch (i2cp->masterTxbytes) { - case 0: - goto doneWriting; - case 1: - dp->DR = i2cp->masterTxbuf[0]; - break; - case 2: - dp->DR = i2cp->masterTxbuf[0]; - dp->DR = i2cp->masterTxbuf[1]; - break; - default: - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, i2cp->masterTxbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, i2cp->masterTxbytes); - dmaStreamEnable(i2cp->dmatx); - } - i2cp->mode = i2cMasterTxing; - break; - - case I2C_EV8_2_MASTER_BYTE_TRANSMITTED: -qEvt(0x88,0); - /* Catches BTF event after the end of transmission.*/ - (void)dp->DR; /* clears BTF flag */ - chkTransition(i2cMasterTxing); -doneWriting: - if (i2cp->masterRxbuf) { - /* Starts "read after write" operation, LSB = 1 -> receive.*/ - dp->CR1 = (uint16_t)(regCR1 | I2C_CR1_START | I2C_CR1_ACK); - i2cp->addr |= 1; - i2cp->mode = i2cMasterStarted; - }else{ - endMasterAction(i2cp, regCR1); - wakeup_isr(i2cp, I2C_OK); - } - break; - - case 0: /* quietly ignore "uninteresting" events (i.e. i2c bus busy) */ - qEvt(0x0000); - break; - - default: /* unhandled event -- abort transaction, flag unknown err */ -qEvt(0x9999,0); - //i2cAbortOperation(i2cp); - i2c_lld_serve_error_interrupt(i2cp, event); - } -} - - -#if HAL_USE_I2C_STARTFIX -/** - * @brief external device detected start condition - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details invoked from ISR if a START CONDITION detected during the time - * the startDetector is armed. - * This is a workaround for the STM32's lack of a repeated start event - * - * @notapi - */ -void i2c_lld_startDetected(I2CDriver *i2cp) -{ -qEvt(0xdddd,0); - switch (i2cp->mode) { - case i2cIdle: - i2cAbortOperation(i2cp); /* quietly reset and reinit */ - return; - case i2cSlaveRxing: - endSlaveRxDMA(i2cp); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); - break; - case i2cSlaveReplying: /* Master did not NACK last transmitted byte */ - endSlaveReplyDMA(i2cp, 2); - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - break; - default: - i2cAbortOperation(i2cp); /* reset and reinit */ - reportErrs(i2cp, I2C_UNKNOWN_ERROR + i2cp->mode); - return; - } - i2cp->targetAdr = i2cInvalidAdr; - stopTimer(i2cp); - i2cp->mode = i2cIdle; -} - -/** - * @brief dummy placeholder for armStartDetector() and disarmStartDetector() - * - * @details *MUST* be placed in the configuration struct in cases where - * HAL_USE_I2C_STARTFIX is configured and no startDetector is defined, - * otherwise NULL pointers will be called for these functions! - * - * @notapi - */ -void i2c_lld_noStartDetector(void) {} -#endif - - -/** - * @brief DMA RX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] flags pre-shifted content of the ISR register - * - * @notapi - */ -static void i2c_lld_serve_rx_end_irq(I2CDriver *i2cp, uint32_t flags) { - I2C_TypeDef *dp = i2cp->i2c; - -qEvt(0xaa,0); - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - - dmaStreamDisable(i2cp->dmarx); - -#if HAL_USE_I2C_SLAVE - if (i2cp->mode < i2cIsMaster) { - static uint8_t bitbucket; - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32) - else - i2cp->slaveBytes = i2cp->slaveRx->size; - /* discard data overrunning available rx buffer, but record total length */ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode & ~STM32_DMA_CR_MINC); - dmaStreamSetMemory0(i2cp->dmarx, &bitbucket); - dmaStreamSetTransactionSize(i2cp->dmarx, 0xffff); - dmaStreamEnable(i2cp->dmarx); - return; - } -#endif - - dp->CR2 &= (uint16_t)(~I2C_CR2_LAST); - endMasterAction(i2cp, dp->CR1); - wakeup_isr(i2cp, I2C_OK); -} - -/** - * @brief DMA TX end IRQ handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_serve_tx_end_irq(I2CDriver *i2cp, uint32_t flags) { -qEvt(0xbb,0); - /* DMA errors handling.*/ -#if defined(STM32_I2C_DMA_ERROR_HOOK) - if ((flags & (STM32_DMA_ISR_TEIF | STM32_DMA_ISR_DMEIF)) != 0) { - STM32_I2C_DMA_ERROR_HOOK(i2cp); - } -#else - (void)flags; -#endif - dmaStreamDisable(i2cp->dmatx); - -#if HAL_USE_I2C_SLAVE - if (i2cp->mode < i2cIsMaster) { - const I2CSlaveMsg *reply = i2cp->slaveReply; - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff; // TODO: Why?? (slaveBytes is uint32) - else - i2cp->slaveBytes = reply->size; - /* repeat the last byte in the reply */ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode & ~STM32_DMA_CR_MINC); - dmaStreamSetMemory0(i2cp->dmatx, reply->body+reply->size-1); - dmaStreamSetTransactionSize(i2cp->dmatx, 0xffff); - dmaStreamEnable(i2cp->dmatx); - } -#endif -} - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD1); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C1 error interrupt handler. - */ -OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint16_t sr = I2CD1.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD1.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD1, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD2); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C2 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint16_t sr = I2CD2.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD2.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD2, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { - - OSAL_IRQ_PROLOGUE(); - - i2c_lld_serve_event_interrupt(&I2CD3); - - OSAL_IRQ_EPILOGUE(); -} - -/** - * @brief I2C3 error interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { - uint16_t sr = I2CD3.i2c->SR1; - - OSAL_IRQ_PROLOGUE(); - - I2CD3.i2c->SR1 = ~(sr & I2C_ERROR_MASK); - i2c_lld_serve_error_interrupt(&I2CD3, sr); - - OSAL_IRQ_EPILOGUE(); -} -#endif /* STM32_I2C_USE_I2C3 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; - I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); - I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); -#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE - chVTObjectInit(&I2CD1.timer); -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; - I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); - I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); -#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE - chVTObjectInit(&I2CD2.timer); -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; - I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); - I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); -#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE - chVTObjectInit(&I2CD3.timer); -#endif -#endif /* STM32_I2C_USE_I2C3 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - - i2cp->txdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE | - STM32_DMA_CR_DIR_P2M; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - bool b; - - rccResetI2C1(); // **** From trunk - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C1_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C1(FALSE); - nvicEnableVector(I2C1_EV_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(I2C1_ER_IRQn, STM32_I2C_I2C1_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - bool b; - - rccResetI2C2(); // *** From trunk - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C2_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C2(FALSE); - nvicEnableVector(I2C2_EV_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(I2C2_ER_IRQn, STM32_I2C_I2C2_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - bool b; - - rccResetI2C3(); // *** From trunk - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_rx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C3_IRQ_PRIORITY, - (stm32_dmaisr_t)i2c_lld_serve_tx_end_irq, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - rccEnableI2C3(FALSE); - nvicEnableVector(I2C3_EV_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(I2C3_ER_IRQn, STM32_I2C_I2C3_IRQ_PRIORITY); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_I2C3 */ - } - - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->DR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->DR); - - /* Reset i2c peripheral.*/ - dp->CR1 = I2C_CR1_SWRST; - dp->CR1 = 0; - - i2cp->mode = i2cIdle; -#if HAL_USE_I2C_LOCK - i2cp->lockDuration = TIME_IMMEDIATE; -#endif -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg; - i2cp->targetAdr = i2cInvalidAdr; - i2cp->slaveTimeout = TIME_INFINITE; -#endif - - /* Setup I2C parameters.*/ - i2c_lld_set_clock(i2cp); - i2c_lld_set_opmode(i2cp); - - /* Enable interrrupts */ - dp->CR2 |= I2C_CR2_ITERREN | I2C_CR2_DMAEN | I2C_CR2_ITEVTEN; - /* Ready to go.*/ - dp->CR1 |= I2C_CR1_PE | I2C_CR1_ACK; -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state, then disable the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - - /* I2C disable.*/ - i2cReset(i2cp); - dmaStreamRelease(i2cp->dmatx); - dmaStreamRelease(i2cp->dmarx); - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - nvicDisableVector(I2C1_EV_IRQn); - nvicDisableVector(I2C1_ER_IRQn); - rccDisableI2C1(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - nvicDisableVector(I2C2_EV_IRQn); - nvicDisableVector(I2C2_ER_IRQn); - rccDisableI2C2(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - nvicDisableVector(I2C3_EV_IRQn); - nvicDisableVector(I2C3_ER_IRQn); - rccDisableI2C3(FALSE); - } -#endif - - reportErrs(i2cp, I2C_STOPPED); /* wake any blocked thread */ -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - reportErrs(i2cp, I2C_STOPPED); /* ensure both master and slave notified */ -#endif - } -} - - -/** - * @brief Starts an I2C bus master transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval I2C_OK if the function succeeded. - * @retval I2C_ERROR if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a - * timeout the driver should be stopped and restarted - * because the bus may in an uncertain state. - * Drivers that support slave mode require only the the driver be restarted - * after a timeout, as stopping and restarting may result in missed events. - * - * There's a system lock active from higher levels when this is called - * - * @notapi - */ -#if USE_OLD_MASTER_STARTUP -// This is the 'original' from the V2.x master/slave code -static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) -{ - osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); - - i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - - virtual_timer_t vt; /* Global timeout for the whole operation.*/ - chVTObjectInit(&vt); - - if (timeout != TIME_INFINITE) - chVTSetI(&vt, timeout, i2c_lld_safety_timeout, i2cp); - i2cp->errors = 0; - i2cp->thread = chThdGetSelfX(); - chSchGoSleepS(CH_STATE_SUSPENDED); - chVTResetI(&vt); - return chThdGetSelfX()->p_u.rdymsg; -} - - -#else - - - -// This version uses same logic as the 'original' V3.x master-only driver. -// Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout() -static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) -{ - systime_t start, end; - - osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); - - osalSysUnlock(); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ - if (!(i2cp->i2c->SR2 & I2C_SR2_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - } - - - i2cp->i2c->CR1 |= I2C_CR1_START | I2C_CR1_ACK; - - /* Waits for the operation completion or a timeout.*/ - return osalThreadSuspendTimeoutS(&i2cp->thread, timeout); -} -#endif - -/** - * @brief Receives data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval I2C_OK if the function succeeded. - * @retval I2C_ERROR if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a - * timeout the driver should be stopped and restarted - * because the bus may in an uncertain state. - * Drivers that support slave mode require only the the driver be restarted - * after a timeout, as stopping and restarting may result in missed events. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - osalDbgAssert((rxbytes < (1<<16)), - "#1 - >64Kbytes"); -#if defined(STM32F1XX_I2C) - osalDbgAssert((rxbytes != 1), - "#2 - rxbytes==1"); -#endif - osalDbgAssert((i2cp->thread==NULL), - "#3 - reentry"); - - /* Initializes driver fields, LSB = 1 -> receive.*/ - i2cp->addr = (addr << 1) | 1; - - /* store away DMA info for later activation in event ISR */ - i2cp->masterRxbuf = rxbuf; - i2cp->masterRxbytes = (uint16_t) rxbytes; - return startMasterAction(i2cp, timeout); -} - -/** - * @brief Transmits data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval I2C_OK if the function succeeded. - * @retval I2C_ERROR if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval I2C_ERR_TIMEOUT A timeout occurred before operation end. After a - * timeout the driver should be stopped and restarted - * because the bus is in an uncertain state. - * Drivers that support slave mode require only the the driver be restarted - * after a timeout, as stopping and restarting may result in missed events. - * - * There's a system lock active on entry from higher level driver - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - if (rxbuf == NULL) - rxbytes = 0; - osalDbgAssert(((rxbytes | txbytes) < (1<<16)), "#1 - >64Kbytes"); -#if defined(STM32F1XX_I2C) - osalDbgCheck((rxbytes == 0) || ((rxbytes > 1) && (rxbuf != NULL))); -#endif - osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); - - /* Initializes driver fields, LSB = 0 -> write.*/ - i2cp->addr = addr << 1; - /* store away DMA info for later activation in event ISR */ - i2cp->masterTxbuf = txbuf; - i2cp->masterTxbytes = (uint16_t) txbytes; - i2cp->masterRxbuf = rxbuf; - i2cp->masterRxbytes = (uint16_t) rxbytes; - return startMasterAction(i2cp, timeout); -} - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -/* These bits are undocumented, but used in STM32l1xx I2C example driver */ -#define I2C_OAR1_Ack_7bit (0x4000) /*enable 7 bit address acknowledge*/ -#define I2C_OAR1_Ack_10bit (0xC000) /*enable 10 bit address acknowledge*/ - -/** - * @brief Reconfigure I2C channel to respond to indicated address - * in addition to those already matched - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C network address - * - * @return Length of message OR the type of event received - * @retval I2C_OK Success - * @retval I2C_ERROR Cannot match address in addition of those already - * - * @details MatchAddress calls are cumulative. - * Specify address zero to match I2C "all call" - * Does not support 10-bit addressing. - * - * @notapi - **/ -msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - I2C_TypeDef *dp = i2cp->i2c; - if (i2cadr == 0) { - dp->CR1 |= I2C_CR1_ENGC; - dp->OAR1 |= I2C_OAR1_Ack_7bit; - }else{ - uint16_t adr = i2cadr << 1; - uint16_t ownAdr = dp->OAR1 & (0x7f<<1); - if (ownAdr == 0 || ownAdr == adr) - dp->OAR1 = adr | I2C_OAR1_Ack_7bit; - else if (!(dp->OAR2 & I2C_OAR2_ENDUAL)) - dp->OAR2 = adr | I2C_OAR2_ENDUAL; - else if ((dp->OAR2 & (0x7f<<1)) != adr) - return I2C_ERROR; /* cannot add this address to set of those matched */ - } - return I2C_OK; -} - - -/** - * @brief Reconfigure I2C channel to no longer match specified address - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C network address - * - * @details A message being transferred that has already matched the - * specified address will continue being processed. - * Requests to unmatch an address that is not currently being matched - * are ignored. - * Does not support 10-bit addressing. - * - * @notapi - **/ -void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - I2C_TypeDef *dp = i2cp->i2c; - if (i2cadr == 0) { - dp->CR1 &= (uint16_t)~I2C_CR1_ENGC; - if ((dp->OAR1 & (0x7f<<1)) == 0) - dp->OAR1 = 0; - }else{ - uint16_t adr = i2cadr << 1; - if ((dp->OAR1 & (0x7f<<1)) == adr) { - if (dp->OAR2 & I2C_OAR2_ENDUAL) - dp->OAR1 = (dp->OAR2 & (0x7f<<1)) | I2C_OAR1_Ack_7bit; - else - dp->OAR1 = dp->CR1 & I2C_CR1_ENGC ? I2C_OAR1_Ack_7bit : 0; - }else if (dp->OAR2 & I2C_OAR2_ENDUAL && (dp->OAR2 & (0x7f<<1)) == adr) - dp->OAR2 &= ~I2C_OAR2_ENDUAL; - } -} - - -/** - * @brief Reconfigure I2C channel to no longer match any address - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details Causes all subsequent messages to be ignored. - * A message being transferred that has already matched a - * slave address will continue being processed. - * - * @notapi - **/ -void i2c_lld_unmatchAll(I2CDriver *i2cp) -{ - I2C_TypeDef *dp = i2cp->i2c; - dp->CR1 &= (uint16_t)~I2C_CR1_ENGC; - dp->OAR1 = 0; - dp->OAR2 = 0; -} - - -/** - * @brief Configure callbacks & buffers to receive messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @notapi - */ -void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) -{ - osalDbgCheck((rxMsg && rxMsg->size <= 0xffff)); - i2cp->slaveNextRx = rxMsg; - if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) { - /* We can receive now! */ - I2C_TypeDef *dp = i2cp->i2c; - (void)dp->SR1, dp->SR2; /* clear I2C_SR1_ADDR */ - i2cp->slaveRx = rxMsg; - /* slave RX DMA setup */ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body); - dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size); - dmaStreamEnable(i2cp->dmarx); - i2cp->mode = i2cSlaveRxing; - dp->CR2 |= I2C_CR2_ITEVTEN; - } -} - - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @notapi - */ -void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) -{ - osalDbgCheck((replyMsg && replyMsg->size <= 0xffff)); - i2cp->slaveNextReply = replyMsg; - if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size) { - i2cp->slaveReply = replyMsg; - /* slave TX DMA setup -- we can reply now! */ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body); - dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size); - dmaStreamEnable(i2cp->dmatx); - i2cp->mode = i2cSlaveReplying; - i2cp->i2c->CR2 |= I2C_CR2_ITEVTEN; - } -} - -#endif /* HAL_USE_I2C_SLAVE */ - -#endif /* HAL_USE_I2C */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h deleted file mode 100644 index d45acaa671..0000000000 --- a/drivers/chibios/i2cslave/I2Cv1/hal_i2c_lld.h +++ /dev/null @@ -1,777 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. I2C Slave API contributed by Brent Roman (brent@mbari.org) - */ - -/** - * @file STM32/I2Cv1/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @brief Peripheral clock frequency. - */ -#define I2C_CLK_FREQ ((STM32_PCLK1) / 1000000) - -/** - * @brief Invalid I2C bus address - */ -#define i2cInvalidAdr ((i2caddr_t) -1) - - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief Enables support for I2C slave mode operation - */ -#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) -#define HAL_USE_I2C_SLAVE FALSE -#define HAL_USE_I2C_STARTFIX FALSE -#endif - -/** - * @brief Enables additional code needed with V1 I2C - */ -#if !defined(HAL_USE_I2C_STARTFIX) || defined(__DOXYGEN__) -#define HAL_USE_I2C_STARTFIX FALSE -#endif - - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** -* @brief I2C1 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C2 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** -* @brief I2C3 DMA priority (0..3|lowest..highest). -* @note The priority level is used for both the TX and RX DMA streams but -* because of the streams ordering the RX stream has always priority -* over the TX stream. -*/ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif - -#if STM32_ADVANCED_DMA || defined(__DOXYGEN__) - -/** - * @brief DMA stream used for I2C1 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 0) -#endif - -/** - * @brief DMA stream used for I2C1 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C1_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#endif - -/** - * @brief DMA stream used for I2C2 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C2 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C2_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#endif - -/** - * @brief DMA stream used for I2C3 RX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_RX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 2) -#endif - -/** - * @brief DMA stream used for I2C3 TX operations. - * @note This option is only available on platforms with enhanced DMA. - */ -#if !defined(STM32_I2C_I2C3_TX_DMA_STREAM) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) -#endif - -#else /* !STM32_ADVANCED_DMA */ - -/* Fixed streams for platforms using the old DMA peripheral, the values are - valid for both STM32F1xx and STM32L1xx.*/ -#define STM32_I2C_I2C1_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 7) -#define STM32_I2C_I2C1_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 6) -#define STM32_I2C_I2C2_RX_DMA_STREAM STM32_DMA_STREAM_ID(1, 5) -#define STM32_I2C_I2C2_TX_DMA_STREAM STM32_DMA_STREAM_ID(1, 4) - -#endif /* !STM32_ADVANCED_DMA*/ - -/* Flag for the whole STM32F1XX family. */ -#if defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) || defined(STM32F10X_LD) || \ - defined(STM32F10X_MD) || defined(STM32F10X_HD) || \ - defined(STM32F10X_XL) || defined(STM32F10X_CL) -#define STM32F1XX_I2C -#endif -/** @} */ - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && \ - !STM32_I2C_USE_I2C3 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C3" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) -#error "I2C1 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) -#error "I2C2 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 RX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif - -/* Check clock range. */ -#if defined(STM32F4XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 42) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32L1XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 32) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F2XX) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 30) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD_VL) || defined(STM32F10X_MD_VL) || \ - defined(STM32F10X_HD_VL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 24) -#error "I2C peripheral clock frequency out of range." -#endif - -#elif defined(STM32F10X_LD) || defined(STM32F10X_MD) || \ - defined(STM32F10X_HD) || defined(STM32F10X_XL) || \ - defined(STM32F10X_CL) -#if !(I2C_CLK_FREQ >= 2) && (I2C_CLK_FREQ <= 36) -#error "I2C peripheral clock frequency out of range." -#endif -#else -#error "unspecified, unsupported or invalid STM32 platform" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing an I2C address. - */ -typedef uint16_t i2caddr_t; - -/** - * @brief Type of I2C driver condition flags. - */ -typedef uint32_t i2cflags_t; - -/** - * @brief Supported modes for the I2C bus. - */ -typedef enum { - OPMODE_I2C = 1, - OPMODE_SMBUS_DEVICE = 2, - OPMODE_SMBUS_HOST = 3, -} i2copmode_t; - -/** - * @brief Supported duty cycle modes for the I2C bus. - */ -typedef enum { - STD_DUTY_CYCLE = 1, - FAST_DUTY_CYCLE_2 = 2, - FAST_DUTY_CYCLE_16_9 = 3, -} i2cdutycycle_t; - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - -/** - * @brief Driver configuration structure. - */ -typedef struct { - i2copmode_t op_mode; /**< @brief Specifies the I2C mode. */ - uint32_t clock_speed; /**< @brief Specifies the clock frequency. - @note Must be set to a value lower - than 400kHz. */ - i2cdutycycle_t duty_cycle; /**< @brief Specifies the I2C fast mode - duty cycle. */ -#if HAL_USE_I2C_STARTFIX && HAL_USE_I2C_SLAVE - void (*armStartDetect)(void); /**< @brief Arm Start Condition Detector */ - void (*disarmStartDetect)(void);/**< @brief Disarm Start Condition Detector */ -#endif -} I2CConfig; - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -typedef struct I2CSlaveMsg I2CSlaveMsg; - -/* - returns the current I2C slave message receive configuration -*/ -I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp); - - -/* - returns the current I2C slave message reply configuration -*/ -I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp); - - -/* - I2C Slave Message Call Back. - Invoked from interrupt context just after - the last byte of the message is transferred or slaveAdr is matched. - - Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access - the relevant message handling configuration -*/ -typedef void I2CSlaveMsgCB(I2CDriver *i2cp); - - -/* - I2CSlaveMsg message handling configurations are normally - stored in read-only memory. - They describe either a buffer to contain incoming messages from - a bus master and associated callback functions, or one - preloaded with an outgoing reply to a read request and its callbacks. -*/ - -struct I2CSlaveMsg { - size_t size; /* sizeof(body) -- zero if master must wait */ - uint8_t *body; /* message contents -- or NULL if master must wait */ - I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */ - I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */ - I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */ -}; - - -I2CSlaveMsgCB I2CSlaveDummyCB; -/* - dummy callback -- placeholder to ignore event -*/ - - /* lock bus on receive or reply -- force master to wait */ -extern const I2CSlaveMsg I2CSlaveLockOnMsg; - -#endif /* HAL_USE_I2C_SLAVE */ - - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) -#if CH_CFG_USE_MUTEXES || defined(__DOXYGEN__) - /** - * @brief Mutex protecting the bus. - */ - mutex_t mutex; -#elif CH_CFG_USE_SEMAPHORES - semaphore_t semaphore; -#endif -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - /** - * @brief Current slave address without R/W bit. - */ - i2caddr_t addr; - /** - * @brief Master RX DMA buffer size. - */ - uint16_t masterRxbytes; - /** - * @brief Master TX DMA buffer size. - */ - uint16_t masterTxbytes; - /** - * @brief Master RX DMA buffer base. - */ - uint8_t *masterRxbuf; - /** - * @brief Master TX DMA buffer base. - */ - const uint8_t *masterTxbuf; - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; - - /** - * @brief low level I2C interface / protocol state - */ - enum i2cMode { - i2cIdle=1, /* awaiting address or inactive */ - i2cSlaveRxing, /* receiving message */ - i2cLockedRxing, /* stretching clock before receiving message */ - i2cSlaveReplying, /* replying to query */ - i2cLockedReplying, /* stretching clock before replying to query */ - - i2cIsMaster=0x11, /* sent start bit (mastering bus) */ - i2cMasterStarted, /* repeated start after write */ - i2cMasterSelecting, /* sending slave address */ - i2cMasterRxing, /* receiving reply from slave */ - i2cMasterTxing /* sending message to slave */ - } mode; - -#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE - /** - * @brief I2C transaction timer - */ - virtual_timer_t timer; -#endif -#if HAL_USE_I2C_LOCK - /** - * @brief I2C bus lock duration - */ - systime_t lockDuration; -#endif -#if HAL_USE_I2C_SLAVE - /* additional fields to support I2C slave transactions */ - - /** - * @brief slave address of message being processed - */ - i2caddr_t targetAdr; - /** - * @brief Error Mask for last slave message - */ - i2cflags_t slaveErrors; - /** - * @brief Length of most recently transferred slave message - */ - uint32_t slaveBytes; - /** - * @brief Maximum # of ticks slave may stretch the I2C clock - */ - systime_t slaveTimeout; - /** - * @brief Pointer to slave message reception handler - */ - const I2CSlaveMsg *slaveRx; - /** - * @brief Pointer to slave message Reply handler - */ - const I2CSlaveMsg *slaveReply; - /** - * @brief Pointer to handler for next slave received message - */ - const I2CSlaveMsg *slaveNextRx; - /** - * @brief Pointer to handler for next slave reply message - */ - const I2CSlaveMsg *slaveNextReply; -#endif -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - - -#if HAL_USE_I2C_LOCK -/** - * @brief Unlock I2C bus after the end of the next transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - **/ -#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE) -#endif - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ -/** - * @brief Get slave errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors) - -/** - * @brief Get slave message bytes transferred from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes) - - -/** - * @brief Get slave timeout in ticks from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout) - -/** - * @brief Set slave timeout in ticks for I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks)) - -/** - * @brief Get slave target address from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr) - -/** - * @brief Get slave receive message descriptor from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx) - -/** - * @brief Get slave reply message descriptor from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply) - -#endif - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - -#if HAL_USE_I2C_LOCK /* I2C slave mode support */ - void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration); -#endif -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - void i2c_lld_unmatchAll(I2CDriver *i2cp); - void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); - void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); -#if HAL_USE_I2C_STARTFIX - void i2c_lld_startDetected(I2CDriver *i2cp); - void i2c_lld_noStartDetector(void); -#define i2cNoStartDetector i2c_lld_noStartDetector -#endif -#endif /* HAL_USE_I2C_SLAVE */ - -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_LLD_H_ */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv2/driver.mk b/drivers/chibios/i2cslave/I2Cv2/driver.mk deleted file mode 100644 index 06fb82ff8f..0000000000 --- a/drivers/chibios/i2cslave/I2Cv2/driver.mk +++ /dev/null @@ -1,21 +0,0 @@ -ifeq ($(USE_HAL_I2C_FALLBACK),yes) - # Fallback SW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/lib/fallback/I2C/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/lib/fallback/I2C -else - # Default HW driver. - ifeq ($(USE_SMART_BUILD),yes) - ifneq ($(findstring HAL_USE_I2C TRUE,$(HALCONF)),) - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c - endif - else - PLATFORMSRC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2/hal_i2c_lld.c - endif - PLATFORMINC += $(CHIBIOS)/os/hal/ports/STM32/LLD/I2Cv2 -endif diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c deleted file mode 100644 index b6df7c7169..0000000000 --- a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.c +++ /dev/null @@ -1,2065 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ - -/* -TODO: -1. Make sure slave mode registers updated OK -2. Test what of the newly inserted defines etc is actually necessary -3. Check whether all relevant features available on all ports on all processors (they are on F7, F051) -4. Do we need timer to get involved on master mode transactions? (May be multimaster requirement) -5. What about multimaster? Possibly nothing special to do, other than support all transitions round master and slave modes. -(Manual: "By default, it operates in slave mode. The interface automatically switches from slave to -master when it generates a START condition, and from master to slave if an arbitration loss -or a STOP generation occurs, allowing multimaster capability") -6. Understand use of lock timer - may only be relevant for multimaster, or even unnecessary -7. Check slave transfers > 255 bytes - -NOTES: -1. 10-bit addressing, masking options not currently supported in software in slave mode - (OAR1 hardware supports single 10-bit address matching; OAR2 supports 7-bit addressing with mask) -2. Address zero supported by setting 'General Call' flag in CR1 in slave mode (set with call to match address zero) -3. Clock stretching always enabled -4. Relevant configurable bits in CR1: - ANFOFF (analog noise filter) - DNF (digital noise filter bits) -5. Setting STM32_I2C_DEBUG_ENABLE to TRUE logs various events into a short circular buffer, which can then be examined using -the debugger. Alternatively, a call to i2cPrintQ(BaseSequentialStream *chp) prints the buffer. Note that the buffer only -has a write pointer, so once full its necessary to infer the start and end of the data - - */ - -/** - * @file STM32/I2Cv2/i2c_lld.c - * @brief STM32 I2C subsystem low level driver source. - * - * @addtogroup I2C - * @{ - */ - -#include "hal.h" - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_DMA == TRUE -#define DMAMODE_COMMON \ - (STM32_DMA_CR_PSIZE_BYTE | STM32_DMA_CR_MSIZE_BYTE | \ - STM32_DMA_CR_MINC | STM32_DMA_CR_DMEIE | \ - STM32_DMA_CR_TEIE | STM32_DMA_CR_TCIE) - -#define I2C1_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_CHN) - -#define I2C1_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_CHN) - -#define I2C2_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_CHN) - -#define I2C2_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_CHN) - -#define I2C3_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_CHN) - -#define I2C3_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_CHN) - -#define I2C4_RX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_RX_DMA_STREAM, \ - STM32_I2C4_RX_DMA_CHN) - -#define I2C4_TX_DMA_CHANNEL \ - STM32_DMA_GETCHANNEL(STM32_I2C_I2C4_TX_DMA_STREAM, \ - STM32_I2C4_TX_DMA_CHN) -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if STM32_I2C_USE_DMA == TRUE -#define i2c_lld_get_rxbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmarx) -#define i2c_lld_get_txbytes(i2cp) dmaStreamGetTransactionSize((i2cp)->dmatx) -#else -#define i2c_lld_get_rxbytes(i2cp) (i2cp)->rxbytes -#define i2c_lld_get_txbytes(i2cp) (i2cp)->txbytes -#endif - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ -#define I2C_ERROR_MASK \ - ((uint32_t)(I2C_ISR_BERR | I2C_ISR_ARLO | I2C_ISR_OVR | I2C_ISR_PECERR | \ - I2C_ISR_TIMEOUT | I2C_ISR_ALERT)) - -#define I2C_INT_MASK \ - ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ - I2C_ISR_ADDR | I2C_ISR_RXNE | I2C_ISR_TXIS)) - -/* Mask of interrupt bits cleared automatically - we mustn't clear ADDR else clock stretching doesn't happen */ -#define I2C_INT_CLEAR_MASK \ - ((uint32_t)(I2C_ISR_TCR | I2C_ISR_TC | I2C_ISR_STOPF | I2C_ISR_NACKF | \ - I2C_ISR_RXNE | I2C_ISR_TXIS)) - - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/** @brief I2C1 driver identifier.*/ -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -I2CDriver I2CD1; -#endif - -/** @brief I2C2 driver identifier.*/ -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -I2CDriver I2CD2; -#endif - -/** @brief I2C3 driver identifier.*/ -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -I2CDriver I2CD3; -#endif - -/** @brief I2C4 driver identifier.*/ -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -I2CDriver I2CD4; -#endif - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -#if STM32_I2C_DEBUG_ENABLE -/* - * Quick and dirty queue to record event interrupts (useful for debug) - * - * Assigned codes (may be others not noted here): - * 0x02 - NAK received - * 0x03 - transfer complete received - * 0x04 - Address match (records current mode before any error recovery etc) - * 0x05 - STOP received - * 0x06 - Part transfer complete interrupt - * 0x07 - Recovery from untidily finished previous transaction - * 0x08 - Recovery from untidily finished previous transaction - * 0x09 - Recovery from untidily finished previous transaction - * 0x10 - error in slave address match - send - * 0x11 - error in slave address match - receive - * 0x12 - address match - send - * 0x13 - address match - receive - * 0x14 - start slave receive operation - * 0x15 - lock on pending slave receive operation (no buffer) - * 0x16 - start slave transmit operation - * 0x17 - lock on pending slave transmit operation (no buffer available) - * 0x80 - new reply set - * 0x81 - reply used immediately - * 0x82 - new receive buffer set - * 0x83 - receive buffer used immediately - * 0xcc - clearing down after transmission - triggered by NAK received (usually valid) - * 0xd0 - Slave error being signalled - * 0xd1 - Slave error due to timeout -*/ -#define QEVENTS 32 - -typedef struct i2cQ_t { - uint8_t code; - uint8_t state; // Channel state - uint8_t mode; // Mode (mostly for slave) - uint16_t param; // Parameter sometimes used -} i2cQ_t; -i2cQ_t i2cQ[QEVENTS]; -unsigned i2cI = QEVENTS; -#define qEvt(posn,info) {if (++i2cI >= QEVENTS) i2cI = 0; \ - i2cQ[i2cI].code=(posn); i2cQ[i2cI].state=(i2cp->state); i2cQ[i2cI].mode=(i2cp->mode); i2cQ[i2cI].param=(info); } - -#include "chprintf.h" - -void i2cPrintQ(BaseSequentialStream *chp) -{ - uint8_t i; - if (QEVENTS == 0) - { - chprintf(chp, "I2C Debug queue disabled\r\n"); - } - else - { - chprintf(chp, "I2C debug ring - write pointer currently %02d\r\n", i2cI); - } - for (i = 0; i < QEVENTS; i++) - { - chprintf(chp, "%02d: %02x->%02x %02x %04x\r\n", i, i2cQ[i].code, i2cQ[i].state, i2cQ[i].mode, i2cQ[i].param); - if (i2cQ[i].code == 0) break; // Handle partially filled queue - } -} - -#else -#define qEvt(posn,info) -#endif - - - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - - -void I2CSlaveDummyCB(I2CDriver *i2cp) -/* - dummy callback -- placeholder to ignore event -*/ -{(void)i2cp;} - - /* lock bus on receive or reply message */ -const I2CSlaveMsg I2CSlaveLockOnMsg = { - 0, NULL, I2CSlaveDummyCB, I2CSlaveDummyCB, I2CSlaveDummyCB -}; - -#endif - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -#if HAL_USE_I2C_MASTER -/** - * @brief Slave (remote) address setup in master mode. - * @note The RW bit is set to zero internally. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * - * @notapi - */ -static void i2c_lld_set_address(I2CDriver *i2cp, i2caddr_t addr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Address alignment depends on the addressing mode selected.*/ - if ((i2cp->config->cr2 & I2C_CR2_ADD10) == 0U) - dp->CR2 = (uint32_t)addr << 1U; - else - dp->CR2 = (uint32_t)addr; -} -#endif - - - -/** - * @brief I2C RX transfer setup. - * @note Configures transfer count and related flags - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_rx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation (device constraint). */ -#if STM32_I2C_USE_DMA - if (i2cp->config->rxchar_cb) - { - n = i2cp->rxbytes; // Always interrupt-driven if we have a receive callback - } - else - { - n = i2c_lld_get_rxbytes(i2cp); // Otherwise get length from DMA or counter as appropriate - } -#else - n = i2cp->rxbytes; -#endif - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - - /* Configures the CR2 registers with both the calculated and static - settings. (Nothing much relevant in static settings - just PEC for SMBUS? */ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | I2C_CR2_RD_WRN | - (n << 16U) | reload; -} - - - -/** - * @brief I2C TX transfer setup. - * @note Configures transfer count and related flags - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_setup_tx_transfer(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - uint32_t reload; - size_t n; - - /* The unit can transfer 255 bytes maximum in a single operation. */ - n = i2c_lld_get_txbytes(i2cp); // Get transaction size from DMA or buffer as configured - if (n > 255U) { - n = 255U; - reload = I2C_CR2_RELOAD; - } - else { - reload = 0U; - } - - /* Configures the CR2 registers with both the calculated and static - settings.*/ - dp->CR2 = (dp->CR2 & ~(I2C_CR2_NBYTES | I2C_CR2_RELOAD)) | i2cp->config->cr2 | - (n << 16U) | reload; -} - - - -/** - * @brief Aborts an I2C transaction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void i2c_lld_abort_operation(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - -// Note: clearing PE doesn't affect configuration bits (including slave addresses) - if (dp->CR1 & I2C_CR1_PE) { - /* Stops the I2C peripheral.*/ - dp->CR1 &= ~I2C_CR1_PE; - while (dp->CR1 & I2C_CR1_PE) - dp->CR1 &= ~I2C_CR1_PE; - dp->CR1 |= I2C_CR1_PE; - } - -#if STM32_I2C_USE_DMA == TRUE - /* Stops the associated DMA streams.*/ - dmaStreamDisable(i2cp->dmatx); - dmaStreamDisable(i2cp->dmarx); -#else - dp->CR1 &= ~(I2C_CR1_TXIE | I2C_CR1_RXIE); // Stop byte-orientated interrupts -#endif -} - - - -#if HAL_USE_I2C_SLAVE || HAL_USE_I2C_LOCK -/** - * @brief stop transaction timeout countdown - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static inline void stopTimer(I2CDriver *i2cp) -{ - osalSysLockFromISR(); - chVTResetI(&i2cp->timer); - osalSysUnlockFromISR(); -} -#else -#define stopTimer(ignored) {} -#endif - - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -/** - * @brief report error via slave exception callback - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @note moves back to the idle mode - * @notapi - */ -static inline void reportSlaveError(I2CDriver *i2cp) { - if (i2cp->mode >= i2cIsMaster) return; - qEvt(0xd0, i2cp->slaveErrors); - const I2CSlaveMsg *xfer = i2cp->mode >= i2cSlaveReplying ? - i2cp->slaveReply : i2cp->slaveRx; - if (xfer->exception) - xfer->exception(i2cp); - i2cp->mode = i2cIdle; - i2cp->targetAdr = i2cInvalidAdr; -} - - -/** - * @brief Handling of stalled slave mode I2C transactions - timer handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static void slaveTimeExpired(void *i2cv) { - I2CDriver *i2cp = i2cv; - - if (i2cp->mode < i2cIsMaster) - { - i2c_lld_abort_operation(i2cp); - reportSlaveError(i2cp); - qEvt(0xd1, 0); - } -} - - -/** - * @brief start or restart slave mode transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] targetAdr slave address which was matched - * - * @notapi - */ -static inline void i2cStartSlaveAction(I2CDriver *i2cp, i2caddr_t targetAdr) -{ - stopTimer(i2cp); - i2cp->targetAdr = targetAdr; - i2cp->slaveBytes = 0; - i2cp->slaveErrors = 0; - if (i2cp->slaveTimeout != TIME_INFINITE) - { - osalSysLockFromISR(); - chVTSetI(&i2cp->timer, i2cp->slaveTimeout, slaveTimeExpired, i2cp); - osalSysUnlockFromISR(); - } -} - - -/** - * @brief end slave receive message DMA - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -static inline void i2cEndSlaveRxDMA(I2CDriver *i2cp) -{ - size_t bytesRemaining = i2c_lld_get_rxbytes(i2cp); - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff - bytesRemaining; - else - i2cp->slaveBytes = i2cp->slaveRx->size - bytesRemaining; -#if STM32_I2C_USE_DMA == TRUE - /* Disabling RX DMA channel.*/ - dmaStreamDisable(i2cp->dmarx); -#else - i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE); -#endif -} - - - -/** - * @brief end slave transmit DMA - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] bytesRemaining bytes lost in output queue - * - * @notapi - */ -static inline void i2cEndSlaveTxDMA(I2CDriver *i2cp, size_t bytesRemaining) -{ - bytesRemaining += i2c_lld_get_rxbytes(i2cp); - if (i2cp->slaveBytes) - i2cp->slaveBytes += 0xffff - bytesRemaining; - else - i2cp->slaveBytes = i2cp->slaveReply->size - bytesRemaining; -#if STM32_I2C_USE_DMA == TRUE - /* Disabling TX DMA channel.*/ - dmaStreamDisable(i2cp->dmatx); -#else - i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE); -#endif -} - -#endif - - - - -/** - * @brief Start a receive transaction (by enabling DMA, or enabling Rx character interrupts) - * - * @note All registers etc must be set up first - */ -static inline void i2cStartReceive(I2CDriver *i2cp) -{ -#if STM32_I2C_USE_DMA == TRUE - if (i2cp->config->rxchar_cb) - { - // Callback in use - use interrupt-driven transfer - i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; - } - else - { - /* Enabling RX DMA.*/ - dmaStreamEnable(i2cp->dmarx); - - /* Transfer complete interrupt enabled.*/ - i2cp->i2c->CR1 |= I2C_CR1_TCIE; - } -#else - - /* Transfer complete and RX interrupts enabled.*/ - i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_RXIE; -#endif -} - - -/** - * @brief Disable transmit data transfer, whether DMA or interrupt-driven - */ -static inline void i2cDisableTransmitOperation(I2CDriver *i2cp) -{ -#if STM32_I2C_USE_DMA == TRUE - /* Disabling TX DMA channel.*/ - dmaStreamDisable(i2cp->dmatx); -#else - i2cp->i2c->CR1 &= ~(I2C_CR1_TXIE); -#endif -} - - -/** - * @brief Disable receive data transfer, whether DMA or interrupt-driven - */ -static inline void i2cDisableReceiveOperation(I2CDriver *i2cp) -{ -#if STM32_I2C_USE_DMA == TRUE - /* Disabling RX DMA channel.*/ - dmaStreamDisable(i2cp->dmarx); -#else - i2cp->i2c->CR1 &= ~(I2C_CR1_RXIE); -#endif -} - - - -/*===========================================================================*/ -/* Shared ISR Code */ -/*===========================================================================*/ - -/** - * @brief I2C shared ISR code - 'Normal' (non-error) interrupts. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded (no masking applied) - * - * @notapi - */ -static void i2c_lld_serve_interrupt(I2CDriver *i2cp, uint32_t isr) { - I2C_TypeDef *dp = i2cp->i2c; - - /* Check for received NACK, the transfer is aborted. Do this in all modes */ - if ((isr & I2C_ISR_NACKF) != 0U) - { - qEvt(2, 0); - - i2cDisableReceiveOperation(i2cp); - i2cDisableTransmitOperation(i2cp); - #if HAL_USE_I2C_SLAVE - /* NACK of last byte transmitted in slave response is NORMAL -- not an error! */ - if (i2cp->mode == i2cSlaveReplying) - { - qEvt(0xcc,0); - i2cEndSlaveTxDMA(i2cp, 1); - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - i2cp->targetAdr = i2cInvalidAdr; - stopTimer(i2cp); - return; - } - #endif - - /* Error flag.*/ - i2cp->errors |= I2C_ACK_FAILURE; - - /* Transaction finished, send the STOP. */ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more interrupts.*/ - dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); - - if (i2cp->mode < i2cIsMaster) - { - i2cp->mode = i2cIdle; - } - else - { - /* Master mode - Errors are signalled to the upper layer.*/ - i2cp->mode = i2cIdle; - // Must only wake up thread in master mode. - _i2c_wakeup_isr(i2cp); // This is a normal completion - } - - return; - } - - -#if STM32_I2C_USE_DMA == FALSE - /* Handling of data transfer if the DMA mode is disabled - done character by character. Mode should be irrelevant */ - { - uint32_t cr1 = dp->CR1; - - if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying)) - { - /* Transmission phase.*/ - if (((cr1 &I2C_CR1_TXIE) != 0U) && ((isr & I2C_ISR_TXIS) != 0U)) { - dp->TXDR = (uint32_t)*i2cp->txptr; - i2cp->txptr++; - i2cp->txbytes--; - if (i2cp->txbytes == 0U) { - dp->CR1 &= ~I2C_CR1_TXIE; // Last byte sent - stop Tx interrupt - } - } - } - else - { - /* Receive phase.*/ - if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { - uint8_t c; - *i2cp->rxptr = c = (uint8_t)dp->RXDR; - i2cp->rxptr++; - i2cp->rxbytes--; - if (i2cp->config->rxchar_cb) - { - if (i2cp->config->rxchar_cb(i2cp, c) > 0) - { - /* Transaction finished, send the STOP. */ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more interrupts.*/ - dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); - - if (i2cp->mode < i2cIsMaster) - { - i2cp->mode = i2cIdle; - } - else - { - /* Master mode - Errors are signalled to the upper layer.*/ - i2cp->mode = i2cIdle; - // Must only wake up thread in master mode. - _i2c_wakeup_isr(i2cp); // This is a normal completion - } - - return; - } - } - if (i2cp->rxbytes == 0U) { - dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode) - } - } - } - } -#else - /* Receive character phase with callback enabled. */ - if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cMasterRxing)) - { - uint32_t cr1 = dp->CR1; - if (((cr1 & I2C_CR1_RXIE) != 0U) && ((isr & I2C_ISR_RXNE) != 0U)) { - uint8_t c; - c = (uint8_t)dp->RXDR; - *i2cp->rxptr = c; - i2cp->rxptr++; - i2cp->rxbytes--; - if (i2cp->config->rxchar_cb) - { - if (i2cp->config->rxchar_cb(i2cp, c) > 0) - { - /* Transaction finished, send the STOP. */ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more interrupts.*/ - dp->CR1 &= ~(I2C_CR1_TCIE | I2C_CR1_TXIE | I2C_CR1_RXIE | I2C_CR1_STOPIE); - - if (i2cp->mode < i2cIsMaster) - { - i2cp->mode = i2cIdle; - } - else - { - /* Master mode - Errors are signalled to the upper layer.*/ - i2cp->mode = i2cIdle; - // Must only wake up thread in master mode. - _i2c_wakeup_isr(i2cp); // This is a normal completion - } - - return; - } - } - if (i2cp->rxbytes == 0U) { - dp->CR1 &= ~I2C_CR1_RXIE; // Buffer full - stop reception (TODO: Should we send NAK?? Only possible in slave mode) - } - } - } -#endif - - - - /* Partial transfer handling, restarting the transfer and returning. */ - if ((isr & I2C_ISR_TCR) != 0U) - { - qEvt(0x06, 0); - if ((i2cp->state == I2C_ACTIVE_TX) || (i2cp->mode == i2cSlaveReplying)) { - i2c_lld_setup_tx_transfer(i2cp); - } - if ((i2cp->state == I2C_ACTIVE_RX) || (i2cp->mode == i2cSlaveRxing)) { - i2c_lld_setup_rx_transfer(i2cp); - } - return; - } - - - - /* The following condition is true if a transfer phase has been completed. */ - if ((isr & I2C_ISR_TC) != 0U) - { - qEvt(3,i2cp->state); -#if HAL_USE_I2C_SLAVE - switch (i2cp->mode) - { - case i2cLockedRxing : /* stretching clock before receiving message - Rx buffer might be full */ - case i2cLockedReplying : - break; // TODO: Two unsupported cases to consider - maybe they can't happen - case i2cSlaveReplying : // Must have just finished sending a reply in slave mode - break; // Just go on to send STOP bit and tidy up - - case i2cSlaveRxing : // Must have just received a message - process if we can - i2cEndSlaveRxDMA(i2cp); - qEvt(0x20, 0); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); - // TODO: Should get a reply message set - if so, start to send it and return - return; // For now, see what happens if we just return - break; - default : // Assume a master mode -#endif - if (i2cp->state == I2C_ACTIVE_TX) { - /* End of the transmit phase.*/ - - i2cDisableTransmitOperation(i2cp); // Disable - - /* Starting receive phase if necessary.*/ - if (i2c_lld_get_rxbytes(i2cp) > 0U) { - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - - #if STM32_I2C_USE_DMA == TRUE - // If receive callback enabled, always transfer using interrupts - if (i2cp->config->rxchar_cb) - { - /* RX interrupt enabled.*/ - dp->CR1 |= I2C_CR1_RXIE; - } - else - { - /* Enabling RX DMA.*/ - dmaStreamEnable(i2cp->dmarx); - } - #else - /* RX interrupt enabled.*/ - dp->CR1 |= I2C_CR1_RXIE; - #endif - - /* Starts the read operation.*/ - dp->CR2 |= I2C_CR2_START; - - /* State change.*/ - i2cp->state = I2C_ACTIVE_RX; - i2cp->mode = i2cMasterRxing; - - /* Note, returning because the transaction is not over yet.*/ - return; - } - } - else - { - /* End of the receive phase.*/ - i2cDisableReceiveOperation(i2cp); - } - -#if HAL_USE_I2C_SLAVE - } -#endif - - /* Transaction finished sending the STOP. */ - dp->CR2 |= I2C_CR2_STOP; - - /* Make sure no more 'Transfer Complete' interrupts. */ - dp->CR1 &= ~I2C_CR1_TCIE; - - /* Normal transaction end.*/ - if (i2cp->mode < i2cIsMaster) - { - // Slave mode - just move to idle state - i2cp->mode = i2cIdle; - } - else - { - i2cp->mode = i2cIdle; - // Must only wake up thread in master mode - _i2c_wakeup_isr(i2cp); - } - } - - -#if HAL_USE_I2C_SLAVE - uint8_t abort = 0; - /* Check for address match - if so, we're slave */ - if ((isr & I2C_ISR_ADDR) != 0U) - { - i2caddr_t targetAdr = (isr & I2C_ISR_ADDCODE) >> 17; // Identify which slave address used - uint8_t xferDir = (isr & I2C_ISR_DIR) ? 0 : 1; // Status bit is 0 for receive, 1 for transmit. xferDir inverts sense - dp->CR1 |= I2C_CR1_STOPIE; // Enable STOP interrupt so we know when slave transaction done - - /* First, tidy up from previous transactions as necessary */ - qEvt(0x04, 0); - switch (i2cp->mode) { - case i2cIdle: - break; - case i2cSlaveRxing: /* Previous transaction not completed properly, or - maybe we were sent a message without being asked for a reply */ - qEvt(0x07, 0); - i2cEndSlaveRxDMA(i2cp); - if (i2cp->slaveRx->processMsg) - i2cp->slaveRx->processMsg(i2cp); // Execute callback if defined - break; - case i2cSlaveReplying: /* Master did not NACK last transmitted byte (most likely picked up by NAK handler) */ - qEvt(0x08, 0); - if (!xferDir) - { - qEvt(0x09, 0); - i2cEndSlaveTxDMA(i2cp, 2); - if (i2cp->slaveReply->processMsg) - i2cp->slaveReply->processMsg(i2cp); - break; - } - // Intentionally don't break if we're addressed to receive - default: - // todo: Does this lot happen in the right order? Is an abort appropriate? Or should we just continue? - qEvt(0x10 + xferDir, 0); - i2cp->slaveErrors = I2C_UNKNOWN_ERROR + i2cp->mode; - i2c_lld_abort_operation(i2cp); /* reset and reinit */ - stopTimer(i2cp); - reportSlaveError(i2cp); // This clears down to idle - abort = 1; - } - if (!abort) - { - qEvt(0x12 + xferDir, (i2cp->slaveNextRx->size)); - if (xferDir) - { - /* Start Receive */ - /* If receive buffer still full, need to extend clock for timeout. Otherwise set up to receive */ - dp->CR1 &= ~I2C_CR1_SBC; // Not needed with receive - i2cStartSlaveAction(i2cp, targetAdr); - - const I2CSlaveMsg *rx = i2cp->slaveNextRx; - if (rx->adrMatched) // Q: Can rx ever be NULL? - rx->adrMatched(i2cp); // Execute callback on address match if specified - rx = i2cp->slaveRx = i2cp->slaveNextRx; // Reload message pointer in case callback changed it - if (rx->body && rx->size) - { - /* Receive buffer available - can receive immediately. Set up slave RX DMA */ - i2c_lld_setup_rx_transfer(i2cp); - #if STM32_I2C_USE_DMA == TRUE - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rx->body); - dmaStreamSetTransactionSize(i2cp->dmarx, rx->size); - #else - i2cp->rxptr = rx->body; - i2cp->rxbytes = rx->size; - #endif - - i2cStartReceive(i2cp); - dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now - i2cp->mode = i2cSlaveRxing; - qEvt(0x14,0); - } - else - { - /* No reply set up - hold clock low and wait (happens automatically) */ - qEvt(0x15,0); - i2cp->mode = i2cLockedRxing; - } - } - else - { - /* Start Transmit */ - i2cStartSlaveAction(i2cp, targetAdr); - const I2CSlaveMsg *reply = i2cp->slaveNextReply; - const I2CSlaveMsg *rx = i2cp->slaveNextRx; // Receive control block - if (rx->adrMatched) // Q: Can rx ever be NULL? - rx->adrMatched(i2cp); // Execute callback on address match if specified - reply = i2cp->slaveReply = i2cp->slaveNextReply; // Reload message pointer in case callback changed it - if (reply->body && reply->size) - { - /* Reply message available - can send immediately. Set up slave TX DMA */ - #if STM32_I2C_USE_DMA == TRUE - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, reply->body); - dmaStreamSetTransactionSize(i2cp->dmatx, reply->size); - /* Start transmission */ - i2c_lld_setup_tx_transfer(i2cp); - - /* Enabling TX DMA.*/ - dmaStreamEnable(i2cp->dmatx); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; - #else - /* Start transmission */ - i2cp->txptr = reply->body; - i2cp->txbytes = reply->size; - i2c_lld_setup_tx_transfer(i2cp); - /* Transfer complete and TX character interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; - #endif - qEvt(0x16,0); - i2cp->mode = i2cSlaveReplying; - dp->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode - dp->ICR = I2C_ISR_ADDR; // We can release the clock stretch now - } - else - { - // clock is automatically stretched if we don't clear the status bit - //dp->CR2 &= (uint16_t)(~I2C_CR2_ITEVTEN); - qEvt(0x17, 0); - i2cp->mode = i2cLockedReplying; - } - } - } /* if !abort */ - } - if ((isr & I2C_ISR_STOPF) != 0U) { - /* - * STOP received: - * in master mode, if generated by peripheral - can probably just ignore - * in slave mode, if detected on bus (from any source?) - * - * Clear everything down - particularly relevant in slave mode - */ - qEvt(0x05, 0); - dp->CR1 &= ~I2C_CR1_STOPIE; // Disable STOP interrupt - i2cDisableReceiveOperation(i2cp); // These two may not be necessary - i2cDisableTransmitOperation(i2cp); - stopTimer(i2cp); - i2cp->mode = i2cIdle; - } -#endif -} - - - -/** - * @brief I2C error handler. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] isr content of the ISR register to be decoded (no masking applied) - * - * @notapi - */ -static void i2c_lld_serve_error_interrupt(I2CDriver *i2cp, uint32_t isr) { - - i2cDisableReceiveOperation(i2cp); - i2cDisableTransmitOperation(i2cp); - stopTimer(i2cp); - -#if HAL_USE_I2C_SLAVE - // In slave mode, just clock errors and return - if (i2cp->mode < i2cIsMaster) - { - reportSlaveError(i2cp); // This clears down to idle - return; - } -#endif - - if (isr & I2C_ISR_BERR) - i2cp->errors |= I2C_BUS_ERROR; - - if (isr & I2C_ISR_ARLO) - i2cp->errors |= I2C_ARBITRATION_LOST; - - if (isr & I2C_ISR_OVR) - i2cp->errors |= I2C_OVERRUN; - - if (isr & I2C_ISR_TIMEOUT) - i2cp->errors |= I2C_TIMEOUT; - - /* If some error has been identified then wake up the waiting thread.*/ - if (i2cp->errors != I2C_NO_ERROR) - { - i2cp->mode = i2cIdle; - _i2c_wakeup_error_isr(i2cp); - } -} - - - - - -#if HAL_USE_I2C_LOCK /* I2C bus locking support */ - -/** - * @brief Handling of expired master bus lock timer - * - * @param[in] i2cv pointer to the @p I2CDriver object - * - * @notapi - */ -static void lockExpired(void *i2cv) { - I2CDriver *i2cp = i2cv; - - if (i2cp->mode == i2cIsMaster && !i2cp->thread) { /* between transactions */ - i2cp->i2c->CR2 |= I2C_CR2_STOP; - i2cp->mode = i2cIdle; - } - i2cp->lockDuration = TIME_IMMEDIATE; -} - - - - -/** - * @brief Lock I2C bus at the beginning of the next message - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] lockDuration max number of ticks to hold bus locked - * - @a TIME_INFINITE no timeout. - * - @a TIME_IMMEDIATE unlock the bus immediately - * . - * - * Lock I2C bus at the beginning of the next message sent - * for a maximum of lockDuration ticks. No other I2C masters will - * be allowed to interrupt until i2cUnlock() is called. - * - * @notapi - **/ -void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration) -{ - i2cp->lockDuration = lockDuration; - if (i2cp->mode >= i2cIsMaster) { - stopTimer(i2cp); - if (lockDuration == TIME_IMMEDIATE) - lockExpired(i2cp); - else if (lockDuration != TIME_INFINITE) - chVTSetI(&i2cp->timer, lockDuration, lockExpired, i2cp); - } -} - -#endif - -/*===========================================================================*/ -/* Driver interrupt handlers. */ -/*===========================================================================*/ - -#if STM32_I2C_USE_I2C1 || defined(__DOXYGEN__) -#if defined(STM32_I2C1_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C1 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C1_GLOBAL_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & ~I2C_ISR_ADDR; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD1, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C1_EVENT_HANDLER) && defined(STM32_I2C1_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C1_EVENT_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_INT_CLEAR_MASK; - - i2c_lld_serve_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C1_ERROR_HANDLER) { - uint32_t isr = I2CD1.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD1.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD1, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C1 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 || defined(__DOXYGEN__) -#if defined(STM32_I2C2_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C2 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C2_GLOBAL_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & ~I2C_ISR_ADDR; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD2, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C2_EVENT_HANDLER) && defined(STM32_I2C2_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C2_EVENT_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_INT_CLEAR_MASK; - - i2c_lld_serve_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C2_ERROR_HANDLER) { - uint32_t isr = I2CD2.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD2.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD2, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C2 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 || defined(__DOXYGEN__) -#if defined(STM32_I2C3_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C3 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C3_GLOBAL_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & ~I2C_ISR_ADDR; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD3, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C3_EVENT_HANDLER) && defined(STM32_I2C3_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C3_EVENT_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_INT_CLEAR_MASK; - - i2c_lld_serve_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C3_ERROR_HANDLER) { - uint32_t isr = I2CD3.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD3.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD3, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C3 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 || defined(__DOXYGEN__) -#if defined(STM32_I2C4_GLOBAL_HANDLER) || defined(__DOXYGEN__) -/** - * @brief I2C4 event interrupt handler. - * - * @notapi - */ -OSAL_IRQ_HANDLER(STM32_I2C4_GLOBAL_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & ~I2C_ISR_ADDR; - - if (isr & I2C_ERROR_MASK) - i2c_lld_serve_error_interrupt(&I2CD4, isr); - else if (isr & I2C_INT_MASK) - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#elif defined(STM32_I2C4_EVENT_HANDLER) && defined(STM32_I2C4_ERROR_HANDLER) -OSAL_IRQ_HANDLER(STM32_I2C4_EVENT_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_INT_CLEAR_MASK; - - i2c_lld_serve_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -OSAL_IRQ_HANDLER(STM32_I2C4_ERROR_HANDLER) { - uint32_t isr = I2CD4.i2c->ISR; - - OSAL_IRQ_PROLOGUE(); - - /* Clearing IRQ bits.*/ - I2CD4.i2c->ICR = isr & I2C_ERROR_MASK; - - i2c_lld_serve_error_interrupt(&I2CD4, isr); - - OSAL_IRQ_EPILOGUE(); -} - -#else -#error "I2C4 interrupt handlers not defined" -#endif -#endif /* STM32_I2C_USE_I2C4 */ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief Low level I2C driver initialization. - * - * @notapi - */ -void i2c_lld_init(void) { - -#if STM32_I2C_USE_I2C1 - i2cObjectInit(&I2CD1); - I2CD1.thread = NULL; - I2CD1.i2c = I2C1; -#if STM32_I2C_USE_DMA == TRUE - I2CD1.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C1_RX_DMA_STREAM); - I2CD1.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C1_TX_DMA_STREAM); -#endif -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - i2cObjectInit(&I2CD2); - I2CD2.thread = NULL; - I2CD2.i2c = I2C2; -#if STM32_I2C_USE_DMA == TRUE - I2CD2.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C2_RX_DMA_STREAM); - I2CD2.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C2_TX_DMA_STREAM); -#endif -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - i2cObjectInit(&I2CD3); - I2CD3.thread = NULL; - I2CD3.i2c = I2C3; -#if STM32_I2C_USE_DMA == TRUE - I2CD3.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C3_RX_DMA_STREAM); - I2CD3.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C3_TX_DMA_STREAM); -#endif -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - i2cObjectInit(&I2CD4); - I2CD4.thread = NULL; - I2CD4.i2c = I2C4; -#if STM32_I2C_USE_DMA == TRUE - I2CD4.dmarx = STM32_DMA_STREAM(STM32_I2C_I2C4_RX_DMA_STREAM); - I2CD4.dmatx = STM32_DMA_STREAM(STM32_I2C_I2C4_TX_DMA_STREAM); -#endif -#endif /* STM32_I2C_USE_I2C4 */ -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_start(I2CDriver *i2cp) { - I2C_TypeDef *dp = i2cp->i2c; - -#if STM32_I2C_USE_DMA == TRUE - /* Common DMA modes.*/ - i2cp->txdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_M2P; - i2cp->rxdmamode = DMAMODE_COMMON | STM32_DMA_CR_DIR_P2M; -#endif - - /* Make sure I2C peripheral is disabled */ - dp->CR1 &= ~I2C_CR1_PE; - i2cp->mode = i2cStopped; - - /* If in stopped state then enables the I2C and DMA clocks.*/ - if (i2cp->state == I2C_STOP) { - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { - - rccResetI2C1(); - rccEnableI2C1(FALSE); -#if STM32_I2C_USE_DMA == TRUE - { - bool b; - - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C1_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C1_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C1_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C1_DMA_PRIORITY); - } -#endif /* STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C1_GLOBAL_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicEnableVector(STM32_I2C1_EVENT_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C1_ERROR_NUMBER, STM32_I2C_I2C1_IRQ_PRIORITY); -#else -#error "I2C1 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C1 */ - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { - - rccResetI2C2(); - rccEnableI2C2(FALSE); -#if STM32_I2C_USE_DMA == TRUE - { - bool b; - - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C2_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C2_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C2_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C2_DMA_PRIORITY); - } -#endif /*STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C2_GLOBAL_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicEnableVector(STM32_I2C2_EVENT_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C2_ERROR_NUMBER, STM32_I2C_I2C2_IRQ_PRIORITY); -#else -#error "I2C2 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C2 */ - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { - - rccResetI2C3(); - rccEnableI2C3(FALSE); -#if STM32_I2C_USE_DMA == TRUE - { - bool b; - - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C3_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C3_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C3_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C3_DMA_PRIORITY); - } -#endif /*STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C3_GLOBAL_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) - nvicEnableVector(STM32_I2C3_EVENT_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C3_ERROR_NUMBER, STM32_I2C_I2C3_IRQ_PRIORITY); -#else -#error "I2C3 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C3 */ - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { - - rccResetI2C4(); - rccEnableI2C4(FALSE); -#if STM32_I2C_USE_DMA == TRUE - { - bool b; - - b = dmaStreamAllocate(i2cp->dmarx, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - b = dmaStreamAllocate(i2cp->dmatx, - STM32_I2C_I2C4_IRQ_PRIORITY, - NULL, - (void *)i2cp); - osalDbgAssert(!b, "stream already allocated"); - - i2cp->rxdmamode |= STM32_DMA_CR_CHSEL(I2C4_RX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - i2cp->txdmamode |= STM32_DMA_CR_CHSEL(I2C4_TX_DMA_CHANNEL) | - STM32_DMA_CR_PL(STM32_I2C_I2C4_DMA_PRIORITY); - } -#endif /*STM32_I2C_USE_DMA == TRUE */ - -#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicEnableVector(STM32_I2C4_GLOBAL_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) - nvicEnableVector(STM32_I2C4_EVENT_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); - nvicEnableVector(STM32_I2C4_ERROR_NUMBER, STM32_I2C_I2C4_IRQ_PRIORITY); -#else -#error "I2C4 interrupt numbers not defined" -#endif - } -#endif /* STM32_I2C_USE_I2C4 */ - } - -#if STM32_I2C_USE_DMA == TRUE - /* I2C registers pointed by the DMA.*/ - dmaStreamSetPeripheral(i2cp->dmarx, &dp->RXDR); - dmaStreamSetPeripheral(i2cp->dmatx, &dp->TXDR); - /* Reset i2c peripheral, the TCIE bit will be handled separately. */ - // TODO: Mask out config bits which user mustn't fiddle with - dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE | - I2C_CR1_TXDMAEN | I2C_CR1_RXDMAEN); -#else - /* Reset i2c peripheral, the TCIE bit will be handled separately. No DMA interrupts */ - dp->CR1 = (i2cp->config->cr1 | I2C_CR1_ERRIE | I2C_CR1_NACKIE); -#endif - - /* Setup I2C parameters.*/ - dp->TIMINGR = i2cp->config->timingr; - - /* Ready to go.*/ - i2cp->mode = i2cIdle; -#if HAL_USE_I2C_LOCK - i2cp->lockDuration = TIME_IMMEDIATE; -#endif -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - i2cp->slaveNextReply = i2cp->slaveNextRx = &I2CSlaveLockOnMsg; - i2cp->targetAdr = i2cInvalidAdr; - i2cp->slaveTimeout = TIME_INFINITE; -#endif - - dp->CR1 |= I2C_CR1_PE; // Enable peripheral -} - - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -void i2c_lld_stop(I2CDriver *i2cp) { - - /* If not in stopped state then disables the I2C clock.*/ - if (i2cp->state != I2C_STOP) { - i2cp->mode = i2cStopped; - - /* I2C disable.*/ - stopTimer(i2cp); - i2c_lld_abort_operation(i2cp); -#if STM32_I2C_USE_DMA == TRUE - dmaStreamRelease(i2cp->dmatx); - dmaStreamRelease(i2cp->dmarx); -#endif - -#if STM32_I2C_USE_I2C1 - if (&I2CD1 == i2cp) { -#if defined(STM32_I2C1_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C1_GLOBAL_NUMBER); -#elif defined(STM32_I2C1_EVENT_NUMBER) && defined(STM32_I2C1_ERROR_NUMBER) - nvicDisableVector(STM32_I2C1_EVENT_NUMBER); - nvicDisableVector(STM32_I2C1_ERROR_NUMBER); -#else -#error "I2C1 interrupt numbers not defined" -#endif - - rccDisableI2C1(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C2 - if (&I2CD2 == i2cp) { -#if defined(STM32_I2C2_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C2_GLOBAL_NUMBER); -#elif defined(STM32_I2C2_EVENT_NUMBER) && defined(STM32_I2C2_ERROR_NUMBER) - nvicDisableVector(STM32_I2C2_EVENT_NUMBER); - nvicDisableVector(STM32_I2C2_ERROR_NUMBER); -#else -#error "I2C2 interrupt numbers not defined" -#endif - - rccDisableI2C2(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C3 - if (&I2CD3 == i2cp) { -#if defined(STM32_I2C3_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C3_GLOBAL_NUMBER); -#elif defined(STM32_I2C3_EVENT_NUMBER) && defined(STM32_I2C3_ERROR_NUMBER) - nvicDisableVector(STM32_I2C3_EVENT_NUMBER); - nvicDisableVector(STM32_I2C3_ERROR_NUMBER); -#else -#error "I2C3 interrupt numbers not defined" -#endif - - rccDisableI2C3(FALSE); - } -#endif - -#if STM32_I2C_USE_I2C4 - if (&I2CD4 == i2cp) { -#if defined(STM32_I2C4_GLOBAL_NUMBER) || defined(__DOXYGEN__) - nvicDisableVector(STM32_I2C4_GLOBAL_NUMBER); -#elif defined(STM32_I2C4_EVENT_NUMBER) && defined(STM32_I2C4_ERROR_NUMBER) - nvicDisableVector(STM32_I2C4_EVENT_NUMBER); - nvicDisableVector(STM32_I2C4_ERROR_NUMBER); -#else -#error "I2C4 interrupt numbers not defined" -#endif - - rccDisableI2C4(FALSE); - } -#endif - } -} - - - -#if HAL_USE_I2C_MASTER == TRUE -/** - * Utility routine brings out common code for master timeout - */ -static msg_t calcMasterTimeout(I2CDriver *i2cp) -{ - systime_t start, end; - - osalDbgAssert((i2cp->mode <= i2cIsMaster), "busy"); - - /* Calculating the time window for the timeout on the busy bus condition.*/ - start = osalOsGetSystemTimeX(); - end = start + OSAL_MS2ST(STM32_I2C_BUSY_TIMEOUT); - - /* Waits until BUSY flag is reset or, alternatively, for a timeout - condition.*/ - while (true) { - osalSysLock(); - - /* If the bus is not busy then the operation can continue, note, the - loop is exited in the locked state.*/ -// if (!(i2cp->i2c->ISR & I2C_ISR_BUSY) && !(i2cp->i2c->CR1 & I2C_CR1_STOP)) - if (!(i2cp->i2c->ISR & I2C_ISR_BUSY)) - break; - - /* If the system time went outside the allowed window then a timeout - condition is returned.*/ - if (!osalOsIsTimeWithinX(osalOsGetSystemTimeX(), start, end)) - return MSG_TIMEOUT; - - osalSysUnlock(); - // TODO: Should we relinquish thread here for a while? - chThdSleepMilliseconds(2); - } - i2cp->mode = i2cIsMaster; // We can set master mode now - return MSG_OK; -} - - -/** - * Start a master mode transaction - * - * Note: may need adjustment to work in multi-master mode as well - see i2c_lld_safety_timeout() - */ -static msg_t startMasterAction(I2CDriver *i2cp, systime_t timeout) -{ -#if STM32_I2C_USE_DMA == TRUE -#else -#endif - msg_t msg; - - /* Starts the operation.*/ - i2cp->i2c->CR2 |= I2C_CR2_START; - - /* Waits for the operation completion or a timeout.*/ - msg = osalThreadSuspendTimeoutS(&i2cp->thread, timeout); - - /* In case of a software timeout a STOP is sent as an extreme attempt - to release the bus.*/ - if (msg == MSG_TIMEOUT) { - i2cp->i2c->CR2 |= I2C_CR2_STOP; - i2cp->mode = i2cIdle; // TODO: Is this enough? - } - return msg; -} - - -/** - * @brief Receives data via the I2C bus as master. - * @details Number of receiving bytes must be more than 1 on STM32F1x. This is - * hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { -// I2C_TypeDef *dp = i2cp->i2c; - - osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection - - -#if STM32_I2C_USE_DMA == TRUE - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); -#endif - // Always set up the receive buffer in case callbacks enabled - i2cp->rxptr = rxbuf; - i2cp->rxbytes = rxbytes; - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Setting up the peripheral.*/ - i2c_lld_setup_rx_transfer(i2cp); - - i2cStartReceive(i2cp); - i2cp->mode = i2cMasterRxing; - - return startMasterAction(i2cp, timeout); -} - - - -/** - * @brief Transmits data via the I2C bus as master. - * @details Number of receiving bytes must be 0 or more than 1 on STM32F1x. - * This is hardware restriction. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address - * @param[in] txbuf pointer to the transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to the receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. After a - * timeout the driver must be stopped and restarted - * because the bus is in an uncertain state. - * - * @notapi - */ -msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout) { - I2C_TypeDef *dp = i2cp->i2c; - - osalDbgAssert((i2cp->thread==NULL), "#3 - reentry"); - - /* Resetting error flags for this transfer.*/ - i2cp->errors = I2C_NO_ERROR; - - /* Releases the lock from high level driver.*/ - osalSysUnlock(); - - calcMasterTimeout(i2cp); // This has to be done before we change the state of the connection - - -#if STM32_I2C_USE_DMA == TRUE - /* TX DMA setup.*/ - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, txbuf); - dmaStreamSetTransactionSize(i2cp->dmatx, txbytes); - - /* RX DMA setup, note, rxbytes can be zero but we write the value anyway.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxbuf); - dmaStreamSetTransactionSize(i2cp->dmarx, rxbytes); -#else - i2cp->txptr = txbuf; - i2cp->txbytes = txbytes; -#endif - // Always set up the receive buffer in case callbacks enabled - i2cp->rxptr = rxbuf; - i2cp->rxbytes = rxbytes; - - /* Setting up the slave address.*/ - i2c_lld_set_address(i2cp, addr); - - /* Preparing the transfer.*/ - i2c_lld_setup_tx_transfer(i2cp); - -#if STM32_I2C_USE_DMA == TRUE - /* Enabling TX DMA.*/ - dmaStreamEnable(i2cp->dmatx); - - /* Transfer complete interrupt enabled.*/ - dp->CR1 |= I2C_CR1_TCIE; -#else - /* Transfer complete and TX interrupts enabled.*/ - dp->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; -#endif - - i2cp->mode = i2cMasterTxing; - - return startMasterAction(i2cp, timeout); -} -#endif /* #if HAL_USE_I2C_MASTER == TRUE */ - - - - -#if HAL_USE_I2C_SLAVE -/************************************************************************/ -/* SLAVE MODE SUPPORT */ -/************************************************************************/ - -/** - * @brief Reconfigure I2C channel to respond to passed address - * in addition to those previously made active - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C network address - * - * @return Length of message OR the type of event received - * @retval I2C_OK Success - * @retval I2C_ERROR Cannot match address in addition of those already - * - * @details MatchAddress calls are cumulative. - * Specify address zero to match I2C "all call" - * Does not support 10-bit addressing. - * Number of supported addresses is chip-dependent - 2+general call on I2CV2 - * Address masking capabilities of OAR2 not supported - * - * @notapi - **/ -msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - I2C_TypeDef *dp = i2cp->i2c; - if (i2cadr == 0) { - dp->CR1 |= I2C_CR1_GCEN; // Just enable General Call - dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled - } - else - { - uint32_t adr = i2cadr << 1; - if ((dp->OAR1 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR1 - if ((dp->OAR2 & (0x7f<<1)) == adr) { return I2C_OK; }; // Already matched in OAR2 - - if (!(dp->OAR1 & I2C_OAR1_OA1EN)) { - dp->OAR1 = adr | I2C_OAR1_OA1EN; // OAR1 previously unused - dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled - } - else - if (!(dp->OAR2 & I2C_OAR2_OA2EN)) { - dp->OAR2 = adr | I2C_OAR2_OA2EN; // OAR2 previously unused - dp->CR1 |= I2C_CR1_ADDRIE; // Make sure address match interrupt enabled - } - else - return I2C_ERROR; /* cannot add this address to set of those matched */ - } - return I2C_OK; -} - - -/** - * @brief Reconfigure I2C channel to no longer match specified address - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C network address - * - * @details A message being transferred that has already matched the - * specified address will continue being processed. - * Requests to unmatch an address that is not currently being matched - * are ignored. - * Does not support 10-bit addressing. - * - * @notapi - **/ -void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - I2C_TypeDef *dp = i2cp->i2c; - if (i2cadr == 0) { - dp->CR1 &= (uint32_t)~I2C_CR1_GCEN; // Disable General Call - } - else { - uint32_t adr = i2cadr << 1; - if ((dp->OAR1 & (0x7f<<1)) == adr) { - // Matched in OAR1 - dp->OAR1 &= ~I2C_OAR1_OA1EN; // Just disable - OAR2 is a bit different - } - else - if ((dp->OAR2 & I2C_OAR2_OA2EN) && (dp->OAR2 & (0x7f<<1)) == adr) - dp->OAR2 &= ~I2C_OAR2_OA2EN; - } - if (!((dp->CR1 & (uint32_t)I2C_CR1_GCEN) || (dp->OAR1 & I2C_OAR1_OA1EN) || (dp->OAR2 & I2C_OAR2_OA2EN))) { - dp->CR1 &= (uint32_t)~(I2C_CR1_ADDRIE); // Disable Address match interrupts if nothing can generate them (strictly necessary??) - } -} - - -/** - * @brief Reconfigure I2C channel to no longer match any address - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details Causes all subsequent messages to be ignored. - * A message being transferred that has already matched a - * slave address will continue being processed. - * - * @notapi - **/ -void i2c_lld_unmatchAll(I2CDriver *i2cp) -{ - I2C_TypeDef *dp = i2cp->i2c; - dp->CR1 &= (uint32_t)~(I2C_CR1_GCEN | I2C_CR1_ADDRIE); // Disable General Call - dp->OAR1 = 0; - dp->OAR2 = 0; -} - - -/** - * @brief Configure callbacks & buffers to receive messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent received messages - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @notapi - */ -void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) -{ - osalDbgCheck((rxMsg && rxMsg->size <= 0xffff)); - qEvt(0x82, rxMsg->size); - i2cp->slaveNextRx = rxMsg; - if (i2cp->mode == i2cLockedRxing && rxMsg->body && rxMsg->size) { - /* We can receive now! */ - i2cp->slaveRx = rxMsg; - /* slave RX DMA setup */ -#if STM32_I2C_USE_DMA == TRUE - /* RX DMA setup.*/ - dmaStreamSetMode(i2cp->dmarx, i2cp->rxdmamode); - dmaStreamSetMemory0(i2cp->dmarx, rxMsg->body); - dmaStreamSetTransactionSize(i2cp->dmarx, rxMsg->size); -#else - i2cp->rxptr = rxMsg->body; - i2cp->rxbytes = rxMsg->size; -#endif - - i2cp->mode = i2cSlaveRxing; - i2c_lld_setup_rx_transfer(i2cp); // Set up the transfer - qEvt(0x83, 0); - i2cStartReceive(i2cp); - i2cp->i2c->CR1 &= ~I2C_CR1_SBC; // Not needed with receive - i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now - } -} - - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @notapi - */ -void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) -{ - osalDbgCheck((replyMsg && replyMsg->size <= 0xffff)); - qEvt(0x80, replyMsg->size); - i2cp->slaveNextReply = replyMsg; - if (i2cp->mode == i2cLockedReplying && replyMsg->body && replyMsg->size) - { - i2cp->slaveReply = replyMsg; - /* slave TX setup -- we can reply now! */ - #if STM32_I2C_USE_DMA == TRUE - dmaStreamSetMode(i2cp->dmatx, i2cp->txdmamode); - dmaStreamSetMemory0(i2cp->dmatx, replyMsg->body); - dmaStreamSetTransactionSize(i2cp->dmatx, replyMsg->size); - i2cp->mode = i2cSlaveReplying; - /* Start transmission */ - i2c_lld_setup_tx_transfer(i2cp); - - /* Enabling TX DMA.*/ - dmaStreamEnable(i2cp->dmatx); - - /* Transfer complete interrupt enabled.*/ - i2cp->i2c->CR1 |= I2C_CR1_TCIE; - #else - /* Start transmission */ - i2cp->txptr = replyMsg->body; - i2cp->txbytes = replyMsg->size; - i2c_lld_setup_tx_transfer(i2cp); - /* Transfer complete and TX character interrupts enabled.*/ - i2cp->i2c->CR1 |= I2C_CR1_TCIE | I2C_CR1_TXIE; - #endif - qEvt(0x81, 0); - i2cp->i2c->CR1 |= I2C_CR1_SBC; // Need this to enable byte counter in transmit mode - i2cp->i2c->ICR = I2C_ISR_ADDR; // We can release the clock stretch now - } -} - -#endif /* HAL_USE_I2C_SLAVE */ - - -#endif /* HAL_USE_I2C */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h b/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h deleted file mode 100644 index c4df28fb2e..0000000000 --- a/drivers/chibios/i2cslave/I2Cv2/hal_i2c_lld.h +++ /dev/null @@ -1,806 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. I2C Slave API for Chibios V2.x V1 I2C originally contributed - by Brent Roman (brent@mbari.org), ported to Chibios V3, V2 I2C by steved - */ - -/** - * @file STM32/I2Cv2/i2c_lld.h - * @brief STM32 I2C subsystem low level driver header. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_LLD_H_ -#define _I2C_LLD_H_ - -#if HAL_USE_I2C || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name TIMINGR register definitions - * @{ - */ -#define STM32_TIMINGR_PRESC_MASK (15U << 28) -#define STM32_TIMINGR_PRESC(n) ((n) << 28) -#define STM32_TIMINGR_SCLDEL_MASK (15U << 20) -#define STM32_TIMINGR_SCLDEL(n) ((n) << 20) -#define STM32_TIMINGR_SDADEL_MASK (15U << 16) -#define STM32_TIMINGR_SDADEL(n) ((n) << 16) -#define STM32_TIMINGR_SCLH_MASK (255U << 8) -#define STM32_TIMINGR_SCLH(n) ((n) << 8) -#define STM32_TIMINGR_SCLL_MASK (255U << 0) -#define STM32_TIMINGR_SCLL(n) ((n) << 0) -/** @} */ - - -/** - * Driver clears down tidily after a timeout - */ -#define I2C_SUPPORT_BUS_CLEAR TRUE - -/** - * @brief Invalid I2C bus address - */ -#define i2cInvalidAdr ((i2caddr_t) -1) - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @name Configuration options - * @{ - */ -/** - * @brief I2C1 driver enable switch. - * @details If set to @p TRUE the support for I2C1 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C1) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C1 FALSE -#endif - -/** - * @brief I2C2 driver enable switch. - * @details If set to @p TRUE the support for I2C2 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C2) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C2 FALSE -#endif - -/** - * @brief I2C3 driver enable switch. - * @details If set to @p TRUE the support for I2C3 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C3) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C3 FALSE -#endif - -/** - * @brief I2C4 driver enable switch. - * @details If set to @p TRUE the support for I2C4 is included. - * @note The default is @p FALSE. - */ -#if !defined(STM32_I2C_USE_I2C4) || defined(__DOXYGEN__) -#define STM32_I2C_USE_I2C4 FALSE -#endif - - -/** - * @brief Enables support for I2C slave mode operation - */ -#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) -#define HAL_USE_I2C_SLAVE FALSE -#endif - - -/** - * @brief Turns on some debugging options - */ -#if !defined(STM32_I2C_DEBUG_ENABLE) || defined(__DOXYGEN__) -#define STM32_I2C_DEBUG_ENABLE FALSE -#endif - - -/** - * @brief I2C timeout on busy condition in milliseconds. - */ -#if !defined(STM32_I2C_BUSY_TIMEOUT) || defined(__DOXYGEN__) -#define STM32_I2C_BUSY_TIMEOUT 50 -#endif - -/** - * @brief I2C1 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C1_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C2 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C2_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C3 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C3_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_IRQ_PRIORITY 10 -#endif - -/** - * @brief I2C4 interrupt priority level setting. - */ -#if !defined(STM32_I2C_I2C4_IRQ_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_IRQ_PRIORITY 10 -#endif - -/** - * @brief DMA use switch. - */ -#if !defined(STM32_I2C_USE_DMA) || defined(__DOXYGEN__) -#define STM32_I2C_USE_DMA TRUE -#endif - -/** - * @brief I2C1 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C1_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C1_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C2 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C2_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C2_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C3 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C3_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C3_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C4 DMA priority (0..3|lowest..highest). - * @note The priority level is used for both the TX and RX DMA streams but - * because of the streams ordering the RX stream has always priority - * over the TX stream. - */ -#if !defined(STM32_I2C_I2C4_DMA_PRIORITY) || defined(__DOXYGEN__) -#define STM32_I2C_I2C4_DMA_PRIORITY 1 -#endif - -/** - * @brief I2C DMA error hook. - * @note The default action for DMA errors is a system halt because DMA - * error can only happen because programming errors. - */ -#if !defined(STM32_I2C_DMA_ERROR_HOOK) || defined(__DOXYGEN__) -#define STM32_I2C_DMA_ERROR_HOOK(i2cp) osalSysHalt("DMA failure") -#endif -/** @} */ - - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -/** @brief error checks */ -#if STM32_I2C_USE_I2C1 && !STM32_HAS_I2C1 -#error "I2C1 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C2 && !STM32_HAS_I2C2 -#error "I2C2 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C3 && !STM32_HAS_I2C3 -#error "I2C3 not present in the selected device" -#endif - -#if STM32_I2C_USE_I2C4 && !STM32_HAS_I2C4 -#error "I2C4 not present in the selected device" -#endif - -#if !STM32_I2C_USE_I2C1 && !STM32_I2C_USE_I2C2 && !STM32_I2C_USE_I2C3 && \ - !STM32_I2C_USE_I2C4 -#error "I2C driver activated but no I2C peripheral assigned" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C1_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C2_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C3_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !OSAL_IRQ_IS_VALID_PRIORITY(STM32_I2C_I2C4_IRQ_PRIORITY) -#error "Invalid IRQ priority assigned to I2C4" -#endif - -#if STM32_I2C_USE_DMA == TRUE -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C1_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C1" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C2_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C2" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C3_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C3" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_PRIORITY(STM32_I2C_I2C4_DMA_PRIORITY) -#error "Invalid DMA priority assigned to I2C4" -#endif - -/* The following checks are only required when there is a DMA able to - reassign streams to different channels.*/ -#if STM32_ADVANCED_DMA -/* Check on the presence of the DMA streams settings in mcuconf.h.*/ -#if STM32_I2C_USE_I2C1 && (!defined(STM32_I2C_I2C1_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C1_TX_DMA_STREAM)) -#error "I2C1 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C2 && (!defined(STM32_I2C_I2C2_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C2_TX_DMA_STREAM)) -#error "I2C2 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C3 && (!defined(STM32_I2C_I2C3_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C3_TX_DMA_STREAM)) -#error "I2C3 DMA streams not defined" -#endif - -#if STM32_I2C_USE_I2C4 && (!defined(STM32_I2C_I2C4_RX_DMA_STREAM) || \ - !defined(STM32_I2C_I2C4_TX_DMA_STREAM)) -#error "I2C4 DMA streams not defined" -#endif - -/* Check on the validity of the assigned DMA channels.*/ -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_RX_DMA_STREAM, \ - STM32_I2C1_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 RX" -#endif - -#if STM32_I2C_USE_I2C1 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C1_TX_DMA_STREAM, \ - STM32_I2C1_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C1 TX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_RX_DMA_STREAM, \ - STM32_I2C2_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 RX" -#endif - -#if STM32_I2C_USE_I2C2 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C2_TX_DMA_STREAM, \ - STM32_I2C2_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C2 TX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_RX_DMA_STREAM, \ - STM32_I2C3_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 RX" -#endif - -#if STM32_I2C_USE_I2C3 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C3_TX_DMA_STREAM, \ - STM32_I2C3_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C3 TX" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_RX_DMA_STREAM, \ - STM32_I2C4_RX_DMA_MSK) -#error "invalid DMA stream associated to I2C4 RX" -#endif - -#if STM32_I2C_USE_I2C4 && \ - !STM32_DMA_IS_VALID_ID(STM32_I2C_I2C4_TX_DMA_STREAM, \ - STM32_I2C4_TX_DMA_MSK) -#error "invalid DMA stream associated to I2C4 TX" -#endif -#endif /* STM32_ADVANCED_DMA */ - -#if !defined(STM32_DMA_REQUIRED) -#define STM32_DMA_REQUIRED -#endif -#endif /* STM32_I2C_USE_DMA == TRUE */ - - - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Type representing an I2C address. - * @note For a 7-bit address, this takes values 0..0x7f, which are then - * shifted left one and the R/W bit added when required - */ -typedef uint16_t i2caddr_t; - -/** - * @brief Type of I2C driver condition flags. - */ -typedef uint32_t i2cflags_t; - - -/** - * @brief Type of a structure representing an I2C driver. - */ -typedef struct I2CDriver I2CDriver; - - -/** - * @brief Supported modes for the I2C bus. - * @note Currently not used; retained for future enhancements - */ -typedef enum { - OPMODE_I2C = 1, - OPMODE_SMBUS_DEVICE = 2, - OPMODE_SMBUS_HOST = 3, -} i2copmode_t; - - - -/** - * @brief Character received I2C notification callback type. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] c received character - * - * @param[out] Return 0 if transfer to continue. 1 if transfer to be stopped - * - * @note Use only in master mode, to stop a read transaction - * once a particular character (or sequence of characters) has been received - */ -typedef uint8_t (*i2cccb_t)(I2CDriver *i2cp, uint16_t c); - - - -/** - * @brief Type of I2C driver configuration structure. - */ -typedef struct { - /** - * @brief TIMINGR register initialization. - * @note Refer to the STM32 reference manual, the values are affected - * by the system clock settings in mcuconf.h. - */ - uint32_t timingr; - /** - * @brief CR1 register initialization. - * @note Leave to zero unless you know what you are doing. - */ - uint32_t cr1; - /** - * @brief CR2 register initialization. - * @note Leave at zero except in special circumstances - most bits controlled via API - */ - uint32_t cr2; - /** - * @brief Character received callback. Return 0 if transfer to continue. 1 if transfer to be stopped - * @note Use only in master mode. Set to NULL if not used. - */ - i2cccb_t rxchar_cb; -} I2CConfig; - - - - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -typedef struct I2CSlaveMsg I2CSlaveMsg; - -/* - returns the current I2C slave message receive configuration -*/ -I2CSlaveMsg *i2cSlaveGetReceiveMsg(I2CDriver *i2cp); - - -/* - returns the current I2C slave message reply configuration -*/ -I2CSlaveMsg *i2cSlaveGetReplyMsg(I2CDriver *i2cp); - - -/* - I2C Slave Message Call Back. - Invoked from interrupt context just after - the last byte of the message is transferred or slaveAdr is matched. - - Use i2cSlaveReceiveMsg() or i2cSlaveReplyMsg() to access - the relevant message handling configuration -*/ -typedef void I2CSlaveMsgCB(I2CDriver *i2cp); - - -/* - I2CSlaveMsg message handling configurations are normally - stored in read-only memory. - They describe either a buffer to contain incoming messages from - a bus master and associated callback functions, or one - preloaded with an outgoing reply to a read request and its callbacks. -*/ - -struct I2CSlaveMsg { - size_t size; /* sizeof(body) -- zero if master must wait */ - uint8_t *body; /* message contents -- or NULL if master must wait */ - I2CSlaveMsgCB *adrMatched; /* invoked when slave address matches */ - I2CSlaveMsgCB *processMsg; /* invoked after message is transferred */ - I2CSlaveMsgCB *exception; /* invoked if error or timeout during transfer */ -}; - - -/* - dummy callback -- placeholder to ignore event -*/ -I2CSlaveMsgCB I2CSlaveDummyCB; - - /* lock bus on receive or reply -- force master to wait */ -extern const I2CSlaveMsg I2CSlaveLockOnMsg; - -#endif /* HAL_USE_I2C_SLAVE */ - - - - -/** - * @brief Structure representing an I2C driver. - */ -struct I2CDriver { - /** - * @brief Driver state. - */ - i2cstate_t state; - /** - * @brief Current configuration data. - */ - const I2CConfig *config; - /** - * @brief Error flags. - */ - i2cflags_t errors; -#if I2C_USE_MUTUAL_EXCLUSION || defined(__DOXYGEN__) - mutex_t mutex; -#endif /* I2C_USE_MUTUAL_EXCLUSION */ -#if defined(I2C_DRIVER_EXT_FIELDS) - I2C_DRIVER_EXT_FIELDS -#endif - /* End of the mandatory fields.*/ - /** - * @brief Thread waiting for I/O completion. - */ - thread_reference_t thread; - - -#if (STM32_I2C_USE_DMA == TRUE) || defined(__DOXYGEN__) - /** - * @brief RX DMA mode bit mask. - */ - uint32_t rxdmamode; - /** - * @brief TX DMA mode bit mask. - */ - uint32_t txdmamode; - /** - * @brief Receive DMA channel. - */ - const stm32_dma_stream_t *dmarx; - /** - * @brief Transmit DMA channel. - */ - const stm32_dma_stream_t *dmatx; -#else /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the next TX buffer location. - */ - const uint8_t *txptr; - /** - * @brief Number of bytes in TX phase. - */ - size_t txbytes; -#endif /* STM32_I2C_USE_DMA == FALSE */ - /** - * @brief Pointer to the next RX buffer location. - */ - uint8_t *rxptr; - /** - * @brief Number of bytes in RX phase. - */ - size_t rxbytes; - /** - * @brief Pointer to the I2Cx registers block. - */ - I2C_TypeDef *i2c; - - - /** - * @brief low level I2C interface / protocol state - */ - enum i2cMode { - i2cStopped = 0, /* Port not initialised, or not started */ - i2cIdle=1, /* awaiting address or inactive */ - i2cSlaveRxing, /* receiving message */ - i2cLockedRxing, /* stretching clock before receiving message - Rx buffer might be full */ - i2cSlaveReplying, /* replying to query (transmitting, slave mode) */ - i2cLockedReplying, /* stretching clock before replying to query (no response available from main code) */ - - i2cIsMaster=0x11, /* sent start bit (mastering bus) */ - i2cMasterStarted, /* repeated start after write */ - i2cMasterSelecting, /* sending slave address */ - i2cMasterRxing, /* receiving reply from slave */ - i2cMasterTxing /* sending message to slave */ - } mode; - -#if HAL_USE_I2C_LOCK || HAL_USE_I2C_SLAVE - /** - * @brief I2C transaction timer - * @note USed for slave mode, lock - */ - virtual_timer_t timer; -#endif -#if HAL_USE_I2C_LOCK - /** - * @brief I2C bus lock duration - */ - systime_t lockDuration; -#endif -#if HAL_USE_I2C_SLAVE - /* additional fields to support I2C slave transactions */ - - /** - * @brief slave address of message being processed - */ - i2caddr_t targetAdr; - /** - * @brief Error Mask for last slave message - */ - i2cflags_t slaveErrors; - /** - * @brief Length of most recently transferred slave message - */ - size_t slaveBytes; - /** - * @brief Maximum # of ticks slave may stretch the I2C clock - */ - systime_t slaveTimeout; - /** - * @brief Pointer to slave message reception handler - */ - const I2CSlaveMsg *slaveRx; - /** - * @brief Pointer to slave message Reply (transmit) handler - * - * @note This is the currently active/just completed reply - */ - const I2CSlaveMsg *slaveReply; - /** - * @brief Pointer to handler for next slave received message - */ - const I2CSlaveMsg *slaveNextRx; - /** - * @brief Pointer to handler for next slave reply (transmit) message - * - * @note This is used for a reply if no message received first - */ - const I2CSlaveMsg *slaveNextReply; -#endif -}; - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Get errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_errors(i2cp) ((i2cp)->errors) - - - -#if HAL_USE_I2C_LOCK -/** - * @brief Unlock I2C bus after the end of the next transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - **/ -#define i2c_lld_unlock(i2cp) (i2cp->lockDuration = TIME_IMMEDIATE) -#endif - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ -/** - * @brief Get slave errors from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveErrors(i2cp) ((i2cp)->slaveErrors) - -/** - * @brief Get slave message bytes transferred from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveBytes(i2cp) ((i2cp)->slaveBytes) - - -/** - * @brief Get slave timeout in ticks from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveTimeout(i2cp) ((i2cp)->slaveTimeout) - -/** - * @brief Set slave timeout in ticks for I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_set_slaveTimeout(i2cp,ticks) ((i2cp)->slaveTimeout=(ticks)) - -/** - * @brief Get slave target address from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveTargetAdr(i2cp) ((i2cp)->targetAdr) - -/** - * @brief Get slave receive message descriptor from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveReceive(i2cp) ((i2cp)->slaveNextRx) - -/** - * @brief Get slave reply message descriptor from I2C driver. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define i2c_lld_get_slaveReply(i2cp) ((i2cp)->slaveNextReply) - - -#endif - - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#if !defined(__DOXYGEN__) -#if STM32_I2C_USE_I2C1 -extern I2CDriver I2CD1; -#endif - -#if STM32_I2C_USE_I2C2 -extern I2CDriver I2CD2; -#endif - -#if STM32_I2C_USE_I2C3 -extern I2CDriver I2CD3; -#endif - -#if STM32_I2C_USE_I2C4 -extern I2CDriver I2CD4; -#endif - -#endif /* !defined(__DOXYGEN__) */ - -#ifdef __cplusplus -extern "C" { -#endif - void i2c_lld_init(void); - void i2c_lld_start(I2CDriver *i2cp); - void i2c_lld_stop(I2CDriver *i2cp); - msg_t i2c_lld_master_transmit_timeout(I2CDriver *i2cp, i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2c_lld_master_receive_timeout(I2CDriver *i2cp, i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - -#if HAL_USE_I2C_LOCK /* I2C slave mode support */ - void i2c_lld_lock(I2CDriver *i2cp, systime_t lockDuration); -#endif -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - msg_t i2c_lld_matchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - void i2c_lld_unmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - void i2c_lld_unmatchAll(I2CDriver *i2cp); - void i2c_lld_slaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); - void i2c_lld_slaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); - -#if STM32_I2C_DEBUG_ENABLE - void i2cPrintQ(BaseSequentialStream *chp); // Debugging routine -#endif /* STM32_I2C_DEBUG_ENABLE */ - -#endif /* HAL_USE_I2C_SLAVE */ - -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C */ - -#endif /* _I2C_LLD_H_ */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2c.c b/drivers/chibios/i2cslave/hal_i2c.c deleted file mode 100644 index 5e4e6438c2..0000000000 --- a/drivers/chibios/i2cslave/hal_i2c.c +++ /dev/null @@ -1,480 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file i2c.c - * @brief I2C Driver code. - * - * @addtogroup I2C - * @{ - */ -#include "hal.h" - -#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver local definitions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported variables. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local variables and types. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver local functions. */ -/*===========================================================================*/ - -/*===========================================================================*/ -/* Driver exported functions. */ -/*===========================================================================*/ - -/** - * @brief I2C Driver initialization. - * @note This function is implicitly invoked by @p halInit(), there is - * no need to explicitly initialize the driver. - * - * @init - */ -void i2cInit(void) { - - i2c_lld_init(); -} - -/** - * @brief Initializes the standard part of a @p I2CDriver structure. - * - * @param[out] i2cp pointer to the @p I2CDriver object - * - * @init - */ -void i2cObjectInit(I2CDriver *i2cp) { - - i2cp->state = I2C_STOP; - i2cp->config = NULL; - -#if I2C_USE_MUTUAL_EXCLUSION == TRUE -#if CH_CFG_USE_MUTEXES - osalMutexObjectInit(&i2cp->mutex); -#else - osalSemObjectInit(&i2cp->semaphore, 1); -#endif /* CH_CFG_USE_MUTEXES */ -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - -#if defined(I2C_DRIVER_EXT_INIT_HOOK) - I2C_DRIVER_EXT_INIT_HOOK(i2cp); -#endif -} - -/** - * @brief Configures and activates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] config pointer to the @p I2CConfig object - * - * @api - */ -void i2cStart(I2CDriver *i2cp, const I2CConfig *config) { - - osalDbgCheck((i2cp != NULL) && (config != NULL)); - osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), "invalid state"); - - osalSysLock(); - i2cp->config = config; - i2c_lld_start(i2cp); - i2cp->state = I2C_READY; - osalSysUnlock(); -} - -/** - * @brief Deactivates the I2C peripheral. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cStop(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - osalDbgAssert((i2cp->state == I2C_STOP) || (i2cp->state == I2C_READY) || - (i2cp->state == I2C_LOCKED), "invalid state"); - - osalSysLock(); - i2c_lld_stop(i2cp); - i2cp->state = I2C_STOP; - osalSysUnlock(); -} - -/** - * @brief Returns the errors mask associated to the previous operation. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @return The errors mask. - * - * @api - */ -i2cflags_t i2cGetErrors(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - - return i2c_lld_get_errors(i2cp); -} - -/** - * @brief Sends data via the I2C bus. - * @details Function designed to realize "read-through-write" transfer - * paradigm. If you want transmit data without any further read, - * than set @b rxbytes field to 0. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address (7 bits) without R/W bit - * @param[in] txbuf pointer to transmit buffer - * @param[in] txbytes number of bytes to be transmitted - * @param[out] rxbuf pointer to receive buffer - * @param[in] rxbytes number of bytes to be received, set it to 0 if - * you want transmit only - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, - i2caddr_t addr, - const uint8_t *txbuf, - size_t txbytes, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout) { - msg_t rdymsg; - - osalDbgCheck((i2cp != NULL) && (addr != 0U) && - (txbytes > 0U) && (txbuf != NULL) && - ((rxbytes == 0U) || ((rxbytes > 0U) && (rxbuf != NULL))) && - (timeout != TIME_IMMEDIATE)); - - osalDbgAssert(i2cp->state == I2C_READY, "not ready"); - - osalSysLock(); - i2cp->errors = I2C_NO_ERROR; - i2cp->state = I2C_ACTIVE_TX; - rdymsg = i2c_lld_master_transmit_timeout(i2cp, addr, txbuf, txbytes, - rxbuf, rxbytes, timeout); - if (rdymsg == MSG_TIMEOUT) { - i2cp->state = I2C_LOCKED; - } - else { - i2cp->state = I2C_READY; - } - osalSysUnlock(); - return rdymsg; -} - -/** - * @brief Receives data from the I2C bus. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] addr slave device address (7 bits) without R/W bit - * @param[out] rxbuf pointer to receive buffer - * @param[in] rxbytes number of bytes to be received - * @param[in] timeout the number of ticks before the operation timeouts, - * the following special values are allowed: - * - @a TIME_INFINITE no timeout. - * . - * - * @return The operation status. - * @retval MSG_OK if the function succeeded. - * @retval MSG_RESET if one or more I2C errors occurred, the errors can - * be retrieved using @p i2cGetErrors(). - * @retval MSG_TIMEOUT if a timeout occurred before operation end. - * - * @api - */ -msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, - i2caddr_t addr, - uint8_t *rxbuf, - size_t rxbytes, - systime_t timeout){ - - msg_t rdymsg; - - osalDbgCheck((i2cp != NULL) && (addr != 0U) && - (rxbytes > 0U) && (rxbuf != NULL) && - (timeout != TIME_IMMEDIATE)); - - osalDbgAssert(i2cp->state == I2C_READY, "not ready"); - - osalSysLock(); - i2cp->errors = I2C_NO_ERROR; - i2cp->state = I2C_ACTIVE_RX; - rdymsg = i2c_lld_master_receive_timeout(i2cp, addr, rxbuf, rxbytes, timeout); - if (rdymsg == MSG_TIMEOUT) { - i2cp->state = I2C_LOCKED; - } - else { - i2cp->state = I2C_READY; - } - osalSysUnlock(); - return rdymsg; -} - - -#if HAL_USE_I2C_LOCK /* I2C slave mode support */ - -/** - * @brief Lock I2C bus at the beginning of the next message sent - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] lockDuration max number of ticks to hold bus locked - * - @a TIME_INFINITE no timeout. - * - @a TIME_IMMEDIATE unlock the bus immediately - * . - * - * @api - */ -void i2cLock(I2CDriver *i2cp, systime_t lockDuration) -{ - chDbgCheck((i2cp != NULL), "i2cLock"); - chSysLock(); - i2c_lld_lock(i2cp, lockDuration); - chSysUnlock(); -} - -/** - * @brief Unlock I2C bus after the end of the next transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - **/ -void i2cUnlock(I2CDriver *i2cp) -{ - chDbgCheck((i2cp != NULL), "i2cUnlock"); - chSysLock(); - i2c_lld_unlock(i2cp); - chSysUnlock(); -} -#endif - - -#if HAL_USE_I2C_SLAVE /* I2C slave mode support */ - -/** - * @brief Reconfigure I2C channel to respond to indicated address - * in addition to those already matched - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C network address - * - * @return Length of message OR the type of event received - * @retval I2C_OK Success - * @retval I2C_ERROR Cannot match address in addition of those already - * - * @details MatchAddress calls are cumulative. - * Specify address zero to match I2C "all call" - * Does not support 10-bit addressing. - * - * @api - **/ -msg_t i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - osalDbgCheck((i2cp != NULL)); - chSysLock(); - msg_t result = i2c_lld_matchAddress(i2cp, i2cadr); - chSysUnlock(); - return result; -} - - -/** - * @brief Configure to ignore messages directed to the given i2cadr - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C bus address - * - @a 0 matches "all call" - * . - * @details A message being transferred that has already matched the - * specified address will continue being processed. - * Requests to unmatch an address that is not currently being matched - * are ignored. - * - * @api - */ -void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - osalDbgCheck((i2cp != NULL)); - chSysLock(); - i2c_lld_unmatchAddress(i2cp, i2cadr); - chSysUnlock(); -} - - -/** - * @brief Reconfigure I2C channel to no longer match any address - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details Causes all subsequent messages to be ignored. - * A message being transferred that has already matched a - * slave address will continue being processed. - * - * @api - **/ -void i2cUnmatchAll(I2CDriver *i2cp) -{ - osalDbgCheck((i2cp != NULL)); - chSysLock(); - i2c_lld_unmatchAll(i2cp); - chSysUnlock(); -} - - -/** - * @brief Configure callbacks & buffers for message reception & query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Must be called from a thread - * Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveConfigure(I2CDriver *i2cp, - const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg) -{ - osalDbgCheck((i2cp != NULL)); - chSysLock(); - i2c_lld_slaveReceive(i2cp, rxMsg); - i2c_lld_slaveReply(i2cp, replyMsg); - chSysUnlock(); -} - - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) -{ - osalDbgCheck((i2cp != NULL && rxMsg != NULL)); - chSysLock(); - i2c_lld_slaveReceive(i2cp, rxMsg); - chSysUnlock(); -} - - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) -{ - osalDbgCheck((i2cp != NULL && replyMsg != NULL)); - chSysLock(); - i2c_lld_slaveReply(i2cp, replyMsg); - chSysUnlock(); -} - -#endif /* HAL_USE_I2C_SLAVE */ - - -#if I2C_USE_MUTUAL_EXCLUSION == TRUE || defined(__DOXYGEN__) -/** - * @brief Gains exclusive access to the I2C bus. - * @details This function tries to gain ownership to the I2C bus, if the bus - * is already being used then the invoking thread is queued. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cAcquireBus(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - -#if CH_CFG_USE_MUTEXES - osalMutexLock(&i2cp->mutex); -#elif CH_CFG_USE_SEMAPHORES - osalSemWait(&i2cp->semaphore); -#endif /* CH_CFG_USE_MUTEXES */ -} - - -/** - * @brief Releases exclusive access to the I2C bus. - * @pre In order to use this function the option @p I2C_USE_MUTUAL_EXCLUSION - * must be enabled. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @api - */ -void i2cReleaseBus(I2CDriver *i2cp) { - - osalDbgCheck(i2cp != NULL); - -#if CH_CFG_USE_MUTEXES - osalMutexUnlock(&i2cp->mutex); -#elif CH_CFG_USE_SEMAPHORES - osalSemSignal(&i2cp->semaphore); -#endif /* CH_CFG_USE_MUTEXES */ -} - -#endif /* I2C_USE_MUTUAL_EXCLUSION == TRUE */ - -#endif /* HAL_USE_I2C == TRUE */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2c.h b/drivers/chibios/i2cslave/hal_i2c.h deleted file mode 100644 index 325941b953..0000000000 --- a/drivers/chibios/i2cslave/hal_i2c.h +++ /dev/null @@ -1,212 +0,0 @@ -/* - ChibiOS - Copyright (C) 2006..2015 Giovanni Di Sirio - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. -*/ -/* - Concepts and parts of this file have been contributed by Uladzimir Pylinsky - aka barthess. - */ - -/** - * @file i2c.h - * @brief I2C Driver macros and structures. - * - * @addtogroup I2C - * @{ - */ - -#ifndef _I2C_H_ -#define _I2C_H_ - -#if (HAL_USE_I2C == TRUE) || defined(__DOXYGEN__) - -/*===========================================================================*/ -/* Driver constants. */ -/*===========================================================================*/ - -/** - * @name I2C bus error conditions - * @{ - */ -#define I2C_NO_ERROR 0x00 /**< @brief No error. */ -#define I2C_BUS_ERROR 0x01 /**< @brief Bus Error. */ -#define I2C_ARBITRATION_LOST 0x02 /**< @brief Arbitration Lost. */ -#define I2C_ACK_FAILURE 0x04 /**< @brief Acknowledge Failure. */ -#define I2C_OVERRUN 0x08 /**< @brief Overrun/Underrun. */ -#define I2C_PEC_ERROR 0x10 /**< @brief PEC Error in - reception. */ -#define I2C_TIMEOUT 0x20 /**< @brief Hardware timeout. */ -#define I2C_SMB_ALERT 0x40 /**< @brief SMBus Alert. */ -#define I2C_UNKNOWN_ERROR 0x80 /**< @brief internal error (base value - current mode value added) */ - -#define I2C_STOPPED ((i2cflags_t)(-1)) - /**< @brief stop condition or i2cStop() called */ -/** @} */ - -/** - * @name I2C function return codes - * @{ - */ -#define I2C_OK (MSG_OK) -#define I2C_ERR_TIMEOUT (MSG_TIMEOUT) -#define I2C_ERROR (MSG_RESET) -/** @} */ - - -/*===========================================================================*/ -/* Driver pre-compile time settings. */ -/*===========================================================================*/ - -/** - * @brief Enables the mutual exclusion APIs on the I2C bus. - */ -#if !defined(I2C_USE_MUTUAL_EXCLUSION) || defined(__DOXYGEN__) -#define I2C_USE_MUTUAL_EXCLUSION TRUE -#endif - -/** - * @brief Enables 'lock' capability needed in I2C slave mode - */ -#if !defined(HAL_USE_I2C_LOCK) || defined(__DOXYGEN__) -#define HAL_USE_I2C_LOCK FALSE -#endif - -/** - * @brief Determines whether master mode required to be supported - */ - #if !defined(HAL_USE_I2C_MASTER) || defined(__DOXYGEN__) - #define HAL_USE_I2C_MASTER TRUE - #endif - -/** - * @brief Determines whether slave mode required to be supported - */ - #if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) - #define HAL_USE_I2C_SLAVE FALSE - #endif - -/*===========================================================================*/ -/* Derived constants and error checks. */ -/*===========================================================================*/ - -#if I2C_USE_MUTUAL_EXCLUSION && !CH_CFG_USE_MUTEXES && !CH_CFG_USE_SEMAPHORES -#error "I2C_USE_MUTUAL_EXCLUSION requires CH_CFG_USE_MUTEXES and/or CH_CFG_USE_SEMAPHORES" -#endif - -/*===========================================================================*/ -/* Driver data structures and types. */ -/*===========================================================================*/ - -/** - * @brief Driver state machine possible states. - */ -typedef enum { - I2C_UNINIT = 0, /**< Not initialized. */ - I2C_STOP = 1, /**< Stopped. */ - I2C_READY = 2, /**< Ready. */ - I2C_ACTIVE_TX = 3, /**< Transmitting. */ - I2C_ACTIVE_RX = 4, /**< Receiving. */ - I2C_LOCKED = 5 /**> Bus or driver locked. */ -} i2cstate_t; - -#include "hal_i2c_lld.h" - -/*===========================================================================*/ -/* Driver macros. */ -/*===========================================================================*/ - -/** - * @brief Wakes up the waiting thread notifying no errors. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wakeup_isr(i2cp) do { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(i2cp)->thread, MSG_OK); \ - osalSysUnlockFromISR(); \ -} while(0) - -/** - * @brief Wakes up the waiting thread notifying errors. - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @notapi - */ -#define _i2c_wakeup_error_isr(i2cp) do { \ - osalSysLockFromISR(); \ - osalThreadResumeI(&(i2cp)->thread, MSG_RESET); \ - osalSysUnlockFromISR(); \ -} while(0) - -/** - * @brief Wrap i2cMasterTransmitTimeout function with TIME_INFINITE timeout. - * @api - */ -#define i2cMasterTransmit(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes) \ - (i2cMasterTransmitTimeout(i2cp, addr, txbuf, txbytes, rxbuf, rxbytes, \ - TIME_INFINITE)) - -/** - * @brief Wrap i2cMasterReceiveTimeout function with TIME_INFINITE timeout. - * @api - */ -#define i2cMasterReceive(i2cp, addr, rxbuf, rxbytes) \ - (i2cMasterReceiveTimeout(i2cp, addr, rxbuf, rxbytes, TIME_INFINITE)) - - -/*===========================================================================*/ -/* External declarations. */ -/*===========================================================================*/ - -#ifdef __cplusplus -extern "C" { -#endif - void i2cInit(void); - void i2cObjectInit(I2CDriver *i2cp); - void i2cStart(I2CDriver *i2cp, const I2CConfig *config); - void i2cStop(I2CDriver *i2cp); - i2cflags_t i2cGetErrors(I2CDriver *i2cp); - msg_t i2cMasterTransmitTimeout(I2CDriver *i2cp, - i2caddr_t addr, - const uint8_t *txbuf, size_t txbytes, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - msg_t i2cMasterReceiveTimeout(I2CDriver *i2cp, - i2caddr_t addr, - uint8_t *rxbuf, size_t rxbytes, - systime_t timeout); - -#if HAL_USE_I2C_LOCK /* I2C slave mode support */ - void i2cLock(I2CDriver *i2cp, systime_t lockDuration); - void i2cUnlock(I2CDriver *i2cp); -#endif - -#if I2C_USE_MUTUAL_EXCLUSION == TRUE - void i2cAcquireBus(I2CDriver *i2cp); - void i2cReleaseBus(I2CDriver *i2cp); -#endif /* I2C_USE_MUTUAL_EXCLUSION */ - - -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C == TRUE */ - -#endif /* _I2C_H_ */ - -/** @} */ diff --git a/drivers/chibios/i2cslave/hal_i2cslave.h b/drivers/chibios/i2cslave/hal_i2cslave.h deleted file mode 100644 index 955b41e25c..0000000000 --- a/drivers/chibios/i2cslave/hal_i2cslave.h +++ /dev/null @@ -1,423 +0,0 @@ -/* - ChibiOS/RT - Copyright (C) 2006,2007,2008,2009,2010, - 2011,2012,2013 Giovanni Di Sirio. - - This file is part of ChibiOS/RT. - - ChibiOS/RT is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - ChibiOS/RT is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - - --- - - A special exception to the GPL can be applied should you wish to distribute - a combined work that includes ChibiOS/RT, without being obliged to provide - the source code for any proprietary components. See the file exception.txt - for full details of how and when the exception can be applied. -*/ -/* - Slave I2C support contributed by Brent Roman of the - Monterey Bay Aquarium Research Institute - */ - -/** - * @file i2cslave.h - * @brief Slave Mode for the I2C Driver. - * - * @addtogroup I2C - * @{ - */ -#ifndef _I2CSLAVE_H_ -#define _I2CSLAVE_H_ - -#if HAL_USE_I2C_SLAVE || defined(__DOXYGEN__) - -#include - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * @brief Configure to respond to messages directed to the given i2cadr - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C bus address - * - @a 0 matches "all call" - * . - * @return Length of message OR the type of event received - * @retval I2C_OK Success - * @retval I2C_ERROR Cannot match address in addition of those already - * - * @details MatchAddress calls are cumulative. - * Specify address zero to match I2C "all call" - * Most hardware supports matching only a signle nonzero address. - * - * @api - */ -int i2cMatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - - -/** - * @brief Configure to ignore messages directed to the given i2cadr - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C bus address - * - @a 0 matches "all call" - * . - * @details A message being transferred that has already matched the - * specified address will continue being processed. - * Requests to unmatch an address that is not currently being matched - * are ignored. - * - * @api - */ -void i2cUnmatchAddress(I2CDriver *i2cp, i2caddr_t i2cadr); - - -/** - * @brief Configure to ignore all messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details A message being transferred that has already matched the - * specified address will continue being processed. - * - * @api - */ -void i2cUnmatchAll(I2CDriver *i2cp); - - -/** - * @brief Configure to respond to messages directed to the given i2cadr - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C bus address - * - @a 0 matches "all call" - * . - * @return non-zero implies failure. - * - * @details Identical to i2cMatchAddress(), but called from interrupt context - * - * @api - */ -static inline msg_t - i2cMatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_matchAddress(i2cp, i2cadr); -} - - -/** - * @brief Configure to ignore messages directed to the given i2cadr - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] i2cadr I2C bus address - * - @a 0 matches "all call" - * . - * @details Identical to i2cUnmatchAddress(), but called from interrupt context - * - * @api - */ -static inline void - i2cUnmatchAddressI(I2CDriver *i2cp, i2caddr_t i2cadr) -{ - osalDbgCheck(i2cp != NULL); - i2c_lld_unmatchAddress(i2cp, i2cadr); -} - - -/** - * @brief Configure to ignore all messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @details Identical to i2cUnmatchAll(), but called from interrupt context - * - * @api - */ -static inline void - i2cUnmatchAllI(I2CDriver *i2cp) -/* - Notes: - Must be called from interrupt context - Does not affect the processing of any message currently being received -*/ -{ - osalDbgCheck(i2cp != NULL); - i2c_lld_unmatchAll(i2cp); -} - - -/* I2C Bus activity timeout configuration */ - -/** - * @brief return maximum number of ticks a slave bus transaction may last - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @return maximum number of ticks a slave bus transaction my last - * - * @details initialized to TIME_INFINITE (disabling slave mode bus timeouts) - * - * @api - */ -static inline - systime_t i2cSlaveTimeout(I2CDriver *i2cp) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveTimeout(i2cp); -} - - -/** - * @brief set the maximum number of ticks a slave bus transaction may last - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] ticks maximum number of ticks a slave bus transaction my last - * - @a TIME_INFINITE disables slave mode bus timeouts - * - @a TIME_IMMEDIATE is invalid - * . - * - * @api - */ -static inline - void i2cSlaveSetTimeout(I2CDriver *i2cp, systime_t ticks) -{ - osalDbgCheck(i2cp != NULL && ticks != TIME_IMMEDIATE); - i2c_lld_set_slaveTimeout(i2cp, ticks); -} - - -/* bus transaction attributes */ - -/** - * @brief return bit mask of errors associated with this slave transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @return I2C bus error conditions described in i2c.h - * - * @api - */ -static inline - i2cflags_t i2cSlaveErrors(I2CDriver *i2cp) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveErrors(i2cp); -} - -/** - * @brief return number of bytes transferred during this slave transaction - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @return number of bytes actually transferred on the bus - * - * @api - */ -static inline - size_t i2cSlaveBytes(I2CDriver *i2cp) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveBytes(i2cp); -} - -/** - * @brief return i2c address to which this message was targetted - * - * @param[in] i2cp pointer to the @p I2CDriver object - * - * @return i2c address to which this message was targetted - * - * @details The address returns will be one of those - * specified earlier as an argument to i2cMatchAddress() - * - * @api - */ -static inline - i2caddr_t i2cSlaveTargetAdr(I2CDriver *i2cp) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveTargetAdr(i2cp); -} - - -/* - An event service thread based API library called i2cevent supports processing - slave messages on a dedicated thread. This facility is built upon the - low-level driver's asynchronous callback functions described below: - - Each callback function may alter the processing of subsequent I2C - messages and read requests by calling i2cSlaveReceive() and - i2cSlaveReply(), respectively. Further, callbacks may alter their - i2cSlaveMsg structs in RAM, but only those for their own channel. - Such changes take immediate affect. This facility can be used to - avoid copying message buffers. - - If receive buffers become full or a reply to a read request cannot be - generated immediately, the relevant I2CSlaveMsg struct may be substituted - for another whose body pointer is NULL or whose body size is zero. - Note that, I2CSlaveMsg structs may be modified - in place within a channel's callbacks to the same effect. - - A NULL body pointer or zero size causes the slave to signal the master node - to wait by holding the I2C clock signal low, "stretching it", during the next - transaction to which that I2CSlaveMsg applies. - The I2C clock resumes only after a i2cSlaveSetReceive() or SetReply() is - called with an I2CSlaveMsg containing a non-NULL body, - or after the transaction timeout expires. - - Therefore, if a NULL body pointer is replaced with a non-NULL one or - a zero length is replaced with a non-zero one, i2cSlaveReceive() or - i2cSlaveReply() MUST be called -- even if with the same pointer values -- - to inform the i2c driver that the transaction may resume. - - Note that Receive and Reply processing is initially "locked". -*/ - -/** - * @brief Configure callbacks & buffers for message reception & query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Must be called from a thread - * Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveConfigure(I2CDriver *i2cp, - const I2CSlaveMsg *rxMsg, const I2CSlaveMsg *replyMsg); - - -/** - * @brief Configure callbacks & buffers for message reception - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Must be called from a thread - * Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveReceive(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg); - -/** - * @brief return @p I2CSlaveMsg for processing received messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @returns @p I2CSlaveMsg struct for processing subsequent messages - * - * @api - */ -static inline - const I2CSlaveMsg *i2cSlaveReceiveMsg(I2CDriver *i2cp) -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveReceive(i2cp); -} - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent queries - * - * @details Must be called from a thread - * Call i2cMatchAddress() after this to start processing - * Enabling match addresses before installing handler callbacks can - * result in locking the I2C bus when a master accesses those - * unconfigured slave addresses - * - * @api - */ -void i2cSlaveReply(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg); - - -/** - * @brief return @p I2CSlaveMsg for processing received messages - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @returns @p I2CSlaveMsg struct for processing subsequent messages - * - * @api - */ -static inline - const I2CSlaveMsg *i2cSlaveReplyMsg(I2CDriver *i2cp) -/* - processing descriptor for the next reply message -*/ -{ - osalDbgCheck(i2cp != NULL); - return i2c_lld_get_slaveReply(i2cp); -} - -/** - * @brief Configure callbacks & buffers for message reception - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] rxMsg @p I2CSlaveMsg struct for processing subsequent messages - * - * @details Must be called from an interrupt context - * - * @api - */ -static inline void - i2cSlaveReceiveI(I2CDriver *i2cp, const I2CSlaveMsg *rxMsg) -{ - osalDbgCheck(i2cp != NULL && rxMsg != NULL); - i2c_lld_slaveReceive(i2cp, rxMsg); -} - -/** - * @brief Configure callbacks & buffers for query reply - * - * @param[in] i2cp pointer to the @p I2CDriver object - * @param[in] replyMsg @p I2CSlaveMsg struct for processing subsequent messages - * - * @details Must be called from an interrupt context - * - * @api - */ -static inline void - i2cSlaveReplyI(I2CDriver *i2cp, const I2CSlaveMsg *replyMsg) -/* - Prepare to reply to I2C read requests from bus masters - according to the replyMsg configuration. - - Notes: - Must be called from interrupt context - Does not affect the processing of any message reply being sent -*/ -{ - osalDbgCheck(i2cp != NULL && replyMsg != NULL); - i2c_lld_slaveReply(i2cp, replyMsg); -} - -#ifdef __cplusplus -} -#endif - -#endif /* HAL_USE_I2C_SLAVE */ - -#endif /* _I2CSLAVE_H_ */ diff --git a/lib/chibios b/lib/chibios index 84a65901f0..c846437e39 160000 --- a/lib/chibios +++ b/lib/chibios @@ -1 +1 @@ -Subproject commit 84a65901f0d4784f10210637478c769e0ee6c415 +Subproject commit c846437e39423ef9394aecd3a96393db24c51ebf From 459dfa510e0722a2e39394e02616793384363ec4 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Thu, 7 Jun 2018 19:13:47 -0400 Subject: [PATCH 47/59] rename to proton c --- keyboards/_qmk_handwire/keymaps/default/readme.md | 1 - .../boards/GENERIC_STM32_F303XC/board.c | 0 .../boards/GENERIC_STM32_F303XC/board.h | 0 .../boards/GENERIC_STM32_F303XC/board.mk | 0 .../{_qmk_handwire => proton_c}/bootloader_defs.h | 0 keyboards/{_qmk_handwire => proton_c}/chconf.h | 0 keyboards/{_qmk_handwire => proton_c}/config.h | 4 ++-- keyboards/{_qmk_handwire => proton_c}/halconf.h | 0 .../keymaps/default/keymap.c | 2 +- keyboards/proton_c/keymaps/default/readme.md | 1 + keyboards/{_qmk_handwire => proton_c}/led.c | 0 keyboards/{_qmk_handwire => proton_c}/matrix.c | 0 keyboards/{_qmk_handwire => proton_c}/mcuconf.h | 0 .../_qmk_handwire.c => proton_c/proton_c.c} | 2 +- .../_qmk_handwire.h => proton_c/proton_c.h} | 10 +++++----- keyboards/{_qmk_handwire => proton_c}/readme.md | 6 +++--- keyboards/{_qmk_handwire => proton_c}/rules.mk | 0 17 files changed, 13 insertions(+), 13 deletions(-) delete mode 100644 keyboards/_qmk_handwire/keymaps/default/readme.md rename keyboards/{_qmk_handwire => proton_c}/boards/GENERIC_STM32_F303XC/board.c (100%) rename keyboards/{_qmk_handwire => proton_c}/boards/GENERIC_STM32_F303XC/board.h (100%) rename keyboards/{_qmk_handwire => proton_c}/boards/GENERIC_STM32_F303XC/board.mk (100%) rename keyboards/{_qmk_handwire => proton_c}/bootloader_defs.h (100%) rename keyboards/{_qmk_handwire => proton_c}/chconf.h (100%) rename keyboards/{_qmk_handwire => proton_c}/config.h (98%) rename keyboards/{_qmk_handwire => proton_c}/halconf.h (100%) rename keyboards/{_qmk_handwire => proton_c}/keymaps/default/keymap.c (99%) create mode 100644 keyboards/proton_c/keymaps/default/readme.md rename keyboards/{_qmk_handwire => proton_c}/led.c (100%) rename keyboards/{_qmk_handwire => proton_c}/matrix.c (100%) rename keyboards/{_qmk_handwire => proton_c}/mcuconf.h (100%) rename keyboards/{_qmk_handwire/_qmk_handwire.c => proton_c/proton_c.c} (96%) rename keyboards/{_qmk_handwire/_qmk_handwire.h => proton_c/proton_c.h} (93%) rename keyboards/{_qmk_handwire => proton_c}/readme.md (83%) rename keyboards/{_qmk_handwire => proton_c}/rules.mk (100%) diff --git a/keyboards/_qmk_handwire/keymaps/default/readme.md b/keyboards/_qmk_handwire/keymaps/default/readme.md deleted file mode 100644 index 32d4bfba61..0000000000 --- a/keyboards/_qmk_handwire/keymaps/default/readme.md +++ /dev/null @@ -1 +0,0 @@ -# The default keymap for clueboard 60% diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c b/keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.c similarity index 100% rename from keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.c rename to keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.c diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h b/keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.h similarity index 100% rename from keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.h rename to keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.h diff --git a/keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk b/keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.mk similarity index 100% rename from keyboards/_qmk_handwire/boards/GENERIC_STM32_F303XC/board.mk rename to keyboards/proton_c/boards/GENERIC_STM32_F303XC/board.mk diff --git a/keyboards/_qmk_handwire/bootloader_defs.h b/keyboards/proton_c/bootloader_defs.h similarity index 100% rename from keyboards/_qmk_handwire/bootloader_defs.h rename to keyboards/proton_c/bootloader_defs.h diff --git a/keyboards/_qmk_handwire/chconf.h b/keyboards/proton_c/chconf.h similarity index 100% rename from keyboards/_qmk_handwire/chconf.h rename to keyboards/proton_c/chconf.h diff --git a/keyboards/_qmk_handwire/config.h b/keyboards/proton_c/config.h similarity index 98% rename from keyboards/_qmk_handwire/config.h rename to keyboards/proton_c/config.h index fe0ad1d5c4..ad14553bed 100644 --- a/keyboards/_qmk_handwire/config.h +++ b/keyboards/proton_c/config.h @@ -23,8 +23,8 @@ #define PRODUCT_ID 0x1770 #define DEVICE_VER 0x0001 #define MANUFACTURER QMK -#define PRODUCT Handwire -#define DESCRIPTION "Handwire protoboard" +#define PRODUCT Proton C +#define DESCRIPTION "Proton C protoboard" /* key matrix size */ #define MATRIX_ROWS 12 diff --git a/keyboards/_qmk_handwire/halconf.h b/keyboards/proton_c/halconf.h similarity index 100% rename from keyboards/_qmk_handwire/halconf.h rename to keyboards/proton_c/halconf.h diff --git a/keyboards/_qmk_handwire/keymaps/default/keymap.c b/keyboards/proton_c/keymaps/default/keymap.c similarity index 99% rename from keyboards/_qmk_handwire/keymaps/default/keymap.c rename to keyboards/proton_c/keymaps/default/keymap.c index 168be875c2..ee2b13e588 100644 --- a/keyboards/_qmk_handwire/keymaps/default/keymap.c +++ b/keyboards/proton_c/keymaps/default/keymap.c @@ -1,4 +1,4 @@ -#include "_qmk_handwire.h" +#include QMK_KEYBOARD_H #define _______ KC_TRNS diff --git a/keyboards/proton_c/keymaps/default/readme.md b/keyboards/proton_c/keymaps/default/readme.md new file mode 100644 index 0000000000..3aec70f621 --- /dev/null +++ b/keyboards/proton_c/keymaps/default/readme.md @@ -0,0 +1 @@ +# The default keymap for the Proton C diff --git a/keyboards/_qmk_handwire/led.c b/keyboards/proton_c/led.c similarity index 100% rename from keyboards/_qmk_handwire/led.c rename to keyboards/proton_c/led.c diff --git a/keyboards/_qmk_handwire/matrix.c b/keyboards/proton_c/matrix.c similarity index 100% rename from keyboards/_qmk_handwire/matrix.c rename to keyboards/proton_c/matrix.c diff --git a/keyboards/_qmk_handwire/mcuconf.h b/keyboards/proton_c/mcuconf.h similarity index 100% rename from keyboards/_qmk_handwire/mcuconf.h rename to keyboards/proton_c/mcuconf.h diff --git a/keyboards/_qmk_handwire/_qmk_handwire.c b/keyboards/proton_c/proton_c.c similarity index 96% rename from keyboards/_qmk_handwire/_qmk_handwire.c rename to keyboards/proton_c/proton_c.c index a7f460b1a9..33ba31a080 100644 --- a/keyboards/_qmk_handwire/_qmk_handwire.c +++ b/keyboards/proton_c/proton_c.c @@ -14,7 +14,7 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#include "_qmk_handwire.h" +#include "proton_c.h" void matrix_init_kb(void) { diff --git a/keyboards/_qmk_handwire/_qmk_handwire.h b/keyboards/proton_c/proton_c.h similarity index 93% rename from keyboards/_qmk_handwire/_qmk_handwire.h rename to keyboards/proton_c/proton_c.h index f482861f9a..d3d1049c6d 100644 --- a/keyboards/_qmk_handwire/_qmk_handwire.h +++ b/keyboards/proton_c/proton_c.h @@ -14,15 +14,15 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ -#ifndef QMK_HANDWIRE_H -#define QMK_HANDWIRE_H +#ifndef PROTON_C_H +#define PROTON_C_H #include "quantum.h" /* - * These are shortcuts to help you work with the various layout options. If your + * These are shortcuts to help you work with the various layout options. If your * keymap works with one of the LAYOUT_...() macros you are encouraged to use that - * and to contribute your keymap to the corresponding layout in + * and to contribute your keymap to the corresponding layout in * `qmk_firmware/layouts/community`. */ @@ -56,4 +56,4 @@ { k50, k51, k52, 0, 0, 0, 0 } \ } -#endif \ No newline at end of file +#endif diff --git a/keyboards/_qmk_handwire/readme.md b/keyboards/proton_c/readme.md similarity index 83% rename from keyboards/_qmk_handwire/readme.md rename to keyboards/proton_c/readme.md index d74c3aa52d..e133cd9e0f 100644 --- a/keyboards/_qmk_handwire/readme.md +++ b/keyboards/proton_c/readme.md @@ -1,14 +1,14 @@ -# QMK Handwire +# Proton C An Arm-based handwire board. * Keyboard Maintainer: [Jack Humbert](https://github.com/jackhumbert) -* Hardware Supported: QMK Handwire +* Hardware Supported: QMK Proton C * rev1 (1.0) * Hardware Availability: [qmk.fm](https://qmk.fm/) Make example for this keyboard (after setting up your build environment): - make _qmk_handwire:default + make proton_c:default See [build environment setup](https://docs.qmk.fm/build_environment_setup.html) then the [make instructions](https://docs.qmk.fm/make_instructions.html) for more information. diff --git a/keyboards/_qmk_handwire/rules.mk b/keyboards/proton_c/rules.mk similarity index 100% rename from keyboards/_qmk_handwire/rules.mk rename to keyboards/proton_c/rules.mk From 53c518f7d4552b0067619ffc2c7a3af5f3e44804 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Fri, 8 Jun 2018 02:07:28 -0400 Subject: [PATCH 48/59] start qwiic keyboard impl --- drivers/arm/twi2c.c | 71 +++++++++++++++++--- drivers/arm/twi2c.h | 6 ++ drivers/qwiic/qwiic_keyboard.c | 118 +++++++++++++++++++++++++++++++++ drivers/qwiic/qwiic_keyboard.h | 22 ++++++ 4 files changed, 207 insertions(+), 10 deletions(-) create mode 100644 drivers/qwiic/qwiic_keyboard.c create mode 100644 drivers/qwiic/qwiic_keyboard.h diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 53af437bc2..e3bed5db86 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -40,7 +40,7 @@ // 400000 // }; -I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; +I2CSlaveMsgCB twi2c_incoming_message_process, twi2c_catch_error, twi2c_clear_after_send; #endif @@ -67,6 +67,12 @@ BaseSequentialStream *chp = NULL; // Used for serial logging #ifdef I2C_SLAVE_ENABLE + + + + + + // Handler when something sent to us const I2CSlaveMsg echoRx = { @@ -74,7 +80,7 @@ const I2CSlaveMsg echoRx = rxBody, /* body of received msg */ NULL, /* do nothing on address match */ twi2c_slave_message_process, /* Routine to process received messages */ - catchError /* Error hook */ + twi2c_catch_error /* Error hook */ }; @@ -85,7 +91,7 @@ I2CSlaveMsg initialReply = (uint8_t *)initialReplyBody, NULL, /* do nothing on address match */ NULL, /* do nothing after reply sent */ - catchError /* Error hook */ + twi2c_catch_error /* Error hook */ }; // // 'Empty' reply when nothing to say, and no message received. In RAM, to allow update @@ -95,7 +101,7 @@ I2CSlaveMsg initialReply = // NULL, // NULL, /* do nothing on address match */ // NULL, /* do nothing after reply sent */ -// catchError /* Error hook */ +// twi2c_catch_error /* Error hook */ // }; @@ -104,8 +110,8 @@ I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ MATRIX_ROWS / 2, /* filled in with the length of the message to send */ txBody, /* Response message */ NULL, /* do nothing special on address match */ - clearAfterSend, /* Clear receive buffer once replied */ - catchError /* Error hook */ + twi2c_clear_after_send, /* Clear receive buffer once replied */ + twi2c_catch_error /* Error hook */ }; @@ -130,7 +136,7 @@ void noteI2cError(uint32_t flags) * * Called in interrupt context, so need to watch what we do */ -void catchError(I2CDriver *i2cp) +void twi2c_catch_error(I2CDriver *i2cp) { noteI2cError(i2cp->errors); } @@ -163,7 +169,7 @@ void twi2c_slave_message_process(I2CDriver *i2cp) { /** * Callback after sending of response complete - restores default reply in case polled */ -void clearAfterSend(I2CDriver *i2cp) +void twi2c_clear_after_send(I2CDriver *i2cp) { // echoReply.size = 0; // Clear receive message // i2cSlaveReplyI(i2cp, &initialReply); @@ -176,7 +182,7 @@ void clearAfterSend(I2CDriver *i2cp) * We then go into a loop checking for errors, and never return */ -void twi2c_slave_init(void) { +void twi2c_slave_init(twi2c_message_received * cb, uint8_t address) { twi2c_init(); @@ -193,7 +199,7 @@ void twi2c_slave_init(void) { i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); // Enable match address after everything else set up - i2cMatchAddress(&I2C_DRIVER, slaveI2Caddress/2); + i2cMatchAddress(&I2C_DRIVER, address/2); // i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); // i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ @@ -238,3 +244,48 @@ uint8_t twi2c_transmit(uint8_t address, uint8_t* data, uint16_t length) { i2cStart(&I2C_DRIVER, &i2cconfig); return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, data, length, 0, 0, MS2ST(100)); } + +uint8_t twi2c_incoming_body[512]; +uint8_t twi2c_outgoing_body[512]; + +// Response to received messages +I2CSlaveMsg twi2c_incoming_message = { + sizeof(twi2c_incoming_body), + twi2c_incoming_body, + NULL, + twi2c_incoming_message_process, + twi2c_catch_error /* Error hook */ +}; + +void twi2c_incoming_message_process(I2CDriver *i2cp) { + size_t len = i2cSlaveBytes(i2cp); + twi2c_message_received_callback(twi2c_incoming_body, len); +} + +// Response to received messages +I2CSlaveMsg twi2c_outgoing_message = { /* this is in RAM so size may be updated */ + sizeof(twi2c_outgoing_body), /* filled in with the length of the message to send */ + twi2c_outgoing_body, + NULL, + twi2c_clear_after_send, + twi2c_catch_error /* Error hook */ +}; + +uint8_t twi2c_reply(uint8_t * data, uint16_t length) { + twi2c_outgoing_body = data; + twi2c_outgoing_message.size = length; + i2cSlaveReplyI(i2cp, &twi2c_outgoing_message); +} + +uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t rx_body, uint16_t rx_length) { + return i2cMasterTransmitTimeout(&I2C_DRIVER, address/2, tx_body, tx_length, rx_body, rx_length, MS2ST(100)); +} + +uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback) { + twi2c_message_received_callback = callback; + i2cStart(&I2C_DRIVER, &i2cconfig); + I2C_DRIVER.slaveTimeout = MS2ST(100); + i2cSlaveConfigure(&I2C_DRIVER, &twi2c_incoming_message, &twi2c_outgoing_message); + i2cMatchAddress(&I2C_DRIVER, address/2); + return 0; +} diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index 57cc54070e..d3dc2a1572 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -26,6 +26,9 @@ #ifdef I2C_SLAVE_ENABLE +typedef void twi2c_message_received(uint8_t * body, uint16_t size); +twi2c_message_received twi2c_message_received_callback; + I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; void twi2c_slave_init(void); @@ -42,3 +45,6 @@ uint8_t twi2c_receive(uint8_t address, uint8_t* data, uint16_t length); uint8_t twi2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); uint8_t twi2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); void twi2c_stop(void); +uint8_t twi2c_reply(uint8_t * data, uint16_t length); +uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t rx_body, uint16_t rx_length); +uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback); diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c new file mode 100644 index 0000000000..b9e01a7f03 --- /dev/null +++ b/drivers/qwiic/qwiic_keyboard.c @@ -0,0 +1,118 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "qwiic_keyboard.h" +#include "keymap.h" +#include "matrix.h" + +#define QWIIC_KEYBOARD_LAYERS 16 +#define QWIIC_KEYBOARD_ROWS 8 +#define QWIIC_KEYBOARD_COLS 8 + +#define QWIIC_KEYBOARD_HANDSHAKE_ADDRESS 0b01010100 +#define QWIIC_KEYBOARD_LISTENING_ADDRESS_START 0b01010110 +#define QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE (2 + (QWIIC_KEYBOARD_LAYERS * QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS)) +#define QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE MATRIX_ROWS + +bool qwiic_keyboard_master = false; +bool qwiic_keyboard_connected = false; +uint8_t * qwiic_keyboard_handshake_message = {0}; +uint8_t * qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; + +uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {0}; +uint8_t qwiic_keyboard_new_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; +uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; +uint8_t qwiic_keyboard_matrix_rows; +uint8_t qwiic_keyboard_matrix_cols; + +void qwiic_keyboard_setup(void) { + twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received); +} + +void qwiic_keyboard_set_master() { + twi2c_stop(); + qwiic_keyboard_master = true; +} + +void qwiic_keyboard_task(void) { + if (qwiic_keyboard_master) { + if (qwiic_keyboard_connected) { + if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address, + NULL, 0, + qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE + )) { + // process key event + } else { + // disconnect + } + } + if (MSG_OK == twi2c_transmit_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, + qwiic_keyboard_new_listening_address, 1, + qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE + )) { + qwiic_keyboard_new_listening_address+=2; + uint8_t * message_pointer = qwiic_keyboard_handshake_message; + qwiic_keyboard_matrix_rows = *message_pointer++; + qwiic_keyboard_matrix_cols = *message_pointer++; + qwiic_keyboard_read_keymap(message_pointer); + } + } +} + +twi2c_message_received qwiic_keyboard_message_received; +extern matrix_row_t matrix[MATRIX_ROWS]; +uint8_t * qwiic_keyboard_reply; + +void qwiic_keyboard_message_received(uint8_t * body, uint16_t size) { + if (qwiic_keyboard_connected) { + memcpy(qwiic_keyboard_reply, matrix, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); + twi2c_reply(qwiic_keyboard_reply, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); + } else { + qwiic_keyboard_connected = true; + qwiic_keyboard_listening_address + uint8_t * message_pointer = qwiic_keyboard_reply; + *message_pointer++ = MATRIX_ROWS; + *message_pointer++ = MATRIX_COLS; + qwiic_keyboard_write_keymap(message_pointer); + twi2c_reply(qwiic_keyboard_reply, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE); + twi2c_stop(); + twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received); + } +} + +void qwiic_keyboard_write_keymap(uint8_t * pointer) { + for (uint8_t layer = 0; layer < QWIIC_KEYBOARD_LAYERS; layer++) { + for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { + for (uint8_t col = 0; col < QWIIC_KEYBOARD_COLS; col++) { + uint16_t keycode = pgm_read_word(&keymaps[layer][row][col]); + *pointer++ = (keycode >> 8); + *pointer++ = (keycode & 0xFF); + } + } + } +} + +void qwiic_keyboard_read_keymap(uint8_t * pointer) { + for (uint8_t layer = 0; layer < QWIIC_KEYBOARD_LAYERS; layer++) { + for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { + for (uint8_t col = 0; col < QWIIC_KEYBOARD_COLS; col++) { + uint16_t keycode = *pointer++; + keycode |= (*pointer++) << 8; + qwiic_keyboard_keymap[layer][row][col] = keycode; + } + } + } +} diff --git a/drivers/qwiic/qwiic_keyboard.h b/drivers/qwiic/qwiic_keyboard.h new file mode 100644 index 0000000000..d73544a9a7 --- /dev/null +++ b/drivers/qwiic/qwiic_keyboard.h @@ -0,0 +1,22 @@ +/* Copyright 2018 Jack Humbert + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef QWIIC_KEYBOARD_H +#define QWIIC_KEYBOARD_H + +#include "quantum.h" + +#endif From 2fccc1a0646827d6547cc5e3faa3934c4dd78dce Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sat, 9 Jun 2018 02:03:32 -0400 Subject: [PATCH 49/59] hooked-up keymap/matrix, compiling, not working --- common_features.mk | 12 ++- drivers/arm/twi2c.c | 174 ++++-------------------------- drivers/arm/twi2c.h | 25 ++--- drivers/qwiic/qwiic_keyboard.c | 147 ++++++++++++++++++------- drivers/qwiic/qwiic_keyboard.h | 4 + keyboards/muon_light/config.h | 2 + keyboards/muon_light/halconf.h | 7 ++ keyboards/muon_light/muon_light.c | 136 +++++++++++------------ keyboards/muon_light/rules.mk | 7 +- tmk_core/common/keyboard.c | 12 ++- 10 files changed, 251 insertions(+), 275 deletions(-) diff --git a/common_features.mk b/common_features.mk index a76c522bfc..f5fce5441c 100644 --- a/common_features.mk +++ b/common_features.mk @@ -124,7 +124,7 @@ endif ifeq ($(strip $(RGB_MATRIX_ENABLE)), yes) OPT_DEFS += -DRGB_MATRIX_ENABLE SRC += is31fl3731.c - SRC += twi2c.c + I2C_ENABLE = yes SRC += $(QUANTUM_DIR)/color.c SRC += $(QUANTUM_DIR)/rgb_matrix.c CIE1931_CURVE = yes @@ -205,7 +205,7 @@ ifeq ($(strip $(USB_HID_ENABLE)), yes) endif ifeq ($(strip $(I2C_SLAVE_ENABLE)), yes) - SRC += twi2c.c + I2C_ENABLE = yes OPT_DEFS += -DI2C_SLAVE_ENABLE endif @@ -214,6 +214,14 @@ ifeq ($(strip $(ENCODER_ENABLE)), yes) SRC += $(QUANTUM_DIR)/encoder.c endif +ifeq ($(strip $(QWIIC_KEYBOARD_ENABLE)), yes) + SRC += qwiic/qwiic_keyboard.c + OPT_DEFS += -DQWIIC_KEYBOARD_ENABLE +endif + +ifeq ($(strip $(I2C_ENABLE)), yes) + SRC += twi2c.c +endif QUANTUM_SRC:= \ $(QUANTUM_DIR)/quantum.c \ diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index e3bed5db86..a4268d87e4 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -20,10 +20,6 @@ #include "chprintf.h" #include "memstreams.h" #include "printf.h" -#include "matrix.h" - -#ifdef I2C_SLAVE_ENABLE - #include "hal_i2cslave.h" /** @@ -41,8 +37,7 @@ // }; I2CSlaveMsgCB twi2c_incoming_message_process, twi2c_catch_error, twi2c_clear_after_send; - -#endif +twi2c_message_received twi2c_message_received_callback; static uint8_t twi2c_address; @@ -54,68 +49,6 @@ static const I2CConfig i2cconfig = { 0 }; -char initialReplyBody[50] = "Initial reply"; // 'Status' response if read without preceding write - - -uint32_t messageCounter = 0; /* Counts number of messages received to return as part of response */ - -uint8_t rxBody[2]; /* stores last message master sent us (intentionally a few bytes smaller than txBody) */ -uint8_t txBody[MATRIX_ROWS/2]; /* Return message buffer for computed replies */ - -BaseSequentialStream *chp = NULL; // Used for serial logging - - -#ifdef I2C_SLAVE_ENABLE - - - - - - - -// Handler when something sent to us -const I2CSlaveMsg echoRx = -{ - sizeof(rxBody), /* max sizeof received msg body */ - rxBody, /* body of received msg */ - NULL, /* do nothing on address match */ - twi2c_slave_message_process, /* Routine to process received messages */ - twi2c_catch_error /* Error hook */ -}; - - -// // 'Empty' reply when nothing to say, and no message received. In RAM, to allow update -I2CSlaveMsg initialReply = -{ - sizeof(initialReplyBody), /* trailing zero byte will be repeated as needed */ - (uint8_t *)initialReplyBody, - NULL, /* do nothing on address match */ - NULL, /* do nothing after reply sent */ - twi2c_catch_error /* Error hook */ -}; - -// // 'Empty' reply when nothing to say, and no message received. In RAM, to allow update -// I2CSlaveMsg initialReply = -// { -// 0, /* trailing zero byte will be repeated as needed */ -// NULL, -// NULL, /* do nothing on address match */ -// NULL, /* do nothing after reply sent */ -// twi2c_catch_error /* Error hook */ -// }; - - -// Response to received messages -I2CSlaveMsg echoReply = { /* this is in RAM so size may be updated */ - MATRIX_ROWS / 2, /* filled in with the length of the message to send */ - txBody, /* Response message */ - NULL, /* do nothing special on address match */ - twi2c_clear_after_send, /* Clear receive buffer once replied */ - twi2c_catch_error /* Error hook */ -}; - - - /** * Track I2C errors */ @@ -129,8 +62,6 @@ void noteI2cError(uint32_t flags) gotI2cError = 1; } - - /** * Generic error handler * @@ -141,31 +72,6 @@ void twi2c_catch_error(I2CDriver *i2cp) noteI2cError(i2cp->errors); } -extern void matrix_copy(matrix_row_t * copy); - -const char hexString[16] = "0123456789abcdef"; - - - -/** - * Message processor - looks at received message, determines reply as quickly as possible - * - * Responds with the value of the messageCounter (in hex), followed by the received message in [..] - * - * Note: Called in interrupt context, so need to be quick! - */ -void twi2c_slave_message_process(I2CDriver *i2cp) { - - // size_t len = i2cSlaveBytes(i2cp); // Number of bytes received - - // memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); - matrix_copy(txBody); - - echoReply.size = MATRIX_ROWS / 2; - i2cSlaveReplyI(i2cp, &echoReply); -} - - /** * Callback after sending of response complete - restores default reply in case polled */ @@ -175,49 +81,7 @@ void twi2c_clear_after_send(I2CDriver *i2cp) // i2cSlaveReplyI(i2cp, &initialReply); } - -/** - * Start the I2C Slave port to accept comms from master CPU - * - * We then go into a loop checking for errors, and never return - */ - -void twi2c_slave_init(twi2c_message_received * cb, uint8_t address) { - - twi2c_init(); - - - i2cStart(&I2C_DRIVER, &i2cconfig); -#if HAL_USE_I2C_SLAVE - I2C_DRIVER.slaveTimeout = MS2ST(100); // Time for complete message -#endif - - // i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &initialReply); - - memset(txBody, 0, MATRIX_ROWS / 2 * sizeof(matrix_row_t)); - - i2cSlaveConfigure(&I2C_DRIVER, &echoRx, &echoReply); - - // Enable match address after everything else set up - i2cMatchAddress(&I2C_DRIVER, address/2); -// i2cMatchAddress(&I2C_DRIVER, myOtherI2Caddress/2); - // i2cMatchAddress(&I2C_DRIVER, 0); /* "all call" */ - - printf("Slave I2C started\n\r"); - -} - -void twi2c_slave_task(void) { - if (gotI2cError) { - gotI2cError = 0; - printf("I2cError: %04x\r\n", lastI2cErrorFlags); - } -} - -#endif - -uint8_t twi2c_start(uint8_t address) { - twi2c_address = address; +uint8_t twi2c_start(void) { i2cStart(&I2C_DRIVER, &i2cconfig); return 0; } @@ -239,12 +103,15 @@ uint8_t twi2c_write(uint8_t data) { return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, &data, 1, 0, 0, MS2ST(100)); } -uint8_t twi2c_transmit(uint8_t address, uint8_t* data, uint16_t length) { - twi2c_address = address; - i2cStart(&I2C_DRIVER, &i2cconfig); - return i2cMasterTransmitTimeout(&I2C_DRIVER, twi2c_address/2, data, length, 0, 0, MS2ST(100)); +uint8_t twi2c_transmit(uint8_t address, uint8_t * data, uint16_t length) { + return i2cMasterTransmitTimeout(&I2C_DRIVER, address/2, data, length, 0, 0, MS2ST(100)); } +uint8_t twi2c_receive(uint8_t address, uint8_t * data, uint16_t length) { + return i2cMasterReceiveTimeout(&I2C_DRIVER, address/2, data, length, MS2ST(100)); +} + + uint8_t twi2c_incoming_body[512]; uint8_t twi2c_outgoing_body[512]; @@ -257,35 +124,40 @@ I2CSlaveMsg twi2c_incoming_message = { twi2c_catch_error /* Error hook */ }; -void twi2c_incoming_message_process(I2CDriver *i2cp) { +void twi2c_incoming_message_process(I2CDriver * i2cp) { size_t len = i2cSlaveBytes(i2cp); - twi2c_message_received_callback(twi2c_incoming_body, len); + (*twi2c_message_received_callback)(i2cp, twi2c_incoming_body, len); } // Response to received messages -I2CSlaveMsg twi2c_outgoing_message = { /* this is in RAM so size may be updated */ - sizeof(twi2c_outgoing_body), /* filled in with the length of the message to send */ +I2CSlaveMsg twi2c_outgoing_message = { + sizeof(twi2c_outgoing_body), twi2c_outgoing_body, NULL, twi2c_clear_after_send, - twi2c_catch_error /* Error hook */ + twi2c_catch_error }; -uint8_t twi2c_reply(uint8_t * data, uint16_t length) { - twi2c_outgoing_body = data; +uint8_t twi2c_reply(I2CDriver * i2cp, uint8_t * data, uint16_t length) { + memcpy(twi2c_outgoing_body, data, length); twi2c_outgoing_message.size = length; i2cSlaveReplyI(i2cp, &twi2c_outgoing_message); + return 0; } -uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t rx_body, uint16_t rx_length) { +uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length) { return i2cMasterTransmitTimeout(&I2C_DRIVER, address/2, tx_body, tx_length, rx_body, rx_length, MS2ST(100)); } uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback) { twi2c_message_received_callback = callback; - i2cStart(&I2C_DRIVER, &i2cconfig); I2C_DRIVER.slaveTimeout = MS2ST(100); i2cSlaveConfigure(&I2C_DRIVER, &twi2c_incoming_message, &twi2c_outgoing_message); i2cMatchAddress(&I2C_DRIVER, address/2); return 0; } + +void twi2c_stop(void) { + i2cUnmatchAll(&I2C_DRIVER); + i2cStop(&I2C_DRIVER); +} diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index d3dc2a1572..047c28e8b0 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -14,6 +14,9 @@ * along with this program. If not, see . */ +#ifndef TWI2C_H +#define TWI2C_H + #include "ch.h" #include "hal.h" @@ -23,20 +26,11 @@ #define slaveI2Caddress 0x30 /* Address in our terms - halved by later code */ //#define myOtherI2Caddress 0x19 - -#ifdef I2C_SLAVE_ENABLE - -typedef void twi2c_message_received(uint8_t * body, uint16_t size); -twi2c_message_received twi2c_message_received_callback; - -I2CSlaveMsgCB twi2c_slave_message_process, catchError, clearAfterSend; - -void twi2c_slave_init(void); - -#endif +I2CSlaveMsgCB twi2c_incoming_message_process, twi2c_catch_error, twi2c_clear_after_send; +typedef void (*twi2c_message_received)(I2CDriver *, uint8_t *, uint16_t); void twi2c_init(void); -uint8_t twi2c_start(uint8_t address); +uint8_t twi2c_start(void); uint8_t twi2c_write(uint8_t data); uint8_t twi2c_read_ack(void); uint8_t twi2c_read_nack(void); @@ -45,6 +39,9 @@ uint8_t twi2c_receive(uint8_t address, uint8_t* data, uint16_t length); uint8_t twi2c_writeReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); uint8_t twi2c_readReg(uint8_t devaddr, uint8_t regaddr, uint8_t* data, uint16_t length); void twi2c_stop(void); -uint8_t twi2c_reply(uint8_t * data, uint16_t length); -uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t rx_body, uint16_t rx_length); + +uint8_t twi2c_reply(I2CDriver * i2cp, uint8_t * data, uint16_t length); +uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length); uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback); + +#endif diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index b9e01a7f03..d6e2357c96 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -17,82 +17,141 @@ #include "qwiic_keyboard.h" #include "keymap.h" #include "matrix.h" +#include "keyboard.h" +#include "twi2c.h" +#include +#include "usb_main.h" +#include "usb_driver.h" #define QWIIC_KEYBOARD_LAYERS 16 #define QWIIC_KEYBOARD_ROWS 8 #define QWIIC_KEYBOARD_COLS 8 -#define QWIIC_KEYBOARD_HANDSHAKE_ADDRESS 0b01010100 +#define qwiic_matrix_t uint8_t + +#define QWIIC_KEYBOARD_HANDSHAKE_ADDRESS 0b01010100 #define QWIIC_KEYBOARD_LISTENING_ADDRESS_START 0b01010110 -#define QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE (2 + (QWIIC_KEYBOARD_LAYERS * QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS)) -#define QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE MATRIX_ROWS +#define QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE (QWIIC_KEYBOARD_LAYERS * QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS) +#define QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE MATRIX_ROWS + +void qwiic_keyboard_write_keymap(uint8_t * pointer); +void qwiic_keyboard_read_keymap(uint8_t * pointer); bool qwiic_keyboard_master = false; bool qwiic_keyboard_connected = false; -uint8_t * qwiic_keyboard_handshake_message = {0}; -uint8_t * qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; +uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0}; +uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; +twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {0}; uint8_t qwiic_keyboard_new_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; -uint8_t qwiic_keyboard_matrix_rows; -uint8_t qwiic_keyboard_matrix_cols; +uint8_t qwiic_keyboard_processing_slave = false; -void qwiic_keyboard_setup(void) { - twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received); +void qwiic_keyboard_init(void) { + twi2c_init(); + twi2c_start(); + twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received_ptr); } -void qwiic_keyboard_set_master() { +void qwiic_keyboard_set_master(void) { twi2c_stop(); + twi2c_start(); qwiic_keyboard_master = true; } void qwiic_keyboard_task(void) { + if (USB_DRIVER.state == USB_ACTIVE) + qwiic_keyboard_master = true; + else + qwiic_keyboard_master = false; if (qwiic_keyboard_master) { if (qwiic_keyboard_connected) { - if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address, - NULL, 0, + // send empty message, expecting matrix info + twi2c_transmit(qwiic_keyboard_listening_address, NULL, 0); + if (MSG_OK == twi2c_receive(qwiic_keyboard_listening_address, qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE )) { - // process key event + // majority of this is pulled from keyboard.c:keyboard_task() + static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS]; + qwiic_matrix_t matrix_row = 0; + qwiic_matrix_t matrix_change = 0; + qwiic_keyboard_processing_slave = true; + SEND_STRING("K."); + for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { + matrix_row = qwiic_keyboard_matrix_message[r]; + matrix_change = matrix_row ^ matrix_prev[r]; + if (matrix_change) { + for (uint8_t c = 0; c < MATRIX_COLS; c++) { + if (matrix_change & ((qwiic_matrix_t)1<= QMK_KEYS_PER_SCAN) + #endif + // process a key per task call + goto MATRIX_LOOP_END; + } + } + } + } + // call with pseudo tick event when no real key event. + #ifdef QMK_KEYS_PER_SCAN + // we can get here with some keys processed now. + if (!keys_processed) + #endif + action_exec(TICK); + MATRIX_LOOP_END: + qwiic_keyboard_processing_slave = false; } else { // disconnect + // qwiic_keyboard_connected = false; + } + } else { + // send new address to listen on, expect back keymap + twi2c_transmit(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, &qwiic_keyboard_new_listening_address, 1); + if (MSG_OK == twi2c_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, + qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE + )) { + qwiic_keyboard_connected = true; + // increment address (for future implemenations of supporting multiple devices) + qwiic_keyboard_new_listening_address+=2; + // load keymap into memory + qwiic_keyboard_read_keymap(qwiic_keyboard_handshake_message); } } - if (MSG_OK == twi2c_transmit_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, - qwiic_keyboard_new_listening_address, 1, - qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE - )) { - qwiic_keyboard_new_listening_address+=2; - uint8_t * message_pointer = qwiic_keyboard_handshake_message; - qwiic_keyboard_matrix_rows = *message_pointer++; - qwiic_keyboard_matrix_cols = *message_pointer++; - qwiic_keyboard_read_keymap(message_pointer); - } } } -twi2c_message_received qwiic_keyboard_message_received; -extern matrix_row_t matrix[MATRIX_ROWS]; -uint8_t * qwiic_keyboard_reply; +uint8_t qwiic_keyboard_reply[MATRIX_ROWS]; -void qwiic_keyboard_message_received(uint8_t * body, uint16_t size) { +void qwiic_keyboard_message_received(I2CDriver *i2cp, uint8_t * body, uint16_t size) { if (qwiic_keyboard_connected) { - memcpy(qwiic_keyboard_reply, matrix, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); - twi2c_reply(qwiic_keyboard_reply, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); + for (uint8_t row = 0; row < MATRIX_ROWS; row++) { + qwiic_keyboard_reply[row] = matrix_get_row(row); + } + twi2c_reply(i2cp, qwiic_keyboard_reply, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); } else { qwiic_keyboard_connected = true; - qwiic_keyboard_listening_address - uint8_t * message_pointer = qwiic_keyboard_reply; - *message_pointer++ = MATRIX_ROWS; - *message_pointer++ = MATRIX_COLS; - qwiic_keyboard_write_keymap(message_pointer); - twi2c_reply(qwiic_keyboard_reply, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE); + qwiic_keyboard_master = false; + qwiic_keyboard_listening_address = body[0]; + qwiic_keyboard_write_keymap(qwiic_keyboard_reply); + twi2c_reply(i2cp, qwiic_keyboard_reply, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE); twi2c_stop(); - twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received); + twi2c_start(); + twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received_ptr); } } +// qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; + +__attribute__((optimize("O0"))) void qwiic_keyboard_write_keymap(uint8_t * pointer) { for (uint8_t layer = 0; layer < QWIIC_KEYBOARD_LAYERS; layer++) { for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { @@ -116,3 +175,19 @@ void qwiic_keyboard_read_keymap(uint8_t * pointer) { } } } + +// overwrite the built-in function - slaves don't need to process keycodes +bool is_keyboard_master(void) { + return qwiic_keyboard_master; +} + +// overwrite the built-in function +uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) { + if (qwiic_keyboard_processing_slave) { + // trick the built-in handling to accept our replacement keymap + return qwiic_keyboard_keymap[(layer)][(key.row)][(key.col)]; + } else { + // Read entire word (16bits) + return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]); + } +} diff --git a/drivers/qwiic/qwiic_keyboard.h b/drivers/qwiic/qwiic_keyboard.h index d73544a9a7..813a02bb9e 100644 --- a/drivers/qwiic/qwiic_keyboard.h +++ b/drivers/qwiic/qwiic_keyboard.h @@ -19,4 +19,8 @@ #include "quantum.h" +void qwiic_keyboard_init(void); +void qwiic_keyboard_task(void); +void qwiic_keyboard_message_received(I2CDriver *i2cp, uint8_t * body, uint16_t size); + #endif diff --git a/keyboards/muon_light/config.h b/keyboards/muon_light/config.h index b4c7b6051b..b8df031a4a 100644 --- a/keyboards/muon_light/config.h +++ b/keyboards/muon_light/config.h @@ -149,4 +149,6 @@ along with this program. If not, see . #define DRIVER_2_LED_TOTAL 24 #define DRIVER_LED_TOTAL DRIVER_1_LED_TOTAL + DRIVER_2_LED_TOTAL +#define NO_USB_STARTUP_CHECK + #endif diff --git a/keyboards/muon_light/halconf.h b/keyboards/muon_light/halconf.h index c3e0cbb728..2e8eed14f4 100644 --- a/keyboards/muon_light/halconf.h +++ b/keyboards/muon_light/halconf.h @@ -79,6 +79,13 @@ #define HAL_USE_I2C TRUE #endif +/** + * @brief Enables the I2C Slave subsystem. + */ +#if !defined(HAL_USE_I2C_SLAVE) || defined(__DOXYGEN__) +#define HAL_USE_I2C_SLAVE TRUE +#endif + /** * @brief Enables the I2S subsystem. */ diff --git a/keyboards/muon_light/muon_light.c b/keyboards/muon_light/muon_light.c index 1896a40c0d..9b6cbb824c 100644 --- a/keyboards/muon_light/muon_light.c +++ b/keyboards/muon_light/muon_light.c @@ -28,13 +28,13 @@ void matrix_scan_kb(void) { matrix_scan_user(); } -void suspend_power_down_kb(void) { - rgb_matrix_set_suspend_state(true); -} +// void suspend_power_down_kb(void) { +// rgb_matrix_set_suspend_state(true); +// } -void suspend_wakeup_init_kb(void) { - rgb_matrix_set_suspend_state(false); -} +// void suspend_wakeup_init_kb(void) { +// rgb_matrix_set_suspend_state(false); +// } const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_ortho_4x6( 18, 19, 20, 21, 22, 23, @@ -43,73 +43,73 @@ const uint8_t music_map[MATRIX_ROWS][MATRIX_COLS] = LAYOUT_ortho_4x6( 0, 1, 2, 3, 4, 5 ); -const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { -/* Refer to IS31 manual for these locations - * driver - * | R location - * | | G location - * | | | B location - * | | | | */ - {0, C1_3, C2_3, C3_3}, - {0, C1_4, C2_4, C3_4}, - {0, C1_5, C2_5, C3_5}, - {0, C1_11, C2_11, C3_11}, - {0, C1_12, C2_12, C3_12}, - {0, C1_13, C2_13, C3_13}, +// const is31_led g_is31_leds[DRIVER_LED_TOTAL] = { +// /* Refer to IS31 manual for these locations +// * driver +// * | R location +// * | | G location +// * | | | B location +// * | | | | */ +// {0, C1_3, C2_3, C3_3}, +// {0, C1_4, C2_4, C3_4}, +// {0, C1_5, C2_5, C3_5}, +// {0, C1_11, C2_11, C3_11}, +// {0, C1_12, C2_12, C3_12}, +// {0, C1_13, C2_13, C3_13}, - {0, C1_6, C2_6, C3_6}, - {0, C1_7, C2_7, C3_7}, - {0, C1_8, C2_8, C3_8}, - {0, C1_14, C2_14, C3_14}, - {0, C1_15, C2_15, C3_15}, - {0, C1_16, C2_16, C3_16}, +// {0, C1_6, C2_6, C3_6}, +// {0, C1_7, C2_7, C3_7}, +// {0, C1_8, C2_8, C3_8}, +// {0, C1_14, C2_14, C3_14}, +// {0, C1_15, C2_15, C3_15}, +// {0, C1_16, C2_16, C3_16}, - {0, C9_1, C8_1, C7_1}, - {0, C9_2, C8_2, C7_2}, - {0, C9_3, C8_3, C7_3}, - {0, C9_9, C8_9, C7_9}, - {0, C9_10, C8_10, C7_10}, - {0, C9_11, C8_11, C7_11}, +// {0, C9_1, C8_1, C7_1}, +// {0, C9_2, C8_2, C7_2}, +// {0, C9_3, C8_3, C7_3}, +// {0, C9_9, C8_9, C7_9}, +// {0, C9_10, C8_10, C7_10}, +// {0, C9_11, C8_11, C7_11}, - {0, C9_4, C8_4, C7_4}, - {0, C9_5, C8_5, C7_5}, - {0, C9_6, C8_6, C7_6}, - {0, C9_12, C8_12, C7_12}, - {0, C9_13, C8_13, C7_13}, - {0, C9_14, C8_14, C7_14} -}; +// {0, C9_4, C8_4, C7_4}, +// {0, C9_5, C8_5, C7_5}, +// {0, C9_6, C8_6, C7_6}, +// {0, C9_12, C8_12, C7_12}, +// {0, C9_13, C8_13, C7_13}, +// {0, C9_14, C8_14, C7_14} +// }; -const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = { +// const rgb_led g_rgb_leds[DRIVER_LED_TOTAL] = { - /*{row | col << 4} - | {x=0..224, y=0..64} - | | modifier - | | | */ - {{0|(0<<4)}, {20.36*0, 21.33*0}, 1}, - {{0|(1<<4)}, {20.36*1, 21.33*0}, 0}, - {{0|(2<<4)}, {20.36*2, 21.33*0}, 0}, - {{0|(3<<4)}, {20.36*3, 21.33*0}, 0}, - {{0|(4<<4)}, {20.36*4, 21.33*0}, 0}, - {{0|(5<<4)}, {20.36*5, 21.33*0}, 0}, +// {row | col << 4} +// | {x=0..224, y=0..64} +// | | modifier +// | | | +// {{0|(0<<4)}, {20.36*0, 21.33*0}, 1}, +// {{0|(1<<4)}, {20.36*1, 21.33*0}, 0}, +// {{0|(2<<4)}, {20.36*2, 21.33*0}, 0}, +// {{0|(3<<4)}, {20.36*3, 21.33*0}, 0}, +// {{0|(4<<4)}, {20.36*4, 21.33*0}, 0}, +// {{0|(5<<4)}, {20.36*5, 21.33*0}, 0}, - {{1|(0<<4)}, {20.36*0, 21.33*1}, 1}, - {{1|(1<<4)}, {20.36*1, 21.33*1}, 0}, - {{1|(2<<4)}, {20.36*2, 21.33*1}, 0}, - {{1|(3<<4)}, {20.36*3, 21.33*1}, 0}, - {{1|(4<<4)}, {20.36*4, 21.33*1}, 0}, - {{1|(5<<4)}, {20.36*5, 21.33*1}, 0}, +// {{1|(0<<4)}, {20.36*0, 21.33*1}, 1}, +// {{1|(1<<4)}, {20.36*1, 21.33*1}, 0}, +// {{1|(2<<4)}, {20.36*2, 21.33*1}, 0}, +// {{1|(3<<4)}, {20.36*3, 21.33*1}, 0}, +// {{1|(4<<4)}, {20.36*4, 21.33*1}, 0}, +// {{1|(5<<4)}, {20.36*5, 21.33*1}, 0}, - {{2|(0<<4)}, {20.36*0, 21.33*2}, 1}, - {{2|(1<<4)}, {20.36*1, 21.33*2}, 0}, - {{2|(2<<4)}, {20.36*2, 21.33*2}, 0}, - {{2|(3<<4)}, {20.36*3, 21.33*2}, 0}, - {{2|(4<<4)}, {20.36*4, 21.33*2}, 0}, - {{2|(5<<4)}, {20.36*5, 21.33*2}, 0}, +// {{2|(0<<4)}, {20.36*0, 21.33*2}, 1}, +// {{2|(1<<4)}, {20.36*1, 21.33*2}, 0}, +// {{2|(2<<4)}, {20.36*2, 21.33*2}, 0}, +// {{2|(3<<4)}, {20.36*3, 21.33*2}, 0}, +// {{2|(4<<4)}, {20.36*4, 21.33*2}, 0}, +// {{2|(5<<4)}, {20.36*5, 21.33*2}, 0}, - {{3|(0<<4)}, {20.36*0, 21.33*3}, 1}, - {{3|(1<<4)}, {20.36*1, 21.33*3}, 1}, - {{3|(2<<4)}, {20.36*2, 21.33*3}, 1}, - {{3|(3<<4)}, {20.36*3, 21.33*3}, 1}, - {{3|(4<<4)}, {20.36*4, 21.33*3}, 1}, - {{3|(5<<4)}, {20.36*5, 21.33*3}, 0} -}; +// {{3|(0<<4)}, {20.36*0, 21.33*3}, 1}, +// {{3|(1<<4)}, {20.36*1, 21.33*3}, 1}, +// {{3|(2<<4)}, {20.36*2, 21.33*3}, 1}, +// {{3|(3<<4)}, {20.36*3, 21.33*3}, 1}, +// {{3|(4<<4)}, {20.36*4, 21.33*3}, 1}, +// {{3|(5<<4)}, {20.36*5, 21.33*3}, 0} +// }; diff --git a/keyboards/muon_light/rules.mk b/keyboards/muon_light/rules.mk index 7047f6566e..4cca7a3b0c 100644 --- a/keyboards/muon_light/rules.mk +++ b/keyboards/muon_light/rules.mk @@ -51,12 +51,13 @@ COMMAND_ENABLE = yes # Commands for debug and configuration NKRO_ENABLE = yes # USB Nkey Rollover CUSTOM_MATRIX = yes # Custom matrix file AUDIO_ENABLE = yes -RGB_MATRIX_ENABLE = yes -ENCODER_ENABLE = yes +# RGB_MATRIX_ENABLE = yes +# ENCODER_ENABLE = yes # SERIAL_LINK_ENABLE = yes +I2C_SLAVE_ENABLE = yes +QWIIC_KEYBOARD_ENABLE = yes # Do not enable SLEEP_LED_ENABLE. it uses the same timer as BACKLIGHT_ENABLE SLEEP_LED_ENABLE = no # Breathing sleep LED during USB suspend LAYOUTS = ortho_4x6 -LAYOUTS_HAS_RGB = no diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 4eff764e2d..07f6c6eb33 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -69,6 +69,9 @@ along with this program. If not, see . #ifdef MIDI_ENABLE # include "process_midi.h" #endif +#ifdef QWIIC_KEYBOARD_ENABLE +# include "qwiic/qwiic_keyboard.h" +#endif #ifdef MATRIX_HAS_GHOST extern const uint16_t keymaps[][MATRIX_ROWS][MATRIX_COLS]; @@ -181,11 +184,14 @@ void keyboard_init(void) { #if defined(NKRO_ENABLE) && defined(FORCE_NKRO) keymap_config.nkro = 1; #endif +#ifdef QWIIC_KEYBOARD_ENABLE + qwiic_keyboard_init(); +#endif } /** \brief Keyboard task: Do keyboard routine jobs * - * Do routine keyboard jobs: + * Do routine keyboard jobs: * * * scan matrix * * handle mouse movements @@ -291,6 +297,10 @@ MATRIX_LOOP_END: midi_task(); #endif +#ifdef QWIIC_KEYBOARD_ENABLE + qwiic_keyboard_task(); +#endif + // update LED if (led_status != host_keyboard_leds()) { led_status = host_keyboard_leds(); From 0f89d7efed117a3e4f8f205d88a6e7c48dd96db4 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sat, 9 Jun 2018 17:57:15 -0400 Subject: [PATCH 50/59] try sound feedback --- drivers/arm/twi2c.c | 4 ++-- drivers/qwiic/qwiic_keyboard.c | 18 ++++++++++++------ 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index a4268d87e4..61a04d3743 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -112,8 +112,8 @@ uint8_t twi2c_receive(uint8_t address, uint8_t * data, uint16_t length) { } -uint8_t twi2c_incoming_body[512]; -uint8_t twi2c_outgoing_body[512]; +uint8_t twi2c_incoming_body[50]; +uint8_t twi2c_outgoing_body[1024]; // Response to received messages I2CSlaveMsg twi2c_incoming_message = { diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index d6e2357c96..2b3324021d 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -60,6 +60,8 @@ void qwiic_keyboard_set_master(void) { qwiic_keyboard_master = true; } +uint8_t command[1] = { 0x00 }; + void qwiic_keyboard_task(void) { if (USB_DRIVER.state == USB_ACTIVE) qwiic_keyboard_master = true; @@ -68,8 +70,8 @@ void qwiic_keyboard_task(void) { if (qwiic_keyboard_master) { if (qwiic_keyboard_connected) { // send empty message, expecting matrix info - twi2c_transmit(qwiic_keyboard_listening_address, NULL, 0); - if (MSG_OK == twi2c_receive(qwiic_keyboard_listening_address, + if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address, + command, 1, qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE )) { // majority of this is pulled from keyboard.c:keyboard_task() @@ -113,10 +115,10 @@ void qwiic_keyboard_task(void) { // disconnect // qwiic_keyboard_connected = false; } - } else { + } else { // if not connected // send new address to listen on, expect back keymap - twi2c_transmit(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, &qwiic_keyboard_new_listening_address, 1); - if (MSG_OK == twi2c_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, + if (MSG_OK == twi2c_transmit_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, + &qwiic_keyboard_new_listening_address, 1, qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE )) { qwiic_keyboard_connected = true; @@ -131,6 +133,8 @@ void qwiic_keyboard_task(void) { uint8_t qwiic_keyboard_reply[MATRIX_ROWS]; +float song_one_up[][2] = SONG(ONE_UP_SOUND); + void qwiic_keyboard_message_received(I2CDriver *i2cp, uint8_t * body, uint16_t size) { if (qwiic_keyboard_connected) { for (uint8_t row = 0; row < MATRIX_ROWS; row++) { @@ -146,6 +150,8 @@ void qwiic_keyboard_message_received(I2CDriver *i2cp, uint8_t * body, uint16_t s twi2c_stop(); twi2c_start(); twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received_ptr); + stop_all_notes(); + PLAY_SONG(song_one_up); } } @@ -169,7 +175,7 @@ void qwiic_keyboard_read_keymap(uint8_t * pointer) { for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { for (uint8_t col = 0; col < QWIIC_KEYBOARD_COLS; col++) { uint16_t keycode = *pointer++; - keycode |= (*pointer++) << 8; + keycode |= ((*pointer++) << 8); qwiic_keyboard_keymap[layer][row][col] = keycode; } } From 13f49ad8d9666c9c6b860075188a93a37f8eb399 Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sat, 9 Jun 2018 23:53:26 -0400 Subject: [PATCH 51/59] all a's working --- drivers/arm/twi2c.c | 5 ++++ drivers/arm/twi2c.h | 1 + drivers/qwiic/qwiic_keyboard.c | 44 +++++++++++++++++----------------- 3 files changed, 28 insertions(+), 22 deletions(-) diff --git a/drivers/arm/twi2c.c b/drivers/arm/twi2c.c index 61a04d3743..973a822430 100644 --- a/drivers/arm/twi2c.c +++ b/drivers/arm/twi2c.c @@ -157,6 +157,11 @@ uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback) return 0; } +uint8_t twi2c_restart_listening(uint8_t address) { + i2cMatchAddress(&I2C_DRIVER, address/2); + return 0; +} + void twi2c_stop(void) { i2cUnmatchAll(&I2C_DRIVER); i2cStop(&I2C_DRIVER); diff --git a/drivers/arm/twi2c.h b/drivers/arm/twi2c.h index 047c28e8b0..daa55fb2d1 100644 --- a/drivers/arm/twi2c.h +++ b/drivers/arm/twi2c.h @@ -43,5 +43,6 @@ void twi2c_stop(void); uint8_t twi2c_reply(I2CDriver * i2cp, uint8_t * data, uint16_t length); uint8_t twi2c_transmit_receive(uint8_t address, uint8_t * tx_body, uint16_t tx_length, uint8_t * rx_body, uint16_t rx_length); uint8_t twi2c_start_listening(uint8_t address, twi2c_message_received callback); +uint8_t twi2c_restart_listening(uint8_t address); #endif diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 2b3324021d..088c70f848 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -44,14 +44,13 @@ uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {0}; -uint8_t qwiic_keyboard_new_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; uint8_t qwiic_keyboard_processing_slave = false; void qwiic_keyboard_init(void) { twi2c_init(); twi2c_start(); - twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received_ptr); + twi2c_start_listening(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, qwiic_keyboard_message_received_ptr); } void qwiic_keyboard_set_master(void) { @@ -79,12 +78,11 @@ void qwiic_keyboard_task(void) { qwiic_matrix_t matrix_row = 0; qwiic_matrix_t matrix_change = 0; qwiic_keyboard_processing_slave = true; - SEND_STRING("K."); for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { matrix_row = qwiic_keyboard_matrix_message[r]; matrix_change = matrix_row ^ matrix_prev[r]; if (matrix_change) { - for (uint8_t c = 0; c < MATRIX_COLS; c++) { + for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) { if (matrix_change & ((qwiic_matrix_t)1<= QMK_KEYS_PER_SCAN) #endif // process a key per task call - goto MATRIX_LOOP_END; + //goto MATRIX_LOOP_END; } } } @@ -109,7 +107,7 @@ void qwiic_keyboard_task(void) { if (!keys_processed) #endif action_exec(TICK); - MATRIX_LOOP_END: + //MATRIX_LOOP_END: qwiic_keyboard_processing_slave = false; } else { // disconnect @@ -118,12 +116,10 @@ void qwiic_keyboard_task(void) { } else { // if not connected // send new address to listen on, expect back keymap if (MSG_OK == twi2c_transmit_receive(QWIIC_KEYBOARD_HANDSHAKE_ADDRESS, - &qwiic_keyboard_new_listening_address, 1, + &qwiic_keyboard_listening_address, 1, qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE )) { qwiic_keyboard_connected = true; - // increment address (for future implemenations of supporting multiple devices) - qwiic_keyboard_new_listening_address+=2; // load keymap into memory qwiic_keyboard_read_keymap(qwiic_keyboard_handshake_message); } @@ -131,27 +127,30 @@ void qwiic_keyboard_task(void) { } } -uint8_t qwiic_keyboard_reply[MATRIX_ROWS]; - float song_one_up[][2] = SONG(ONE_UP_SOUND); +bool first_message = true; void qwiic_keyboard_message_received(I2CDriver *i2cp, uint8_t * body, uint16_t size) { if (qwiic_keyboard_connected) { - for (uint8_t row = 0; row < MATRIX_ROWS; row++) { - qwiic_keyboard_reply[row] = matrix_get_row(row); + for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { + if (row < MATRIX_ROWS) { + qwiic_keyboard_matrix_message[row] = matrix_get_row(row); + } else { + qwiic_keyboard_matrix_message[row] = 0; + } + } + twi2c_reply(i2cp, qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); + if (first_message) { + PLAY_SONG(song_one_up); + first_message = false; } - twi2c_reply(i2cp, qwiic_keyboard_reply, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE); } else { qwiic_keyboard_connected = true; qwiic_keyboard_master = false; qwiic_keyboard_listening_address = body[0]; - qwiic_keyboard_write_keymap(qwiic_keyboard_reply); - twi2c_reply(i2cp, qwiic_keyboard_reply, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE); - twi2c_stop(); - twi2c_start(); - twi2c_start_listening(qwiic_keyboard_listening_address, qwiic_keyboard_message_received_ptr); - stop_all_notes(); - PLAY_SONG(song_one_up); + twi2c_restart_listening(qwiic_keyboard_listening_address); + qwiic_keyboard_write_keymap(qwiic_keyboard_handshake_message); + twi2c_reply(i2cp, qwiic_keyboard_handshake_message, QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE); } } @@ -191,7 +190,8 @@ bool is_keyboard_master(void) { uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) { if (qwiic_keyboard_processing_slave) { // trick the built-in handling to accept our replacement keymap - return qwiic_keyboard_keymap[(layer)][(key.row)][(key.col)]; + //return qwiic_keyboard_keymap[(layer)][(key.row)][(key.col)]; + return KC_A; } else { // Read entire word (16bits) return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]); From d01f40edbf1e0c2e8d5927141767f6cd578bb5db Mon Sep 17 00:00:00 2001 From: Jack Humbert Date: Sun, 10 Jun 2018 00:25:21 -0400 Subject: [PATCH 52/59] workingggg --- drivers/qwiic/qwiic_keyboard.c | 15 +++++++++------ keyboards/muon_light/config.h | 2 +- 2 files changed, 10 insertions(+), 7 deletions(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 088c70f848..52c7d87935 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -77,6 +77,9 @@ void qwiic_keyboard_task(void) { static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS]; qwiic_matrix_t matrix_row = 0; qwiic_matrix_t matrix_change = 0; + #ifdef QMK_KEYS_PER_SCAN + uint8_t keys_processed = 0; + #endif qwiic_keyboard_processing_slave = true; for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { matrix_row = qwiic_keyboard_matrix_message[r]; @@ -96,7 +99,7 @@ void qwiic_keyboard_task(void) { if (++keys_processed >= QMK_KEYS_PER_SCAN) #endif // process a key per task call - //goto MATRIX_LOOP_END; + goto QWIIC_MATRIX_LOOP_END; } } } @@ -107,7 +110,7 @@ void qwiic_keyboard_task(void) { if (!keys_processed) #endif action_exec(TICK); - //MATRIX_LOOP_END: + QWIIC_MATRIX_LOOP_END: qwiic_keyboard_processing_slave = false; } else { // disconnect @@ -173,8 +176,8 @@ void qwiic_keyboard_read_keymap(uint8_t * pointer) { for (uint8_t layer = 0; layer < QWIIC_KEYBOARD_LAYERS; layer++) { for (uint8_t row = 0; row < QWIIC_KEYBOARD_ROWS; row++) { for (uint8_t col = 0; col < QWIIC_KEYBOARD_COLS; col++) { - uint16_t keycode = *pointer++; - keycode |= ((*pointer++) << 8); + uint16_t keycode = ((*pointer++) << 8); + keycode |= (*pointer++); qwiic_keyboard_keymap[layer][row][col] = keycode; } } @@ -190,8 +193,8 @@ bool is_keyboard_master(void) { uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) { if (qwiic_keyboard_processing_slave) { // trick the built-in handling to accept our replacement keymap - //return qwiic_keyboard_keymap[(layer)][(key.row)][(key.col)]; - return KC_A; + return qwiic_keyboard_keymap[(layer)][(key.row)][(key.col)]; + //return KC_A; } else { // Read entire word (16bits) return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]); diff --git a/keyboards/muon_light/config.h b/keyboards/muon_light/config.h index b8df031a4a..d76b140577 100644 --- a/keyboards/muon_light/config.h +++ b/keyboards/muon_light/config.h @@ -57,7 +57,7 @@ along with this program. If not, see . #define ENCODERS_PAD_B { B13 } /* Debounce reduces chatter (unintended double-presses) - set 0 if debouncing is not needed */ -#define DEBOUNCE 0 +#define DEBOUNCE 6 /* Prevent modifiers from being stuck on after layer changes. */ #define PREVENT_STUCK_MODIFIERS From 3775c92ff88cbd72f53ed97709932a5352495092 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Sat, 23 Jun 2018 00:14:22 +0300 Subject: [PATCH 53/59] Fix missing brackets warning --- drivers/qwiic/qwiic_keyboard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 52c7d87935..8542a9f2b9 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -43,7 +43,7 @@ uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; -uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {0}; +uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; uint8_t qwiic_keyboard_processing_slave = false; From c11c7948e6c6814aa9df509c2d718b200820da60 Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 17:10:03 +0300 Subject: [PATCH 54/59] Make the layer cache more efficient Also change the internal representation to a one dimensional array --- tests/layer_cache/config.h | 21 ++++ tests/layer_cache/keymap.c | 24 +++++ tests/layer_cache/rules.mk | 16 +++ tests/layer_cache/test_layer_cache.cpp | 140 +++++++++++++++++++++++++ tmk_core/common/action_layer.c | 75 +++++++++---- 5 files changed, 256 insertions(+), 20 deletions(-) create mode 100644 tests/layer_cache/config.h create mode 100644 tests/layer_cache/keymap.c create mode 100644 tests/layer_cache/rules.mk create mode 100644 tests/layer_cache/test_layer_cache.cpp diff --git a/tests/layer_cache/config.h b/tests/layer_cache/config.h new file mode 100644 index 0000000000..656cedb338 --- /dev/null +++ b/tests/layer_cache/config.h @@ -0,0 +1,21 @@ +/* Copyright 2018 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#pragma once + +#define MATRIX_ROWS 2 +#define MATRIX_COLS 2 +#define PREVENT_STUCK_MODIFIERS diff --git a/tests/layer_cache/keymap.c b/tests/layer_cache/keymap.c new file mode 100644 index 0000000000..d310bff8b9 --- /dev/null +++ b/tests/layer_cache/keymap.c @@ -0,0 +1,24 @@ +/* Copyright 2018 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "quantum.h" + +const uint16_t PROGMEM keymaps[][MATRIX_ROWS][MATRIX_COLS] = { + [0] = { + {KC_A, KC_B}, + {KC_C, KC_D}, + } +}; diff --git a/tests/layer_cache/rules.mk b/tests/layer_cache/rules.mk new file mode 100644 index 0000000000..9b8615f954 --- /dev/null +++ b/tests/layer_cache/rules.mk @@ -0,0 +1,16 @@ +# Copyright 2018 Fred Sundvik +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +CUSTOM_MATRIX=yes diff --git a/tests/layer_cache/test_layer_cache.cpp b/tests/layer_cache/test_layer_cache.cpp new file mode 100644 index 0000000000..4aebe24b74 --- /dev/null +++ b/tests/layer_cache/test_layer_cache.cpp @@ -0,0 +1,140 @@ +/* Copyright 2018 Fred Sundvik + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "test_common.hpp" + +#if MAX_LAYER_BITS != 5 +#error "Tese tests assume that the MAX_LAYER_BITS is equal to 5" +// If this is changed, change the constants below +#endif + +#if MATRIX_COLS != 2 || MATRIX_ROWS !=2 +#error "These tests assume that the second row starts after the second column" +#endif + +namespace +{ + constexpr uint8_t max_layer_value = 0b11111; + constexpr uint8_t min_layer_value = 0; + constexpr uint8_t alternating_starting_with_1 = 0b10101; + constexpr uint8_t alternating_starting_with_0 = 0b01010; + + + uint8_t read_cache(uint8_t col, uint8_t row) { + keypos_t key; + key.col = col; + key.row = row; + return read_source_layers_cache(key); + } + + void write_cache(uint8_t col, uint8_t row, uint8_t value) { + keypos_t key; + key.col = col; + key.row = row; + return update_source_layers_cache(key, value); + } + + void fill_cache() { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + write_cache(j, i, max_layer_value); + } + } + } + + void clear_cache() { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + write_cache(j, i, min_layer_value); + } + } + } +} + +class LayerCache : public testing::Test +{ +public: + LayerCache() + { + clear_cache(); + } +}; + +TEST_F(LayerCache, LayerCacheIsInitializedToZero) { + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + EXPECT_EQ(read_cache(j, i), min_layer_value); + } + } +} + +TEST_F(LayerCache, FillAndClearCache) { + fill_cache(); + clear_cache(); + for (int i=0; i < MATRIX_ROWS; i++) { + for (int j=0; j < MATRIX_COLS; j++) { + EXPECT_EQ(read_cache(j, i), min_layer_value); + } + } +} + +TEST_F(LayerCache, WriteAndReadFirstPosMaximumValue) { + write_cache(0, 0, max_layer_value); + EXPECT_EQ(read_cache(0, 0), max_layer_value); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosMaximumValue) { + write_cache(1, 0, max_layer_value); + EXPECT_EQ(read_cache(1, 0), max_layer_value); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadFirstPosAlternatingBitsStartingWith1) { + write_cache(0, 0, alternating_starting_with_1); + EXPECT_EQ(read_cache(0, 0), alternating_starting_with_1); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosAlternatingBitsStartingWith1) { + write_cache(1, 0, alternating_starting_with_1); + EXPECT_EQ(read_cache(1, 0), alternating_starting_with_1); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadFirstPosAlternatingBitsStartingWith0) { + write_cache(0, 0, alternating_starting_with_0); + EXPECT_EQ(read_cache(0, 0), alternating_starting_with_0); + // The second position should not be updated + EXPECT_EQ(read_cache(1, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} + +TEST_F(LayerCache, WriteAndReadSecondPosAlternatingBitsStartingWith0) { + write_cache(1, 0, alternating_starting_with_0); + EXPECT_EQ(read_cache(1, 0), alternating_starting_with_0); + // The surrounding positions should not be updated + EXPECT_EQ(read_cache(0, 0), min_layer_value); + EXPECT_EQ(read_cache(0, 1), min_layer_value); +} diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index f3cd381ab0..a1ead402c8 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -220,37 +220,72 @@ void layer_debug(void) #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS + 7) / 8][MAX_LAYER_BITS] = {{0}}; +uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; +static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; void update_source_layers_cache(keypos_t key, uint8_t layer) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; + const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint32_t bit_number = key_number * MAX_LAYER_BITS; + const uint16_t byte_number = bit_number / 8; + if (byte_number >= sizeof(source_layers_cache)) { + return; + } + const uint8_t bit_position = bit_number % 8; + int8_t shift = 16 - MAX_LAYER_BITS - bit_position; - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - source_layers_cache[storage_row][bit_number] ^= - (-((layer & (1U << bit_number)) != 0) - ^ source_layers_cache[storage_row][bit_number]) - & (1U << storage_bit); + if (shift > 8 ) { + // We need to write only one byte + shift -= 8; + const uint8_t mask = layer_cache_mask << shift; + const uint8_t shifted_layer = layer << shift; + source_layers_cache[byte_number] = (shifted_layer & mask) | (source_layers_cache[byte_number] & (~mask)); + } else { + if (byte_number + 1 >= sizeof(source_layers_cache)) { + return; } + // We need to write two bytes + uint16_t value = layer; + uint16_t mask = layer_cache_mask; + value <<= shift; + mask <<= shift; + + uint16_t masked_value = value & mask; + uint16_t inverse_mask = ~mask; + + // This could potentially be done with a single write, but then we have to assume the endian + source_layers_cache[byte_number + 1] = masked_value | (source_layers_cache[byte_number + 1] & (inverse_mask)); + masked_value >>= 8; + inverse_mask >>= 8; + source_layers_cache[byte_number] = masked_value | (source_layers_cache[byte_number] & (inverse_mask)); + } } uint8_t read_source_layers_cache(keypos_t key) { - const uint8_t key_number = key.col + (key.row * MATRIX_COLS); - const uint8_t storage_row = key_number / 8; - const uint8_t storage_bit = key_number % 8; - uint8_t layer = 0; + const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint32_t bit_number = key_number * MAX_LAYER_BITS; + const uint16_t byte_number = bit_number / 8; + if (byte_number >= sizeof(source_layers_cache)) { + return 0; + } + const uint8_t bit_position = bit_number % 8; - for (uint8_t bit_number = 0; bit_number < MAX_LAYER_BITS; bit_number++) { - layer |= - ((source_layers_cache[storage_row][bit_number] - & (1U << storage_bit)) != 0) - << bit_number; + int8_t shift = 16 - MAX_LAYER_BITS - bit_position; + + if (shift > 8 ) { + // We need to read only one byte + shift -= 8; + return (source_layers_cache[byte_number] >> shift) & layer_cache_mask; + } else { + if (byte_number + 1 >= sizeof(source_layers_cache)) { + return 0; } - - return layer; + // Otherwise read two bytes + // This could potentially be done with a single read, but then we have to assume the endian + uint16_t value = source_layers_cache[byte_number] << 8 | source_layers_cache[byte_number + 1]; + return (value >> shift) & layer_cache_mask; + } } #endif From f9c61b1bbe14ffb9d00107fcb68e86dcba6eb22a Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 17:21:00 +0300 Subject: [PATCH 55/59] Add a keymatrix_t type This contains both the matrix number and key position, in preparation for multi-matrix support --- drivers/qwiic/qwiic_keyboard.c | 16 +++++++--------- .../planck/old_keymap_files/keymap_common.c | 2 +- quantum/keymap.h | 2 +- quantum/keymap_common.c | 8 +++++--- quantum/process_keycode/process_music.c | 13 +++++++------ quantum/quantum.c | 2 +- tests/layer_cache/test_layer_cache.cpp | 14 ++++++++------ tmk_core/common/action.c | 2 +- tmk_core/common/action.h | 4 ++-- tmk_core/common/action_layer.c | 14 +++++++------- tmk_core/common/action_layer.h | 10 +++++----- tmk_core/common/bootmagic.c | 2 +- tmk_core/common/keyboard.c | 3 ++- tmk_core/common/keyboard.h | 16 +++++++++++----- 14 files changed, 59 insertions(+), 49 deletions(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 8542a9f2b9..8e3591fd9d 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -80,7 +80,6 @@ void qwiic_keyboard_task(void) { #ifdef QMK_KEYS_PER_SCAN uint8_t keys_processed = 0; #endif - qwiic_keyboard_processing_slave = true; for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { matrix_row = qwiic_keyboard_matrix_message[r]; matrix_change = matrix_row ^ matrix_prev[r]; @@ -88,7 +87,8 @@ void qwiic_keyboard_task(void) { for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) { if (matrix_change & ((qwiic_matrix_t)1<. /* translates key to keycode */ -uint8_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +uint8_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { return pgm_read_byte(&keymaps[(layer)][(key.row)][(key.col)]); } diff --git a/quantum/keymap.h b/quantum/keymap.h index bfcb2f7cd5..734d128573 100644 --- a/quantum/keymap.h +++ b/quantum/keymap.h @@ -44,7 +44,7 @@ along with this program. If not, see . #include "quantum_keycodes.h" // translates key to keycode -uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key); +uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key); // translates function id to action uint16_t keymap_function_id_to_action( uint16_t function_id ); diff --git a/quantum/keymap_common.c b/quantum/keymap_common.c index 9a412b66ad..d68001bb65 100644 --- a/quantum/keymap_common.c +++ b/quantum/keymap_common.c @@ -38,7 +38,7 @@ extern keymap_config_t keymap_config; #include /* converts key to action */ -action_t action_for_key(uint8_t layer, keypos_t key) +action_t action_for_key(uint8_t layer, keymatrix_t key) { // 16bit keycodes - important uint16_t keycode = keymap_key_to_keycode(layer, key); @@ -184,10 +184,12 @@ void action_function(keyrecord_t *record, uint8_t id, uint8_t opt) // translates key to keycode __attribute__ ((weak)) -uint16_t keymap_key_to_keycode(uint8_t layer, keypos_t key) +uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { // Read entire word (16bits) - return pgm_read_word(&keymaps[(layer)][(key.row)][(key.col)]); + // The default implmention does not have multiple matrix support + // and therfore it ignores the matrix field of the key + return pgm_read_word(&keymaps[(layer)][(key.pos.row)][(key.pos.col)]); } // translates function id to action diff --git a/quantum/process_keycode/process_music.c b/quantum/process_keycode/process_music.c index 697aa237fa..fc6de4350a 100644 --- a/quantum/process_keycode/process_music.c +++ b/quantum/process_keycode/process_music.c @@ -198,22 +198,23 @@ bool process_music(uint16_t keycode, keyrecord_t *record) { } uint8_t note = 36; + // Note: Multimatrix support is missing from this (it's probablly better to define it using keycodes) #ifdef MUSIC_MAP if (music_mode == MUSIC_MODE_CHROMATIC) { - note = music_starting_note + music_offset + 36 + music_map[record->event.key.row][record->event.key.col]; + note = music_starting_note + music_offset + 36 + music_map[record->event.key.pos.row][record->event.key.pos.col]; } else { - uint8_t position = music_map[record->event.key.row][record->event.key.col]; + uint8_t position = music_map[record->event.key.pos.row][record->event.key.pos.col]; note = music_starting_note + music_offset + 36 + SCALE[position % 12] + (position / 12)*12; } #else if (music_mode == MUSIC_MODE_CHROMATIC) - note = (music_starting_note + record->event.key.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset - 3)+12*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_GUITAR) - note = (music_starting_note + record->event.key.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset + 32)+5*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_VIOLIN) - note = (music_starting_note + record->event.key.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + record->event.key.pos.col + music_offset + 32)+7*(MATRIX_ROWS - record->event.key.pos.row); else if (music_mode == MUSIC_MODE_MAJOR) - note = (music_starting_note + SCALE[record->event.key.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.row); + note = (music_starting_note + SCALE[record->event.key.pos.col + music_offset] - 3)+12*(MATRIX_ROWS - record->event.key.pos.row); else note = music_starting_note; #endif diff --git a/quantum/quantum.c b/quantum/quantum.c index 331ed5634c..086c1160b4 100644 --- a/quantum/quantum.c +++ b/quantum/quantum.c @@ -190,7 +190,7 @@ static bool grave_esc_was_shifted = false; bool process_record_quantum(keyrecord_t *record) { /* This gets the keycode from the key pressed */ - keypos_t key = record->event.key; + keymatrix_t key = record->event.key; uint16_t keycode; #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) diff --git a/tests/layer_cache/test_layer_cache.cpp b/tests/layer_cache/test_layer_cache.cpp index 4aebe24b74..cc58cbbdba 100644 --- a/tests/layer_cache/test_layer_cache.cpp +++ b/tests/layer_cache/test_layer_cache.cpp @@ -34,16 +34,18 @@ namespace uint8_t read_cache(uint8_t col, uint8_t row) { - keypos_t key; - key.col = col; - key.row = row; + keymatrix_t key; + key.pos.col = col; + key.pos.row = row; + key.matrix = 0; return read_source_layers_cache(key); } void write_cache(uint8_t col, uint8_t row, uint8_t value) { - keypos_t key; - key.col = col; - key.row = row; + keymatrix_t key; + key.pos.col = col; + key.pos.row = row; + key.matrix = 0; return update_source_layers_cache(key, value); } diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index f7c039f457..cfc933fb28 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -892,7 +892,7 @@ void clear_keyboard_but_mods(void) * * FIXME: Needs documentation. */ -bool is_tap_key(keypos_t key) +bool is_tap_key(keymatrix_t key) { action_t action = layer_switch_get_action(key); diff --git a/tmk_core/common/action.h b/tmk_core/common/action.h index acc55c7d38..7b69c6c282 100644 --- a/tmk_core/common/action.h +++ b/tmk_core/common/action.h @@ -50,7 +50,7 @@ typedef struct { void action_exec(keyevent_t event); /* action for key */ -action_t action_for_key(uint8_t layer, keypos_t key); +action_t action_for_key(uint8_t layer, keymatrix_t key); /* macro */ const macro_t *action_get_macro(keyrecord_t *record, uint8_t id, uint8_t opt); @@ -94,7 +94,7 @@ void unregister_mods(uint8_t mods); void clear_keyboard(void); void clear_keyboard_but_mods(void); void layer_switch(uint8_t new_layer); -bool is_tap_key(keypos_t key); +bool is_tap_key(keymatrix_t key); #ifndef NO_ACTION_TAPPING void process_record_tap_hint(keyrecord_t *record); diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index a1ead402c8..6bcf3d935d 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -223,9 +223,9 @@ void layer_debug(void) uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; -void update_source_layers_cache(keypos_t key, uint8_t layer) +void update_source_layers_cache(keymatrix_t key, uint8_t layer) { - const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; if (byte_number >= sizeof(source_layers_cache)) { @@ -261,9 +261,9 @@ void update_source_layers_cache(keypos_t key, uint8_t layer) } } -uint8_t read_source_layers_cache(keypos_t key) +uint8_t read_source_layers_cache(keymatrix_t key) { - const uint16_t key_number = key.col + (key.row * MATRIX_COLS); + const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; if (byte_number >= sizeof(source_layers_cache)) { @@ -296,7 +296,7 @@ uint8_t read_source_layers_cache(keypos_t key) * when the layer is switched after the down event but before the up * event as they may get stuck otherwise. */ -action_t store_or_get_action(bool pressed, keypos_t key) +action_t store_or_get_action(bool pressed, keymatrix_t key) { #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) if (disable_action_cache) { @@ -323,7 +323,7 @@ action_t store_or_get_action(bool pressed, keypos_t key) * * FIXME: Needs docs */ -int8_t layer_switch_get_layer(keypos_t key) +int8_t layer_switch_get_layer(keymatrix_t key) { #ifndef NO_ACTION_LAYER action_t action; @@ -350,7 +350,7 @@ int8_t layer_switch_get_layer(keypos_t key) * * FIXME: Needs docs */ -action_t layer_switch_get_action(keypos_t key) +action_t layer_switch_get_action(keymatrix_t key) { return action_for_key(layer_switch_get_layer(key), key); } diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index 72a6bd8f68..8f47fb0c96 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -91,15 +91,15 @@ uint32_t layer_state_set_kb(uint32_t state); #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) /* The number of bits needed to represent the layer number: log2(32). */ #define MAX_LAYER_BITS 5 -void update_source_layers_cache(keypos_t key, uint8_t layer); -uint8_t read_source_layers_cache(keypos_t key); +void update_source_layers_cache(keymatrix_t key, uint8_t layer); +uint8_t read_source_layers_cache(keymatrix_t key); #endif -action_t store_or_get_action(bool pressed, keypos_t key); +action_t store_or_get_action(bool pressed, keymatrix_t key); /* return the topmost non-transparent layer currently associated with key */ -int8_t layer_switch_get_layer(keypos_t key); +int8_t layer_switch_get_layer(keymatrix_t key); /* return action depending on current layer status */ -action_t layer_switch_get_action(keypos_t key); +action_t layer_switch_get_action(keymatrix_t key); #endif diff --git a/tmk_core/common/bootmagic.c b/tmk_core/common/bootmagic.c index 9f79fb8eed..828769c322 100644 --- a/tmk_core/common/bootmagic.c +++ b/tmk_core/common/bootmagic.c @@ -116,7 +116,7 @@ static bool scan_keycode(uint8_t keycode) matrix_row_t matrix_row = matrix_get_row(r); for (uint8_t c = 0; c < MATRIX_COLS; c++) { if (matrix_row & ((matrix_row_t)1< Date: Fri, 29 Jun 2018 20:48:08 +0300 Subject: [PATCH 56/59] Add proper multimatrix support --- drivers/qwiic/qwiic_keyboard.c | 87 +++++++++---------- tmk_core/common/action_layer.c | 49 ++++++++--- tmk_core/common/action_layer.h | 2 + tmk_core/common/keyboard.c | 151 +++++++++++++++++++++++++-------- tmk_core/common/keyboard.h | 3 + 5 files changed, 195 insertions(+), 97 deletions(-) diff --git a/drivers/qwiic/qwiic_keyboard.c b/drivers/qwiic/qwiic_keyboard.c index 8e3591fd9d..4c7e22fdee 100644 --- a/drivers/qwiic/qwiic_keyboard.c +++ b/drivers/qwiic/qwiic_keyboard.c @@ -37,15 +37,15 @@ void qwiic_keyboard_write_keymap(uint8_t * pointer); void qwiic_keyboard_read_keymap(uint8_t * pointer); -bool qwiic_keyboard_master = false; -bool qwiic_keyboard_connected = false; -uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0}; -uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; -twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; +static bool qwiic_keyboard_master = false; +static bool qwiic_keyboard_connected = false; +static uint8_t qwiic_keyboard_handshake_message[QWIIC_KEYBOARD_HANDSHAKE_MESSAGE_SIZE] = {0}; +static uint8_t qwiic_keyboard_matrix_message[QWIIC_KEYBOARD_ROWS] = {0}; +static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS] = {0}; +static twi2c_message_received qwiic_keyboard_message_received_ptr = qwiic_keyboard_message_received; -uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; -uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; -uint8_t qwiic_keyboard_processing_slave = false; +static uint16_t qwiic_keyboard_keymap[QWIIC_KEYBOARD_LAYERS][QWIIC_KEYBOARD_ROWS][QWIIC_KEYBOARD_COLS] = {{{0}}}; +static uint8_t qwiic_keyboard_listening_address = QWIIC_KEYBOARD_LISTENING_ADDRESS_START; void qwiic_keyboard_init(void) { twi2c_init(); @@ -69,50 +69,10 @@ void qwiic_keyboard_task(void) { if (qwiic_keyboard_master) { if (qwiic_keyboard_connected) { // send empty message, expecting matrix info - if (MSG_OK == twi2c_transmit_receive(qwiic_keyboard_listening_address, + if (MSG_OK != twi2c_transmit_receive(qwiic_keyboard_listening_address, command, 1, qwiic_keyboard_matrix_message, QWIIC_KEYBOARD_MATRIX_MESSAGE_SIZE )) { - // majority of this is pulled from keyboard.c:keyboard_task() - static qwiic_matrix_t matrix_prev[QWIIC_KEYBOARD_ROWS]; - qwiic_matrix_t matrix_row = 0; - qwiic_matrix_t matrix_change = 0; - #ifdef QMK_KEYS_PER_SCAN - uint8_t keys_processed = 0; - #endif - for (uint8_t r = 0; r < QWIIC_KEYBOARD_ROWS; r++) { - matrix_row = qwiic_keyboard_matrix_message[r]; - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { - for (uint8_t c = 0; c < QWIIC_KEYBOARD_COLS; c++) { - if (matrix_change & ((qwiic_matrix_t)1<= QMK_KEYS_PER_SCAN) - #endif - // process a key per task call - goto QWIIC_MATRIX_LOOP_END; - } - } - } - } - // call with pseudo tick event when no real key event. - #ifdef QMK_KEYS_PER_SCAN - // we can get here with some keys processed now. - if (!keys_processed) - #endif - action_exec(TICK); - QWIIC_MATRIX_LOOP_END: - qwiic_keyboard_processing_slave = false; - } else { // disconnect // qwiic_keyboard_connected = false; } @@ -198,3 +158,32 @@ uint16_t keymap_key_to_keycode(uint8_t layer, keymatrix_t key) { return qwiic_keyboard_keymap[(layer)][(key.pos.row)][(key.pos.col)]; } } + +uint8_t multimatrix_get_num_matrices(void) { + return qwiic_keyboard_connected ? 1 : 0; +} + +uint8_t multimatrix_get_num_cols(uint8_t matrix) { + return QWIIC_KEYBOARD_COLS; +} + +uint8_t multimatrix_get_num_rows(uint8_t matrix) { + return QWIIC_KEYBOARD_ROWS; +} + +uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { +return qwiic_keyboard_matrix_message[row]; +} + +uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { + return matrix_prev[row]; +} + +void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { + matrix_prev[row] = value; +} + +uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { + static uint8_t source_layers_cache[(QWIIC_KEYBOARD_ROWS * QWIIC_KEYBOARD_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; + return source_layers_cache; +} diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index 6bcf3d935d..f01a3d99d8 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -220,15 +220,32 @@ void layer_debug(void) #endif #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) -uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; +__attribute__((weak)) +uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { + return 0; +} + +static uint8_t* get_source_layers_cache(keymatrix_t key) { + if (key.matrix == 0) { + static uint8_t source_layers_cache[(MATRIX_ROWS * MATRIX_COLS * MAX_LAYER_BITS + 7) / 8] = {0}; + return source_layers_cache; + } else { + return multimatrix_get_source_layers_cache(key.matrix - 1); + } +} + void update_source_layers_cache(keymatrix_t key, uint8_t layer) { - const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); + const uint8_t num_cols = keyboard_get_num_cols(key.matrix); + const uint8_t num_rows = keyboard_get_num_rows(key.matrix); + const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows); + uint8_t* cache = get_source_layers_cache(key); + const uint16_t key_number = key.pos.col + (key.pos.row * num_cols); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; - if (byte_number >= sizeof(source_layers_cache)) { + if (byte_number >= num_cache_bytes) { return; } const uint8_t bit_position = bit_number % 8; @@ -239,9 +256,9 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer) shift -= 8; const uint8_t mask = layer_cache_mask << shift; const uint8_t shifted_layer = layer << shift; - source_layers_cache[byte_number] = (shifted_layer & mask) | (source_layers_cache[byte_number] & (~mask)); + cache[byte_number] = (shifted_layer & mask) | (cache[byte_number] & (~mask)); } else { - if (byte_number + 1 >= sizeof(source_layers_cache)) { + if (byte_number + 1 >= num_cache_bytes) { return; } // We need to write two bytes @@ -254,19 +271,23 @@ void update_source_layers_cache(keymatrix_t key, uint8_t layer) uint16_t inverse_mask = ~mask; // This could potentially be done with a single write, but then we have to assume the endian - source_layers_cache[byte_number + 1] = masked_value | (source_layers_cache[byte_number + 1] & (inverse_mask)); + cache[byte_number + 1] = masked_value | (cache[byte_number + 1] & (inverse_mask)); masked_value >>= 8; inverse_mask >>= 8; - source_layers_cache[byte_number] = masked_value | (source_layers_cache[byte_number] & (inverse_mask)); + cache[byte_number] = masked_value | (cache[byte_number] & (inverse_mask)); } } uint8_t read_source_layers_cache(keymatrix_t key) { - const uint16_t key_number = key.pos.col + (key.pos.row * MATRIX_COLS); + const uint8_t num_cols = keyboard_get_num_cols(key.matrix); + const uint8_t num_rows = keyboard_get_num_rows(key.matrix); + const uint16_t num_cache_bytes = get_source_layers_cache_size(num_cols, num_rows); + uint8_t* cache = get_source_layers_cache(key); + const uint16_t key_number = key.pos.col + (key.pos.row * num_cols); const uint32_t bit_number = key_number * MAX_LAYER_BITS; const uint16_t byte_number = bit_number / 8; - if (byte_number >= sizeof(source_layers_cache)) { + if (byte_number >= num_cache_bytes) { return 0; } const uint8_t bit_position = bit_number % 8; @@ -276,17 +297,21 @@ uint8_t read_source_layers_cache(keymatrix_t key) if (shift > 8 ) { // We need to read only one byte shift -= 8; - return (source_layers_cache[byte_number] >> shift) & layer_cache_mask; + return (cache[byte_number] >> shift) & layer_cache_mask; } else { - if (byte_number + 1 >= sizeof(source_layers_cache)) { + if (byte_number + 1 >= num_cache_bytes) { return 0; } // Otherwise read two bytes // This could potentially be done with a single read, but then we have to assume the endian - uint16_t value = source_layers_cache[byte_number] << 8 | source_layers_cache[byte_number + 1]; + uint16_t value = cache[byte_number] << 8 | cache[byte_number + 1]; return (value >> shift) & layer_cache_mask; } } + +uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows) { + return (num_rows * num_cols * MAX_LAYER_BITS + 7) / 8; +} #endif /** \brief Store or get action (FIXME: Needs better summary) diff --git a/tmk_core/common/action_layer.h b/tmk_core/common/action_layer.h index 8f47fb0c96..c64d0df9df 100644 --- a/tmk_core/common/action_layer.h +++ b/tmk_core/common/action_layer.h @@ -93,6 +93,8 @@ uint32_t layer_state_set_kb(uint32_t state); #define MAX_LAYER_BITS 5 void update_source_layers_cache(keymatrix_t key, uint8_t layer); uint8_t read_source_layers_cache(keymatrix_t key); + +uint8_t get_source_layers_cache_size(uint8_t num_cols, uint8_t num_rows); #endif action_t store_or_get_action(bool pressed, keymatrix_t key); diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index c19661147b..36f7f76705 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -145,6 +145,82 @@ bool is_keyboard_master(void) { return true; } +__attribute__((weak)) +uint8_t multimatrix_get_num_matrices(void) { + return 0; +} + +__attribute__((weak)) +uint8_t multimatrix_get_num_cols(uint8_t matrix) { + return 0; +} + +__attribute__((weak)) +uint8_t multimatrix_get_num_rows(uint8_t matrix) { + return 0; +} + +__attribute__((weak)) +uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { + return 0; +} + +__attribute__((weak)) +uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { + return 0; +} + +__attribute__((weak)) +void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { +} + +static uint8_t get_num_matrices(void) { + return 1 + multimatrix_get_num_matrices(); +} + +uint8_t keyboard_get_num_cols(uint8_t matrix) { + if (matrix == 0) { + return MATRIX_COLS; + } else { + return multimatrix_get_num_cols(matrix - 1); + } +} + +uint8_t keyboard_get_num_rows(uint8_t matrix) { + if (matrix == 0) { + return MATRIX_ROWS; + } else { + return multimatrix_get_num_rows(matrix - 1); + } +} + +static uint32_t get_row(uint8_t matrix, uint8_t row) { + if (matrix == 0) { + return matrix_get_row(row); + } else { + return multimatrix_get_row(matrix - 1, row); + } +} + +static matrix_row_t matrix_prev[MATRIX_ROWS]; + +static uint32_t get_row_cache(uint8_t matrix, uint8_t row) { + if (matrix == 0) { + return matrix_prev[row]; + } else { + return multimatrix_get_row_cache(matrix - 1, row); + } +} + +static void set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { + if (matrix == 0) { + matrix_prev[row] = value; + } else { + return multimatrix_set_row_cache(matrix - 1, row, value); + } +} + + /** \brief keyboard_init * * FIXME: needs doc @@ -203,54 +279,57 @@ void keyboard_init(void) { */ void keyboard_task(void) { - static matrix_row_t matrix_prev[MATRIX_ROWS]; -#ifdef MATRIX_HAS_GHOST - // static matrix_row_t matrix_ghost[MATRIX_ROWS]; -#endif static uint8_t led_status = 0; - matrix_row_t matrix_row = 0; - matrix_row_t matrix_change = 0; + uint32_t matrix_row = 0; + uint32_t matrix_change = 0; #ifdef QMK_KEYS_PER_SCAN uint8_t keys_processed = 0; #endif matrix_scan(); if (is_keyboard_master()) { - for (uint8_t r = 0; r < MATRIX_ROWS; r++) { - matrix_row = matrix_get_row(r); - matrix_change = matrix_row ^ matrix_prev[r]; - if (matrix_change) { + for (uint8_t m = 0; m < get_num_matrices(); m++) { + uint8_t num_cols = keyboard_get_num_cols(m); + uint8_t num_rows = keyboard_get_num_rows(m); + for (uint8_t r = 0; r < num_rows; r++) { + matrix_row = get_row(m, r); + uint32_t row_cache = get_row_cache(m, r); + matrix_change = matrix_row ^ row_cache; + if (matrix_change) { #ifdef MATRIX_HAS_GHOST - if (has_ghost_in_row(r, matrix_row)) { - /* Keep track of whether ghosted status has changed for - * debugging. But don't update matrix_prev until un-ghosted, or - * the last key would be lost. - */ - //if (debug_matrix && matrix_ghost[r] != matrix_row) { - // matrix_print(); - //} + //NOTE: The we support ghosting only for the main matrix, since it's only useful for old keyboards without diodes + if (has_ghost_in_row(r, matrix_row)) { + /* Keep track of whether ghosted status has changed for + * debugging. But don't update matrix_prev until un-ghosted, or + * the last key would be lost. + */ + //if (debug_matrix && matrix_ghost[r] != matrix_row) { + // matrix_print(); + //} + //matrix_ghost[r] = matrix_row; + continue; + } //matrix_ghost[r] = matrix_row; - continue; - } - //matrix_ghost[r] = matrix_row; #endif - if (debug_matrix) matrix_print(); - for (uint8_t c = 0; c < MATRIX_COLS; c++) { - if (matrix_change & ((matrix_row_t)1<= QMK_KEYS_PER_SCAN) + // only jump out if we have processed "enough" keys. + if (++keys_processed >= QMK_KEYS_PER_SCAN) #endif - // process a key per task call - goto MATRIX_LOOP_END; + // process a key per task call + goto MATRIX_LOOP_END; + } } } } diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index 08f9979817..f3bbb1739d 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -72,6 +72,9 @@ void keyboard_task(void); /* it runs when host LED status is updated */ void keyboard_set_leds(uint8_t leds); +uint8_t keyboard_get_num_cols(uint8_t matrix); +uint8_t keyboard_get_num_rows(uint8_t matrix); + #ifdef __cplusplus } #endif From 9ddb678fd0af3276755a62e871a99263eb9d87ba Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 21:05:15 +0300 Subject: [PATCH 57/59] Document some functions --- tmk_core/common/action_layer.c | 5 +++ tmk_core/common/keyboard.c | 58 +++++++++++++++++++++++++++++++--- tmk_core/common/keyboard.h | 2 ++ 3 files changed, 61 insertions(+), 4 deletions(-) diff --git a/tmk_core/common/action_layer.c b/tmk_core/common/action_layer.c index f01a3d99d8..7c7cec7071 100644 --- a/tmk_core/common/action_layer.c +++ b/tmk_core/common/action_layer.c @@ -222,6 +222,11 @@ void layer_debug(void) #if !defined(NO_ACTION_LAYER) && defined(PREVENT_STUCK_MODIFIERS) static const uint8_t layer_cache_mask = (1u << MAX_LAYER_BITS) - 1; +/** \brief Get the pointer to the source layer cache for a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t* multimatrix_get_source_layers_cache(uint8_t matrix) { return 0; diff --git a/tmk_core/common/keyboard.c b/tmk_core/common/keyboard.c index 36f7f76705..076f11686c 100644 --- a/tmk_core/common/keyboard.c +++ b/tmk_core/common/keyboard.c @@ -145,39 +145,79 @@ bool is_keyboard_master(void) { return true; } +/** \brief Get the number of currently connected matrices + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: It should return the number of additional matrices, the master is always implied. + */ __attribute__((weak)) uint8_t multimatrix_get_num_matrices(void) { return 0; } +/** \brief Get the number of columns of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t multimatrix_get_num_cols(uint8_t matrix) { return 0; } +/** \brief Get the number of rows of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint8_t multimatrix_get_num_rows(uint8_t matrix) { return 0; } +/** \brief Get the row status of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint32_t multimatrix_get_row(uint8_t matrix, uint8_t row) { return 0; } +/** \brief Get the row cache of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) uint32_t multimatrix_get_row_cache(uint8_t matrix, uint8_t row) { return 0; } +/** \brief Set the row cache of a connected matrix + * + * Implement this if you support multiple matrices, see qwiic_keyboard.c for an example + * NOTE: The matrix index 0 is the first remote matrix, the function is not called for the master + */ __attribute__((weak)) void multimatrix_set_row_cache(uint8_t matrix, uint8_t row, uint32_t value) { } -static uint8_t get_num_matrices(void) { +/** \brief Get the number of currently connected matrices + * + * For normal keyboards this usually returns 1, but for multi-matrix keyboards this will + * return the total number of connected keyboards/modules including the master + */ +uint8_t keyboard_get_num_matrices(void) { return 1 + multimatrix_get_num_matrices(); } +/** \brief Get the number of columns of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ uint8_t keyboard_get_num_cols(uint8_t matrix) { if (matrix == 0) { return MATRIX_COLS; @@ -186,6 +226,11 @@ uint8_t keyboard_get_num_cols(uint8_t matrix) { } } +/** \brief Get the number of rows of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ uint8_t keyboard_get_num_rows(uint8_t matrix) { if (matrix == 0) { return MATRIX_ROWS; @@ -194,7 +239,12 @@ uint8_t keyboard_get_num_rows(uint8_t matrix) { } } -static uint32_t get_row(uint8_t matrix, uint8_t row) { +/** \brief Get the row status of a connected matrix + * + * Specify the matrix index to query connected multi-matrix keyboards/modules + * 0 is always the master + */ +uint32_t keyboard_get_row(uint8_t matrix, uint8_t row) { if (matrix == 0) { return matrix_get_row(row); } else { @@ -288,11 +338,11 @@ void keyboard_task(void) matrix_scan(); if (is_keyboard_master()) { - for (uint8_t m = 0; m < get_num_matrices(); m++) { + for (uint8_t m = 0; m < keyboard_get_num_matrices(); m++) { uint8_t num_cols = keyboard_get_num_cols(m); uint8_t num_rows = keyboard_get_num_rows(m); for (uint8_t r = 0; r < num_rows; r++) { - matrix_row = get_row(m, r); + matrix_row = keyboard_get_row(m, r); uint32_t row_cache = get_row_cache(m, r); matrix_change = matrix_row ^ row_cache; if (matrix_change) { diff --git a/tmk_core/common/keyboard.h b/tmk_core/common/keyboard.h index f3bbb1739d..6424e2fd2d 100644 --- a/tmk_core/common/keyboard.h +++ b/tmk_core/common/keyboard.h @@ -72,8 +72,10 @@ void keyboard_task(void); /* it runs when host LED status is updated */ void keyboard_set_leds(uint8_t leds); +uint8_t keyboard_get_num_matrices(void); uint8_t keyboard_get_num_cols(uint8_t matrix); uint8_t keyboard_get_num_rows(uint8_t matrix); +uint32_t keyboard_get_row(uint8_t matrix, uint8_t row); #ifdef __cplusplus } From 32028cfc43fd7a26bde5eb507fc2aa330e75a36e Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 22:57:05 +0300 Subject: [PATCH 58/59] Fix SWAP_HANDS for multimatrix --- tmk_core/common/action.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tmk_core/common/action.c b/tmk_core/common/action.c index cfc933fb28..f85a695b85 100644 --- a/tmk_core/common/action.c +++ b/tmk_core/common/action.c @@ -106,13 +106,14 @@ bool swap_held = false; void process_hand_swap(keyevent_t *event) { static swap_state_row_t swap_state[MATRIX_ROWS]; - keypos_t pos = event->key; + // TODO: Properly support multimatrices, currenty this only works for single-matrix keyboards + keypos_t pos = event->key.pos; swap_state_row_t col_bit = (swap_state_row_t)1<pressed ? swap_hands : swap_state[pos.row] & (col_bit); if (do_swap) { - event->key = hand_swap_config[pos.row][pos.col]; + event->key.pos = hand_swap_config[pos.row][pos.col]; swap_state[pos.row] |= col_bit; } else { swap_state[pos.row] &= ~(col_bit); From 19e0bc852f1b42d0a97b916d2c703d54a570090b Mon Sep 17 00:00:00 2001 From: Fred Sundvik Date: Fri, 29 Jun 2018 22:59:23 +0300 Subject: [PATCH 59/59] Fix rgb matrix compilation --- quantum/rgb_matrix.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/quantum/rgb_matrix.c b/quantum/rgb_matrix.c index d29a65b907..f72acca670 100644 --- a/quantum/rgb_matrix.c +++ b/quantum/rgb_matrix.c @@ -119,7 +119,8 @@ void rgb_matrix_set_color_all( uint8_t red, uint8_t green, uint8_t blue ) { bool process_rgb_matrix(uint16_t keycode, keyrecord_t *record) { if ( record->event.pressed ) { uint8_t led[8], led_count; - map_row_column_to_led(record->event.key.row, record->event.key.col, led, &led_count); + // TODO: Support multi-matrix keyboards + map_row_column_to_led(record->event.key.pos.row, record->event.key.pos.col, led, &led_count); if (led_count > 0) { for (uint8_t i = LED_HITS_TO_REMEMBER; i > 1; i--) { g_last_led_hit[i - 1] = g_last_led_hit[i - 2];