Working I2C-controlled digits
This commit is contained in:
		@@ -16,4 +16,4 @@ pico_enable_stdio_usb(qclk 1)
 | 
				
			|||||||
pico_enable_stdio_uart(qclk 0)
 | 
					pico_enable_stdio_uart(qclk 0)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pico_add_extra_outputs(qclk)
 | 
					pico_add_extra_outputs(qclk)
 | 
				
			||||||
target_link_libraries(qclk pico_stdlib)
 | 
					target_link_libraries(qclk pico_stdlib hardware_i2c pico_i2c_slave)
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										89
									
								
								mcu/main.c
									
									
									
									
									
								
							
							
						
						
									
										89
									
								
								mcu/main.c
									
									
									
									
									
								
							@@ -1,27 +1,33 @@
 | 
				
			|||||||
#include <stdio.h>
 | 
					#include <stdio.h>
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#include "hardware/gpio.h"
 | 
					#include "hardware/gpio.h"
 | 
				
			||||||
 | 
					#include "hardware/i2c.h"
 | 
				
			||||||
#include "pico/stdlib.h"
 | 
					#include "pico/stdlib.h"
 | 
				
			||||||
#include "pico/binary_info.h"
 | 
					#include "pico/binary_info.h"
 | 
				
			||||||
 | 
					#include "pico/i2c_slave.h"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const uint PIN_DIGIT_BASE = 18;
 | 
					const uint PIN_DIGIT_BASE = 18;
 | 
				
			||||||
const uint PIN_SEGMENT_BASE = 2;
 | 
					const uint PIN_SEGMENT_BASE = 2;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const uint N_DIGITS = 4;
 | 
					const uint N_DIGITS = 4;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
uint8_t digit_states[4] = { 0b11001100, 0b11111111, 0b10101010, 0b00101001 };
 | 
					const uint I2C_PIN_SDA = 0;
 | 
				
			||||||
 | 
					const uint I2C_PIN_SCL = 1;
 | 
				
			||||||
 | 
					const uint I2C_SLAVE_ADDRESS = 0x17;
 | 
				
			||||||
 | 
					const uint I2C_RATE = 100 * 1000;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
