From 49fe0eec8f17698fc5f86d0abe01777af1fb2b23 Mon Sep 17 00:00:00 2001 From: Romain Forlot Date: Fri, 14 Apr 2017 13:24:07 +0200 Subject: Change directory architecture to use 2 separated projects. Each projects, binder and generator, has to be compiled separatly. CAN-binder will host high and low level binding CAN-config-generator only the generator used for low level binding. build.sh script just launch both build in their respective dir. Change-Id: Ic77932660fcca507b23a631d4e4e790f608880ae Signed-off-by: Romain Forlot --- CAN-binder/examples/basic/generate_example.cpp | 197 ++++++++++++ CAN-binder/examples/basic/handlers.cpp | 22 ++ CAN-binder/examples/basic/signals.json | 95 ++++++ .../examples/toyota/configuration-generated.cpp | 339 +++++++++++++++++++++ CAN-binder/examples/toyota/signals.json | 257 ++++++++++++++++ 5 files changed, 910 insertions(+) create mode 100644 CAN-binder/examples/basic/generate_example.cpp create mode 100644 CAN-binder/examples/basic/handlers.cpp create mode 100644 CAN-binder/examples/basic/signals.json create mode 100644 CAN-binder/examples/toyota/configuration-generated.cpp create mode 100644 CAN-binder/examples/toyota/signals.json (limited to 'CAN-binder/examples') diff --git a/CAN-binder/examples/basic/generate_example.cpp b/CAN-binder/examples/basic/generate_example.cpp new file mode 100644 index 0000000..24b01df --- /dev/null +++ b/CAN-binder/examples/basic/generate_example.cpp @@ -0,0 +1,197 @@ +/* DO NOT MODIFY: This source is generated by the scripts in the + * vi-firmware repository. + * + * Generated for v7.x of the OpenXC VI firmware. + */ + +#include "diagnostics.h" +#include "can/canread.h" +#include "can/canwrite.h" +#include "signals.h" +#include "obd2.h" +#include "util/log.h" +#include "config.h" +#include "shared_handlers.h" + +namespace can = openxc::can; + +using openxc::util::log::debug; +using openxc::pipeline::Pipeline; +using openxc::config::getConfiguration; +using openxc::can::read::booleanDecoder; +using openxc::can::read::stateDecoder; +using openxc::can::read::ignoreDecoder; +using openxc::diagnostics::obd2::handleObd2Pid; +using namespace openxc::signals::handlers; + +#include "can/canread.h" + +using openxc::can::read::publishNumericalMessage; + +void handleSteeringWheelMessage(CanMessage* message, + CanSignal* signals, int signalCount, Pipeline* pipeline) { + publishNumericalMessage("latitude", 42.0, pipeline); +} + +openxc_DynamicField handleInverted(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send) { + return openxc::payload::wrapNumber(value * -1); +} + +void initializeMyStuff() { } + +void initializeOtherStuff() { } + +void myLooper() { + // this function will be called once each time through the main loop, after + // all CAN message processing has been completed +} + +const int MESSAGE_SET_COUNT = 1; +CanMessageSet MESSAGE_SETS[MESSAGE_SET_COUNT] = { + { 0, "example", 2, 1, 5, 1 }, +}; + +const int MAX_CAN_BUS_COUNT = 2; +CanBus CAN_BUSES[][MAX_CAN_BUS_COUNT] = { + { // message set: example + { speed: 500000, + address: 1, + maxMessageFrequency: 0, + rawWritable: false, + passthroughCanMessages: false, + bypassFilters: false, + loopback: false + }, + + { speed: 125000, + address: 2, + maxMessageFrequency: 0, + rawWritable: false, + passthroughCanMessages: false, + bypassFilters: false, + loopback: false + }, + + }, +}; + +const int MAX_MESSAGE_COUNT = 1; +CanMessageDefinition CAN_MESSAGES[][MAX_MESSAGE_COUNT] = { + { // message set: example + { bus: &CAN_BUSES[0][0], id: 0x128, format: STANDARD, frequencyClock: {0.000000}, forceSendChanged: true}, // ECM_z_5D2 + }, +}; + +const int MAX_SIGNAL_STATES = 12; +const int MAX_SIGNALS_WITH_STATES_COUNT = 1; +const CanSignalState SIGNAL_STATES[][MAX_SIGNALS_WITH_STATES_COUNT][MAX_SIGNAL_STATES] = { + { // message set: example + { {value: 1, name: "FIRST"}, {value: 2, name: "SECOND"}, {value: 3, name: "THIRD"}, {value: 4, name: "FOURTH"}, {value: 5, name: "REVERSE"}, {value: 6, name: "NEUTRAL"}, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, { 0, NULL }, }, + }, +}; + +const int MAX_SIGNAL_COUNT = 5; +CanSignal SIGNALS[][MAX_SIGNAL_COUNT] = { + { // message set: example + {message: &CAN_MESSAGES[0][0], genericName: "GearshiftPosition", bitPosition: 41, bitSize: 3, factor: 1.000000, offset: 0.000000, minValue: 0.000000, maxValue: 0.000000, frequencyClock: {0.000000}, sendSame: true, forceSendChanged: false, states: SIGNAL_STATES[0][0], stateCount: 6, writable: false, decoder: stateDecoder, encoder: NULL}, // GrshftPos + {message: &CAN_MESSAGES[0][0], genericName: "SteeringWheelAngle", bitPosition: 52, bitSize: 12, factor: 0.153920, offset: 0.000000, minValue: 0.000000, maxValue: 0.000000, frequencyClock: {0.000000}, sendSame: true, forceSendChanged: false, states: NULL, stateCount: 0, writable: false, decoder: handleUnsignedSteeringWheelAngle, encoder: NULL}, // StrAnglAct + {message: &CAN_MESSAGES[0][0], genericName: "engine_speed", bitPosition: 12, bitSize: 8, factor: 1.000000, offset: 0.000000, minValue: 0.000000, maxValue: 0.000000, frequencyClock: {15.000000}, sendSame: true, forceSendChanged: false, states: NULL, stateCount: 0, writable: false, decoder: NULL, encoder: NULL}, // EngSpd + {message: &CAN_MESSAGES[0][0], genericName: "steering_angle_sign", bitPosition: 52, bitSize: 12, factor: 1.000000, offset: 0.000000, minValue: 0.000000, maxValue: 0.000000, frequencyClock: {0.000000}, sendSame: true, forceSendChanged: false, states: NULL, stateCount: 0, writable: false, decoder: ignoreDecoder, encoder: NULL}, // StrAnglSign + {message: &CAN_MESSAGES[0][0], genericName: "steering_wheel_angle_error", bitPosition: 44, bitSize: 12, factor: 1.000000, offset: 0.000000, minValue: 0.000000, maxValue: 0.000000, frequencyClock: {0.000000}, sendSame: true, forceSendChanged: false, states: NULL, stateCount: 0, writable: false, decoder: ignoreDecoder, encoder: NULL}, // StrAnglErr + }, +}; + +void openxc::signals::initialize(openxc::diagnostics::DiagnosticsManager* diagnosticsManager) { + switch(getConfiguration()->messageSetIndex) { + case 0: // message set: example + initializeMyStuff(); + break; + } +} + +void openxc::signals::loop() { + switch(getConfiguration()->messageSetIndex) { + case 0: // message set: example + myLooper(); + break; + } +} + +const int MAX_COMMAND_COUNT = 1; +CanCommand COMMANDS[][MAX_COMMAND_COUNT] = { + { // message set: example + { genericName: "turn_signal_status", handler: handleTurnSignalCommand }, + }, +}; + +void openxc::signals::decodeCanMessage(Pipeline* pipeline, CanBus* bus, CanMessage* message) { + switch(getConfiguration()->messageSetIndex) { + case 0: // message set: example + switch(bus->address) { + case 1: + switch (message->id) { + case 0x128: // ECM_z_5D2 + handleSteeringWheelMessage(message, SIGNALS[0], getSignalCount(), pipeline); + can::read::translateSignal(&SIGNALS[0][0], message, SIGNALS[0], getSignalCount(), pipeline); // GrshftPos + can::read::translateSignal(&SIGNALS[0][1], message, SIGNALS[0], getSignalCount(), pipeline); // StrAnglAct + can::read::translateSignal(&SIGNALS[0][2], message, SIGNALS[0], getSignalCount(), pipeline); // EngSpd + can::read::translateSignal(&SIGNALS[0][3], message, SIGNALS[0], getSignalCount(), pipeline); // StrAnglSign + can::read::translateSignal(&SIGNALS[0][4], message, SIGNALS[0], getSignalCount(), pipeline); // StrAnglErr + break; + } + break; + case 2: + switch (message->id) { + } + break; + } + break; + } +} + + +CanCommand* openxc::signals::getCommands() { + return COMMANDS[getActiveMessageSet()->index]; +} + +int openxc::signals::getCommandCount() { + return getActiveMessageSet()->commandCount; +} + +CanMessageDefinition* openxc::signals::getMessages() { + return CAN_MESSAGES[getActiveMessageSet()->index]; +} + +int openxc::signals::getMessageCount() { + return getActiveMessageSet()->messageCount; +} + +CanSignal* openxc::signals::get_can_signals() { + return SIGNALS[getActiveMessageSet()->index]; +} + +int openxc::signals::getSignalCount() { + return getActiveMessageSet()->signalCount; +} + +CanBus* openxc::signals::getCanBuses() { + return CAN_BUSES[getActiveMessageSet()->index]; +} + +int openxc::signals::getCanBusCount() { + return getActiveMessageSet()->busCount; +} + +CanMessageSet* openxc::signals::getActiveMessageSet() { + return &MESSAGE_SETS[getConfiguration()->messageSetIndex]; +} + +CanMessageSet* openxc::signals::getMessageSets() { + return MESSAGE_SETS; +} + +int openxc::signals::getMessageSetCount() { + return MESSAGE_SET_COUNT; +} + diff --git a/CAN-binder/examples/basic/handlers.cpp b/CAN-binder/examples/basic/handlers.cpp new file mode 100644 index 0000000..4316f15 --- /dev/null +++ b/CAN-binder/examples/basic/handlers.cpp @@ -0,0 +1,22 @@ +#include "can/canread.h" + +using openxc::can::read::publishNumericalMessage; + +void handleSteeringWheelMessage(CanMessage* message, + CanSignal* signals, int signalCount, Pipeline* pipeline) { + publishNumericalMessage("latitude", 42.0, pipeline); +} + +openxc_DynamicField handleInverted(CanSignal* signal, CanSignal* signals, + int signalCount, float value, bool* send) { + return openxc::payload::wrapNumber(value * -1); +} + +void initializeMyStuff() { } + +void initializeOtherStuff() { } + +void myLooper() { + // this function will be called once each time through the main loop, after + // all CAN message processing has been completed +} diff --git a/CAN-binder/examples/basic/signals.json b/CAN-binder/examples/basic/signals.json new file mode 100644 index 0000000..8d9a2d2 --- /dev/null +++ b/CAN-binder/examples/basic/signals.json @@ -0,0 +1,95 @@ +{ "name": "example", + "extra_sources": [ + "handlers.cpp" + ], + "initializers": [ + "initializeMyStuff" + ], + "loopers": [ + "myLooper" + ], + "buses": { + "hs": { + "controller": 1, + "speed": 500000 + }, + "ms": { + "controller": 2, + "speed": 125000 + } + }, + "commands": [ + { "name": "turn_signal_status", + "handler": "handleTurnSignalCommand" + } + ], + "messages": { + "0x128": { + "name": "ECM_z_5D2", + "bus": "hs", + "signals": { + "StrAnglAct": { + "generic_name": "SteeringWheelAngle", + "bit_position": 52, + "bit_size": 12, + "factor": 0.15392, + "offset": 0, + "decoder": "handleUnsignedSteeringWheelAngle"}, + "StrAnglSign": { + "generic_name": "steering_angle_sign", + "decoder": "ignoreDecoder", + "bit_position": 52, + "bit_size": 12}, + "EngSpd": { + "generic_name": "engine_speed", + "max_frequency": 15, + "bit_position": 12, + "bit_size": 8}, + "GrshftPos": { + "generic_name": "GearshiftPosition", + "bit_position": 41, + "bit_size": 3, + "states": { + "FIRST": [1], + "SECOND": [2], + "THIRD": [3], + "FOURTH": [4], + "REVERSE": [5], + "NEUTRAL": [6]} + }, + "StrAnglErr": { + "decoder": "ignoreDecoder", + "generic_name": "steering_wheel_angle_error", + "bit_position": 44, + "bit_size": 12 + } + }, + "handlers": ["handleSteeringWheelMessage"] + } + }, + "diagnostic_messages": [ + { + "bus": "hs", + "id": 2015, + "mode": 1, + "pid": 12, + "frequency": 1, + "decoder": "handleObd2Pid" + }, + { + "bus": "hs", + "id": 2016, + "mode": 2, + "pid": 12, + "frequency": 1 + }, + { + "bus": "hs", + "id": 2016, + "mode": 22, + "pid": 6, + "frequency": 1, + "decoder": "handleMyDiagRequest" + } + ] +} diff --git a/CAN-binder/examples/toyota/configuration-generated.cpp b/CAN-binder/examples/toyota/configuration-generated.cpp new file mode 100644 index 0000000..4ffc902 --- /dev/null +++ b/CAN-binder/examples/toyota/configuration-generated.cpp @@ -0,0 +1,339 @@ +#include "configuration.hpp" +#include "can/can-decoder.hpp" + +configuration_t::configuration_t() + : can_message_set_{{0, "example", 0, 1, 5, 0, 19}} + , can_message_definition_ + { + { + can_message_definition_t(0, "can0", 0x620, can_message_format_t::STANDARD, frequency_clock_t(0.00000f), true) + } + } + , can_signals_ + { + { + { + 0, + 0, + "doors.coffer.open", + 88, + 1, + 0.00000f, + 0, + 0, + 0, + frequency_clock_t(0.00000f), + true, + false, + { + }, + false, + decoder_t::booleanDecoder, + nullptr, + false + }, + { + 0, + 0, + "doors.driver.open", + 78, + 1, + 0.00000f, + 0, + 0, + 0, + frequency_clock_t(0.00000f), + true, + false, + { + }, + false, + decoder_t::booleanDecoder, + nullptr, + false + }, + { + 0, + 0, + "doors.passenger.open", + 79, + 1, + 0.00000f, + 0, + 0, + 0, + frequency_clock_t(0.00000f), + true, + false, + { + }, + false, + decoder_t::booleanDecoder, + nullptr, + false + }, + { + 0, + 0, + "doors.rearleft.open", + 86, + 1, + 0.00000f, + 0, + 0, + 0, + frequency_clock_t(0.00000f), + true, + false, + { + }, + false, + decoder_t::booleanDecoder, + nullptr, + false + }, + { + 0, + 0, + "doors.rearright.open", + 85, + 4, + 0.00000f, + 0, + 0, + 0, + frequency_clock_t(0.00000f), + true, + false, + { + }, + false, + decoder_t::booleanDecoder, + nullptr, + false + } + } + } + , diagnostic_messages_ + { + { + { + 4, + "engine.load", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 5, + "engine.coolant.temperature", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 10, + "fuel.pressure", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 11, + "intake.manifold.pressure", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 12, + "engine.speed", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 13, + "vehicle.speed", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 15, + "intake.air.temperature", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 16, + "mass.airflow", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 17, + "throttle.position", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 31, + "running.time", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 45, + "EGR.error", + 0, + 0, + UNIT::INVALID, + 0.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 47, + "fuel.level", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 51, + "barometric.pressure", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 76, + "commanded.throttle.position", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 82, + "ethanol.fuel.percentage", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 90, + "accelerator.pedal.position", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 91, + "hybrid.battery-pack.remaining.life", + 0, + 0, + UNIT::INVALID, + 5.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 92, + "engine.oil.temperature", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + }, + { + 99, + "engine.torque", + 0, + 0, + UNIT::INVALID, + 1.00000f, + decoder_t::decode_obd2_response, + nullptr, + true + } + } + } +{ +} + +const std::string configuration_t::get_diagnostic_bus() const +{ + return "can0"; +} + + diff --git a/CAN-binder/examples/toyota/signals.json b/CAN-binder/examples/toyota/signals.json new file mode 100644 index 0000000..e6260c1 --- /dev/null +++ b/CAN-binder/examples/toyota/signals.json @@ -0,0 +1,257 @@ +{ "name": "example", + "extra_sources": [], + "initializers": [], + "loopers": [], + "buses": {}, + "commands": [], + "messages": { + "0x620": { + "bus": "can0", + "signals": { + "doors.driver.open": { + "generic_name": "doors.driver.open", + "bit_position": 78, + "bit_size": 1, + "factor": 0, + "offset": 0, + "decoder": "decoder_t::booleanDecoder"}, + "doors.passenger.open": { + "generic_name": "doors.passenger.open", + "bit_position": 79, + "bit_size": 1, + "factor": 0, + "offset": 0, + "decoder": "decoder_t::booleanDecoder"}, + "doors.rearleft.open": { + "generic_name": "doors.rearleft.open", + "bit_position": 86, + "bit_size": 1, + "factor": 0, + "offset": 0, + "decoder": "decoder_t::booleanDecoder"}, + "doors.rearright.open": { + "generic_name": "doors.rearright.open", + "bit_position": 85, + "bit_size": 4, + "factor": 0, + "offset": 0, + "decoder": "decoder_t::booleanDecoder"}, + "doors.coffer.open": { + "generic_name": "doors.coffer.open", + "bit_position": 88, + "bit_size": 1, + "factor": 0, + "offset": 0, + "decoder": "decoder_t::booleanDecoder"} + } + }, + "0x3D9": { + "bus": "can0", + "signals": { + "PT_FuelLevelPct": { + "generic_name": "fuel.level", + "bit_position": 8, + "bit_size": 8, + "factor": 0.392157, + "offset": 0 + }, + "PT_EngineSpeed": { + "generic_name": "engine.speed", + "bit_position": 16, + "bit_size": 16, + "factor": 0.25, + "offset": 0 + }, + "PT_FuelLevelLow": { + "generic_name": "fuel.level.low", + "bit_position": 55, + "bit_size": 1, + "factor": 1, + "offset": 0, + "decoder": "decoder_t::booleanDecoder" + } + } + }, + "0x4D1": { + "bus": "can0", + "signals": { + "PT_EngineOilTempHigh": { + "generic_name": "engine.oil.temp.high", + "bit_position": 7, + "bit_size": 1, + "factor": 1, + "offset": 0, + "decoder": "decoder_t::booleanDecoder" + }, + "PT_EngineOilTemp": { + "generic_name": "engine.oil.temp", + "bit_position": 16, + "bit_size": 8, + "factor": 1, + "offset": 0 + } + } + }, + "0x3E9": { + "bus": "can0", + "signals": { + "PT_VehicleAvgSpeed": { + "generic_name": "vehicle.average.speed", + "bit_position": 0, + "bit_size": 15, + "factor": 0.015625, + "offset": 0 + } + } + } + }, +"diagnostic_messages": [ + { + "bus": "can0", + "pid": 4, + "name": "engine.load", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 5, + "name": "engine.coolant.temperature", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 10, + "name": "fuel.pressure", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 11, + "name": "intake.manifold.pressure", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 12, + "name": "engine.speed", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 13, + "name": "vehicle.speed", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 15, + "name": "intake.air.temperature", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 16, + "name": "mass.airflow", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 17, + "name": "throttle.position", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 31, + "name": "running.time", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 45, + "name": "EGR.error", + "frequency": 0, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 47, + "name": "fuel.level", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 51, + "name": "barometric.pressure", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 70, + "name": "ambient.air.temperature", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 76, + "name": "commanded.throttle.position", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 82, + "name": "ethanol.fuel.percentage", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 90, + "name": "accelerator.pedal.position", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 91, + "name": "hybrid.battery-pack.remaining.life", + "frequency": 5, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 92, + "name": "engine.oil.temperature", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 94, + "name": "engine.fuel.rate", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + }, + { + "bus": "can0", + "pid": 99, + "name": "engine.torque", + "frequency": 1, + "decoder": "decoder_t::decode_obd2_response" + } + ] +} -- cgit 1.2.3-korg