git-subtree-dir: blinkled/encdec8b10b
git-subtree-split: 28ed9d5da0
blinkled
| @@ -0,0 +1,6 @@ | |||
| .idea | |||
| __pycache__ | |||
| build/ | |||
| venv/ | |||
| dist/ | |||
| *egg-info* | |||
| @@ -0,0 +1,9 @@ | |||
| language: python | |||
| python: | |||
| - "3.4" | |||
| - "3.5" | |||
| - "3.6" | |||
| install: | |||
| - pip install -e . | |||
| script: | |||
| - make test | |||
| @@ -0,0 +1,21 @@ | |||
| MIT License | |||
| Copyright (c) 2019 Ola Grøttvik | |||
| Permission is hereby granted, free of charge, to any person obtaining a copy | |||
| of this software and associated documentation files (the "Software"), to deal | |||
| in the Software without restriction, including without limitation the rights | |||
| to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |||
| copies of the Software, and to permit persons to whom the Software is | |||
| furnished to do so, subject to the following conditions: | |||
| The above copyright notice and this permission notice shall be included in all | |||
| copies or substantial portions of the Software. | |||
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |||
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |||
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | |||
| AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |||
| LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |||
| OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | |||
| SOFTWARE. | |||
| @@ -0,0 +1,26 @@ | |||
| .PHONY: init freeze test test_verbose build_dist upload | |||
| venv: | |||
| python3 -m venv .env | |||
| init: | |||
| pip install -r requirements.txt | |||
| freeze: | |||
| pip freeze | grep -v "pkg-resources" > requirements.txt | |||
| test: | |||
| nosetests tests/* | |||
| test_verbose: | |||
| nosetests --nocapture tests/* | |||
| build_dist: | |||
| rm -rf dist/* | |||
| python3 setup.py sdist bdist_wheel | |||
| upload_test: | |||
| python3 -m twine upload --repository-url https://test.pypi.org/legacy/ dist/* | |||
| upload: | |||
| python3 -m twine upload dist/* | |||
| @@ -0,0 +1,88 @@ | |||
| [](https://travis-ci.com/olagrottvik/encdec8b10b) | |||
| # encdec8b10b | |||
| Encode and decode 8B10B encoding | |||
| ## Get | |||
| ``` | |||
| python3 -m pip install encdec8b10b | |||
| ``` | |||
| ## Usage | |||
| ### Encode Data Byte | |||
| ``` | |||
| from encdec8b10b import EncDec8B10B | |||
| running_disp = 0 | |||
| byte_to_enc = 0xf | |||
| running_disp, encoded = EncDec8B10B.enc_8b10b(byte_to_enc, running_disp) | |||
| print(hex(encoded)) | |||
| Output >> 0xba | |||
| ``` | |||
| ### Encode Control Byte | |||
| ``` | |||
| from encdec8b10b import EncDec8B10B | |||
| running_disp = 0 | |||
| byte_to_enc = 0xbc # comma | |||
| ctrl = 1 | |||
| running_disp, encoded = EncDec8B10B.enc_8b10b(byte_to_enc, running_disp, ctrl) | |||
| print(hex(encoded)) | |||
| Output >> 0x17c | |||
| ``` | |||
| ### Decode Data Byte | |||
| ``` | |||
| from encdec8b10b import EncDec8B10B | |||
| byte_to_dec = 0xba | |||
| ctrl, decoded = EncDec8B10B.dec_8b10b(byte_to_dec) | |||
| print(hex(decoded)) | |||
| Output >> 0xf | |||
| # ctrl variable confirm that it was a data byte | |||
| print(ctrl) | |||
| Output >> 0 | |||
| ``` | |||
| ### Decode Control Byte | |||
| ``` | |||
| from encdec8b10b import EncDec8B10B | |||
| byte_to_dec = 0x17c # comma encoded | |||
| ctrl, decoded = EncDec8B10B.dec_8b10b(byte_to_dec) | |||
| print(hex(decoded)) | |||
| Output >> 0xbc | |||
| # ctrl variable confirm that it was a control byte | |||
| print(ctrl) | |||
| Output >> 1 | |||
| ``` | |||
| ### Verbosity | |||
| Both functions have a verbose-mode to make it easier to confirm everything that's happening: | |||
| ``` | |||
| from encdec8b10b import EncDec8B10B | |||
| running_disp = 0 | |||
| byte_to_enc = 0xA0 | |||
| running_disp, encoded = EncDec8B10B.enc_8b10b(byte_to_enc, running_disp, verbose=True) | |||
| Output >> Encoder - In: A0 - Encoded: 146 - Running Disparity: 0 | |||
| ctrl, decoded = EncDec8B10B.dec_8b10b(encoded, verbose=True) | |||
| Output >> Decoded: A0 - Control: 0 | |||
| ``` | |||
| ## 8B10B | |||
| 8B10B Encoding were implemented by Al Widmer and Peter Franaszek in 1983. It is still widely used in high-speed electronics. | |||
| - [Original article](https://ieeexplore.ieee.org/document/5390392) | |||
| - [Wikipedia](https://en.wikipedia.org/wiki/8b/10b_encoding) | |||
| ### Thanks | |||
| - [Ryu Shinhyung](https://opencores.org/projects/async_8b10b_encoder_decoder) for creating the tables used in this module | |||
| - [Chuck Benz](http://asics.chuckbenz.com/) for creating awesome combinational 8B10B modules | |||
| - [Alex Forencich](http://www.alexforencich.com/wiki/en/scripts/matlab/enc8b10b) for his 8B10B Matlab script | |||
| @@ -0,0 +1 @@ | |||
| from .core import EncDec_8B10B as EncDec8B10B | |||
| @@ -0,0 +1,16 @@ | |||
| bleach==3.1.4 | |||
| certifi==2019.3.9 | |||
| chardet==3.0.4 | |||
| docutils==0.14 | |||
| idna==2.8 | |||
| nose==1.3.7 | |||
| pkginfo==1.5.0.1 | |||
| Pygments==2.3.1 | |||
| readme-renderer==24.0 | |||
| requests==2.21.0 | |||
| requests-toolbelt==0.9.1 | |||
| six==1.12.0 | |||
| tqdm==4.31.1 | |||
| twine==1.13.0 | |||
| urllib3==1.24.2 | |||
| webencodings==0.5.1 | |||
| @@ -0,0 +1,17 @@ | |||
| import setuptools | |||
| with open("README.md", "r") as fh: | |||
| long_description = fh.read() | |||
| setuptools.setup( | |||
| name='encdec8b10b', | |||
| version='1.0', | |||
| packages=setuptools.find_packages(), | |||
| url='https://github.com/olagrottvik/encdec8b10b', | |||
| license='MIT', | |||
| author='Ola Grøttvik', | |||
| author_email='olagrottvik@gmail.com', | |||
| description='8B10B Encoding and Decoding', | |||
| long_description=long_description, | |||
| long_description_content_type="text/markdown", | |||
| ) | |||
| @@ -0,0 +1,7 @@ | |||
| # -*- coding: utf-8 -*- | |||
| import sys | |||
| import os | |||
| sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) | |||
| import encdec8b10b | |||
| @@ -0,0 +1,87 @@ | |||
| # -*- coding: utf-8 -*- | |||
| from .context import encdec8b10b | |||
| from encdec8b10b import EncDec8B10B | |||
| import random | |||
| import unittest | |||
| verbose = True # Set to True to get test output | |||
| class TestSuite(unittest.TestCase): | |||
| """All test cases""" | |||
| def test_comma(self): | |||
| print("Testing K28.5 Comma...") | |||
| running_disparity = 0 | |||
| test_data = 0xBC | |||
| test_ctrl = 1 | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(test_data, running_disparity, test_ctrl, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(data_decoded, running_disparity, 1, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert data_decoded == test_data and ctrl == test_ctrl, "K28.5 Comma Test Failed" | |||
| def test_known_seq(self): | |||
| print("Testing Known Sequence...") | |||
| known_seq = [0xa0, 0x7a, 0xFF, 0xc2, 0x48, 0xda, 0x1b, 0x2e, 0x1f, 0x5b, 0xa5, 0x20, 0xb6, 0x10, 0xc3, 0x4d, 0xa0, 0x17, 0x83, | |||
| 0x3b, 0x2e, 0x7d, 0x61, 0x73, 0x4d, 0xc5, 0x42, 0x59, 0x45, 0x7c, 0x12, 0x1c, 0x03, 0x52, 0xdd, 0x30, 0xa5] | |||
| encoded_seq = [0x146, 0xda, 0x235, 0x1ad, 0x298, 0x19a, 0x9b, 0x24e, 0xb5, 0x29b, 0x165, 0x246, 0x156, 0xb6, 0x1a3, 0x28d, 0x179, 0x368, 0x123, | |||
| 0x25b, 0x24e, 0xe2, 0x32e, 0x313, 0x28d, 0x1a5, 0x292, 0x299, 0x2a5, 0x0dc, 0x372, 0x9c, 0x363, 0x2b2, 0x1a2, 0x276, 0x165] | |||
| result_encoded = list() | |||
| result_decoded = list() | |||
| # Manually set running disparity to known start | |||
| running_disparity = 1 | |||
| test_ctrl = 0 | |||
| for byte, encoded in zip(known_seq, encoded_seq): | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(byte, running_disparity, test_ctrl, verbose) | |||
| assert data_encoded == encoded, "Data Encoded (0x{:03X}) does not match known sequence (0x{:03X})".format(data_encoded, encoded) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert data_decoded == byte, "Data Decoded (0x{:02X}) does not match input byte (0x{:02X})".format(data_decoded, byte) | |||
| def test_rand_seq(self): | |||
| print("Testing Random Data Sequence...") | |||
| test_ctrl = 0 | |||
| running_disparity = 0 | |||
| for i in range(100000): | |||
| rand_byte = random.randint(0, 0xFF) | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(rand_byte, running_disparity, test_ctrl, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert rand_byte == data_decoded, "Data Decoded (0x{:02X}) does not match input byte (0x{:02X})".format(data_decoded, rand_byte) | |||
| running_disparity = 1 | |||
| for i in range(100000): | |||
| rand_byte = random.randint(0, 0xFF) | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(rand_byte, running_disparity, test_ctrl, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert rand_byte == data_decoded, "Data Decoded (0x{:02X}) does not match input byte (0x{:02X})".format(data_decoded, rand_byte) | |||
| def test_ctrl_symbol(self): | |||
| print("Testing All Control symbols...") | |||
| test_ctrl = 1 | |||
| ctrl_symbols = [0x1c, 0x3c, 0x5c, 0x7c, 0x9c, | |||
| 0xbc, 0xdc, 0xfc, 0xf7, 0xfb, 0xfd, 0xfe] | |||
| running_disparity = 0 | |||
| for symbol in ctrl_symbols: | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b( | |||
| symbol, running_disparity, test_ctrl, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert symbol == data_decoded, "Data Decoded (0x{:02X}) does not match input byte (0x{:02X})".format( | |||
| data_decoded, symbol) | |||
| running_disparity = 1 | |||
| for symbol in ctrl_symbols: | |||
| running_disparity, data_encoded = EncDec8B10B.enc_8b10b(symbol, running_disparity, test_ctrl, verbose) | |||
| ctrl, data_decoded = EncDec8B10B.dec_8b10b(data_encoded, verbose) | |||
| assert symbol == data_decoded, "Data Decoded (0x{:02X}) does not match input byte (0x{:02X})".format(data_decoded, symbol) | |||
| if __name__ == '__main__': | |||
| unittest.main() | |||