void write_digit(uint8_t digit) {
 | 
					uint8_t digit_states[4] = { 0 };
 | 
				
			||||||
 | 
					static struct {
 | 
				
			||||||
 | 
					  bool digit_written;
 | 
				
			||||||
 | 
					  uint digit;
 | 
				
			||||||
 | 
					} i2c_context;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void write_digit(uint8_t digit) {
 | 
				
			||||||
  const uint mask = (0xffffffff << PIN_SEGMENT_BASE) ^ (0xffffffff << PIN_SEGMENT_BASE + 8);
 | 
					  const uint mask = (0xffffffff << PIN_SEGMENT_BASE) ^ (0xffffffff << PIN_SEGMENT_BASE + 8);
 | 
				
			||||||
  gpio_put_masked(mask, (~digit & 0xff) << PIN_SEGMENT_BASE);
 | 
					  gpio_put_masked(mask, (~digit & 0xff) << PIN_SEGMENT_BASE);
 | 
				
			||||||
  gpio_put_masked(mask, digit << PIN_SEGMENT_BASE);
 | 
					  gpio_put_masked(mask, digit << PIN_SEGMENT_BASE);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					static void setup_io() {
 | 
				
			||||||
int main() {
 | 
					 | 
				
			||||||
  bi_decl(bi_program_description("qCLK driver."));
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  stdio_init_all();
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
  for (uint i = PIN_DIGIT_BASE; i < PIN_DIGIT_BASE + N_DIGITS; i++) {
 | 
					  for (uint i = PIN_DIGIT_BASE; i < PIN_DIGIT_BASE + N_DIGITS; i++) {
 | 
				
			||||||
    gpio_init(i);
 | 
					    gpio_init(i);
 | 
				
			||||||
    gpio_set_dir(i, GPIO_OUT);
 | 
					    gpio_set_dir(i, GPIO_OUT);
 | 
				
			||||||
@@ -32,14 +38,65 @@ int main() {
 | 
				
			|||||||
    gpio_set_dir(i, GPIO_OUT);
 | 
					    gpio_set_dir(i, GPIO_OUT);
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
  write_digit(0);
 | 
					  write_digit(0);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static void display_loop() {
 | 
				
			||||||
 | 
					  for (uint i = 0; i < N_DIGITS; i++) {
 | 
				
			||||||
 | 
					    uint prev = i == 0 ? N_DIGITS - 1 : i - 1;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  while (1) {
 | 
					    gpio_put(PIN_DIGIT_BASE + prev, 0);
 | 
				
			||||||
    for (uint i = 0; i < N_DIGITS; i++) {
 | 
					    sleep_us(100);
 | 
				
			||||||
      uint prev = i == 0 ? N_DIGITS - 1 : i - 1;
 | 
					
 | 
				
			||||||
      gpio_put(PIN_DIGIT_BASE + prev, 0);
 | 
					    write_digit(digit_states[i]);
 | 
				
			||||||
      write_digit(digit_states[i]);
 | 
					    gpio_put(PIN_DIGIT_BASE + i, 1);
 | 
				
			||||||
      gpio_put(PIN_DIGIT_BASE + i, 1);
 | 
					    sleep_ms(1);
 | 
				
			||||||
      sleep_ms(1);
 | 
					 | 
				
			||||||
    }
 | 
					 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void i2c_slave_handler(i2c_inst_t *i2c, i2c_slave_event_t event) {
 | 
				
			||||||
 | 
					  switch (event) {
 | 
				
			||||||
 | 
					  case I2C_SLAVE_RECEIVE: // master has written some data
 | 
				
			||||||
 | 
					    if (!i2c_context.digit_written) {
 | 
				
			||||||
 | 
					        // writes always start with the memory address
 | 
				
			||||||
 | 
					        uint8_t addr = i2c_read_byte_raw(i2c);
 | 
				
			||||||
 | 
					        i2c_context.digit = addr < N_DIGITS ? addr : -1;
 | 
				
			||||||
 | 
					        i2c_context.digit_written = true;
 | 
				
			||||||
 | 
					    } else if (i2c_context.digit != -1) {
 | 
				
			||||||
 | 
					        // save into memory
 | 
				
			||||||
 | 
					        digit_states[i2c_context.digit] = i2c_read_byte_raw(i2c);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  case I2C_SLAVE_REQUEST: // master is requesting data
 | 
				
			||||||
 | 
					    // load from memory
 | 
				
			||||||
 | 
					    uint8_t data = i2c_context.digit != -1 ? digit_states[i2c_context.digit] : 0;
 | 
				
			||||||
 | 
					    i2c_write_byte_raw(i2c, data);
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  case I2C_SLAVE_FINISH: // master has signalled Stop / Restart
 | 
				
			||||||
 | 
					    i2c_context.digit_written = false;
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  default:
 | 
				
			||||||
 | 
					    break;
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					static void setup_i2c() {
 | 
				
			||||||
 | 
					  gpio_init(I2C_PIN_SDA);
 | 
				
			||||||
 | 
					  gpio_set_function(I2C_PIN_SDA, GPIO_FUNC_I2C);
 | 
				
			||||||
 | 
					  gpio_pull_up(I2C_PIN_SDA);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gpio_init(I2C_PIN_SCL);
 | 
				
			||||||
 | 
					  gpio_set_function(I2C_PIN_SCL, GPIO_FUNC_I2C);
 | 
				
			||||||
 | 
					  gpio_pull_up(I2C_PIN_SCL);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  i2c_init(i2c0, I2C_RATE);
 | 
				
			||||||
 | 
					  // configure I2C0 for slave mode
 | 
				
			||||||
 | 
					  i2c_slave_init(i2c0, I2C_SLAVE_ADDRESS, &i2c_slave_handler);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					int main() {
 | 
				
			||||||
 | 
					  bi_decl(bi_program_description("qCLK driver."));
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  stdio_init_all();
 | 
				
			||||||
 | 
					  setup_io();
 | 
				
			||||||
 | 
					  setup_i2c();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  while (1) display_loop();
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user