Skip to content
This repository has been archived by the owner on Nov 30, 2024. It is now read-only.

Commit

Permalink
📝 ⚡ applied requested changes
Browse files Browse the repository at this point in the history
  • Loading branch information
Coreyboy1820 committed Mar 18, 2024
1 parent 9f40b71 commit 3e34fc3
Show file tree
Hide file tree
Showing 7 changed files with 268 additions and 343 deletions.
2 changes: 1 addition & 1 deletion CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ libhal_test_and_make_library(
LIBRARY_NAME libhal-soft

SOURCES
src/i2c_bit_bang.cpp
src/bit_bang_i2c.cpp
src/rc_servo.cpp
src/i2c_minimum_speed.cpp
src/adc_mux.cpp
Expand Down
2 changes: 1 addition & 1 deletion demos/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ project(demos LANGUAGES CXX)

libhal_build_demos(
DEMOS
i2c_bit_bang
bit_bang_i2c

PACKAGES
libhal-soft
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
// See the License for the specific language governing permissions and
// limitations under the License.

#include <libhal-soft/i2c_bit_bang.hpp>
#include <libhal-soft/bit_bang_i2c.hpp>
#include <libhal-stm-imu/lis3dhtr_i2c.hpp>
#include <libhal-util/serial.hpp>
#include <libhal-util/steady_clock.hpp>
Expand All @@ -33,12 +33,12 @@ void application(hardware_map_t& p_map)
hal::print(console, "Starting lis3dhtr_i2c Application...\n");
hal::delay(clock, 50ms);

hal::i2c_bit_bang::i2c_pins pins{ .sda = &sda, .scl = &scl };
hal::bit_bang_i2c::pins pins{ .sda = &sda, .scl = &scl };

hal::i2c_bit_bang i2c_bit_bang(pins, clock, hal::i2c_bit_bang::bus_info{});
i2c_bit_bang.configure(hal::i2c::settings{ .clock_rate = 100.0_kHz });
hal::bit_bang_i2c bit_bang_i2c(pins, clock);
bit_bang_i2c.configure(hal::i2c::settings{ .clock_rate = 100.0_kHz });

hal::stm_imu::lis3dhtr_i2c lis(i2c_bit_bang);
hal::stm_imu::lis3dhtr_i2c lis(bit_bang_i2c);

while (true) {
hal::delay(clock, 500ms);
Expand Down
42 changes: 1 addition & 41 deletions demos/platforms/lpc4074.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,45 +11,5 @@
// 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 <libhal-armcortex/dwt_counter.hpp>
#include <libhal-armcortex/startup.hpp>
#include <libhal-armcortex/system_control.hpp>

#include <libhal-lpc40/clock.hpp>
#include <libhal-lpc40/constants.hpp>
#include <libhal-lpc40/i2c.hpp>
#include <libhal-lpc40/spi.hpp>

#include <libhal-lpc40/output_pin.hpp>
#include <libhal-lpc40/uart.hpp>

#include "../hardware_map.hpp"

hardware_map_t initialize_platform()
{
using namespace hal::literals;

// Set the MCU to the maximum clock speed
hal::lpc40::maximum(12.0_MHz);

static hal::cortex_m::dwt_counter counter(
hal::lpc40::get_frequency(hal::lpc40::peripheral::cpu));

static std::array<hal::byte, 64> receive_buffer{};
static hal::lpc40::uart uart0(0,
receive_buffer,
hal::serial::settings{
.baud_rate = 38400,
});

static hal::lpc40::output_pin scl(1, 15);
static hal::lpc40::output_pin sda(1, 23);

return hardware_map_t{
.console = &uart0,
.output_pin0 = &scl,
.output_pin1 = &sda,
.clock = &counter,
.reset = []() { hal::cortex_m::reset(); },
};
}
#include "lpc4078.cpp"
177 changes: 177 additions & 0 deletions include/libhal-soft/bit_bang_i2c.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,177 @@
// Copyright 2024 Khalil Estell
//
// 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.

#pragma once

#include <chrono>
#include <libhal/i2c.hpp>
#include <libhal/output_pin.hpp>
#include <libhal/units.hpp>

namespace hal {
/**
* @brief A bit bang implementation for i2c.
*
* This implementation of i2c only needs 2 gpios and a steady_clock to work
* correctly. It supports single-controller multiple peripherals but we intend
* to support multiple controllers in the future. bit-bang is a best-effort
* implementation of i2c. The maximum achievable clock rate for the lpc4078 is
* about 180kHz. Interrupts disrupt this controller.
*/
class bit_bang_i2c : public i2c
{
public:
struct pins
{
output_pin* sda;
output_pin* scl;
};

/**
* @brief Construct a new i2c bit bang object
*
* @param p_pins This holds both scl and sda to be used inside of the driver
* @param p_steady_clock A steady clock that should have a higher frequency
* then the configured frequency for the bit bang
* @param p_duty_cycle The duty cycle that the clock sent over scl will run at
*/
bit_bang_i2c(pins p_pins,
steady_clock& p_steady_clock,
const float& p_duty_cycle = 0.5f);

private:
void driver_configure(const settings& p_settings) override;

virtual void driver_transaction(
hal::byte p_address,
std::span<const hal::byte> p_data_out,
std::span<hal::byte> p_data_in,
function_ref<hal::timeout_function> p_timeout) override;

/**
* @brief This function will send the start condition it will also pull the
* pins high before sending the start condition
*/
void send_start_condition();

/**
* @brief This function will send the stop condition while also making sure
* the sda pin is pulled low before sending the stop condition
*/
void send_stop_condition();

/**
* @brief This function will go through the steps of writing the address
* of the peripheral the controller wishes to speak to while also ensuring the
* data written is acknowledged
*
* @param p_address The address of the peripheral, configured with the
* read/write bit already that the controller is requesting to talk to
* @param p_timeout A timeout function which is primarily used for clock
* stretching to ensure the peripheral doesn't hold the line too long
*
* @throws hal::no_such_device when the address written to the bus was not
* acknowledged
*/
void write_address(hal::byte p_address,
function_ref<hal::timeout_function> p_timeout);

/**
* @brief This function will write the entire contents of the span out to the
* bus while making sure all data gets acknowledged
*
* @param p_data_out This is a span of bytes which will be written to the bus
* @param p_timeout A timeout function which is primarily used for clock
* stretching to ensure the peripheral doesn't hold the line too long
*
* @throws hal::io_error when the data written to the bus was not
* acknowledged
*/
void write(std::span<const hal::byte> p_data_out,
function_ref<hal::timeout_function> p_timeout);

/**
* @brief This function will handle writing a singular byte each call while
* also retrieving the acknowledge bits
*
* @param p_byte_to_write This is the byte that will be written to the bus
* @param p_timeout A timeout function which is primarily used for clock
* stretching to ensure the peripheral doesn't hold the line too long
*
* @return bool true when the byte written was ack'd and false when it was
* nack'd
*/
bool write_byte(hal::byte p_byte_to_write,
function_ref<hal::timeout_function> p_timeout);

/**
* @brief This function will write a single bit at a time, dealing with
* simulating the clock and the clock stretching feature
*
* @param p_bit_to_write The bit which will be written on the bus
* @param p_timeout A timeout function which is primarily used for clock
* stretching to ensure the peripheral doesn't hold the line too long
*/
void write_bit(hal::byte p_bit_to_write,
function_ref<hal::timeout_function> p_timeout);

/**
* @brief This function will read in as many bytes as allocated inside of the
* span while also acking or nacking the data
*
* @param p_data_in A span which will be filled with the bytes that will be
* read from the bus
* @param p_timeout A timeout function which is primarily used for clock
* stretching to ensure the peripheral doesn't hold the line too long
*/
void read(std::span<hal::byte> p_data_in,
function_ref<hal::timeout_function> p_timeout);

/**
* @brief This function is responsible for reading a byte at a time off the
* bus and also creating the byte from bits
*
* @return hal::byte the byte that has been read off of the bus
*/
hal::byte read_byte();

/**
* @brief This function is responsible for reading a single bit at a time. It
* will manage the clock and will release sda (pull it high) every time it is
* called
*
* @return hal::byte which will house the single byte read from the bus
*/
hal::byte read_bit();

/// @brief An output pin which is the i2c scl pin
output_pin* m_scl;

/// @brief An output pin which is the i2c sda pin
output_pin* m_sda;

/// @brief A steady_clock provides a mechanism to delay the clock pulses of
/// the scl line.
steady_clock* m_clock;

/// @brief The time that scl will be held high for
uint64_t m_scl_high_ticks;

/// @brief The time that scl will be held low for
uint64_t m_scl_low_ticks;

/// @brief All the information that the bus will need to operate on
float m_duty_cycle;
};
} // namespace hal
Loading

0 comments on commit 3e34fc3

Please sign in to comment.