Skip to content
Snippets Groups Projects
Commit dd2eb4a7 authored by umithedolphin's avatar umithedolphin
Browse files

last commit

parent c0fba59e
No related branches found
No related tags found
No related merge requests found
Showing with 2605 additions and 0 deletions
README.md 0 → 100644
## Stack Class
The `Stack` class represents a basic stack data structure in Python. It provides methods for pushing elements onto the stack, popping elements from the stack, and checking if the stack is empty.
### Methods
`__init__(self)`
- Constructor method to initialize an empty stack.
`push(self, item)`
- Pushes an item onto the top of the stack.
`pop(self)`
- Removes and returns the item at the top of the stack.
`is_empty(self)`
-Returns True if the stack is empty, False otherwise.
### Testing
From the terminal run
`python -m unittest test`
## RPN (Reverse Polish Notation) Evaluation
### Introduction
This Python function `rpn_eval` evaluates expressions in Reverse Polish Notation (RPN). RPN, also known as postfix notation, is a mathematical notation in which every operator follows all of its operands.
## Usage
The function `rpn_eval` takes a single argument, `expr`, which is a string representing the RPN expression to be evaluated. It returns a string representation of the result of the evaluation.
Example usage:
```python
result = rpn_eval("3 4 + 5 *")
print(result) # Output: "35"
```
The evaluate expression method takes a string (expr) and returns a string. This method checks if the expression passed as an arguement is an infix or postfix. If the expression is a postfix expression, it calls the rpn_eval method. Else, if it's an infix expression, it converts the expression to postfix one by using the helper methods in sy.py file. After the conversion has been made, the rpn_eval method is now called on the converted expression.
### Test cases
From the terminal run
`python -m unittest test`
---
### Part 2
To get the oled screen done we developed a python extension in a file named dd_oled.c
## OLED Python extension
This Python extension provides a convenient interface for controlling an OLED display module. It allows users to initialize the display, write text, set pixels, adjust contrast, and perform other display-related operations.
## Installation
To install the extension:
```bash
python3 setup.py install
```
## Keypad matrix
## Introduction
The `Keypad` class provides a simple interface for interacting with a keypad matrix using Raspberry Pi GPIO pins.
## Usage
### Installation
Ensure that you have the RPi.GPIO library installed. You can install it via pip:
```bash
pip install RPi.GPIO
### Detecting Key Press
You can use the `wait_for_key()` method to block until a key is pressed and return the row and column of the pressed key:
```
# Define column and row pins
col_pins = [2, 3, 4] # Example column pins
row_pins = [17, 27, 22] # Example row pins
# Initialize the keypad
keypad = Keypad(col_pins, row_pins)
key = keypad.wait_for_key()
print("Pressed Key:", key)
```
Alternatively, you can manually check for a key press using the get_key() method:
```python
key = keypad.get_key()
if key is not None:
print("Pressed Key:", key)
```
## Cleaning Up GPIO
After using the keypad, it's essential to clean up the GPIO pins:
## BRINGING EVERYTHING TOGETHER
### Calculator.py
This python file brings the hardware and the software together.
We import the OLED and Keypad Classes from their respective modules
Then we instantiate and then start calling the necessary methods on them.
Within this file is a while loop, that tries to get the keys pressed by calling the keypad.wait_for_key() method, which returns the row and column of the key pressed and displays the text to the OLED screen.
* checks if key pressed = "C" then it clears the screen by calling oled.clear()
* checks if the key pressed = "=" then calls the evaluate expression method from the rpn module, which checks if the expression passed to it is an infix or postfix expression.
if it's an infix expression, it calls the tokenize and shunt methods from the sy module before calculating the expresion by calling the rpn_eval method which eventually returns the calculated result or an error.
File added
File added
File added
File added
from matrix_keypad import Keypad
from dd_oled import OLED
from rpn import evaluate_expression
import time
# Define GPIO pins for Matrix Keypad
ROW_PINS = [16, 20, 21, 5]
COL_PINS = [6, 13, 19, 26]
# Define key mapping for Matrix Keypad
KEY_MAPPING = {
(0, 0): "1", (0, 1): "2", (0, 2): "3", (0, 3): "+",
(1, 0): "4", (1, 1): "5", (1, 2): "6", (1, 3): "-",
(2, 0): "7", (2, 1): "8", (2, 2): "9", (2, 3): "*",
(3, 0): "C", (3, 1): "0", (3, 2): "=", (3, 3): "/"
}
# Initialize Matrix Keypad and OLED display
keypad = Keypad(ROW_PINS, COL_PINS)
oled = OLED(channel=1, address=0x3C, type=OLED_128x64, flip=0, invert=0)
# Main loop
infix_expr = ""
while True:
# Wait for a key to be pressed
row, col = keypad.wait_for_key()
key = KEY_MAPPING.get((row, col))
# Handle numeric and operator keys
if key is not None:
infix_expr += key + " "
oled.display_text(infix_expr, x=0, y=0, font_size=FONT_NORMAL)
# Handle clear and evaluate keys
elif key == "C":
infix_expr = ""
oled.clear()
elif key == "=":
try:
result = evaluate_expression(rpn_expr)
oled.display_text(f"Result: {result}", x=0, y=2, font_size=FONT_SMALL)
except Exception as e:
oled.display_text(f"Error: {e}", x=0, y=4, font_size=FONT_SMALL)
# Delay for debounce or adjust as needed
time.sleep(0.1)
#include <Python.h>
#include "oled96.h"
static PyObject* init_oled(PyObject* self, PyObject* args) {
int channel, address, type, flip, invert;
if (!PyArg_ParseTuple(args, "iiiii", &channel, &address, &type, &flip, &invert)) {
return NULL;
}
int result = oledInit(channel, address, type, flip, invert);
return Py_BuildValue("i", result);
}
static PyObject* shutdown_oled(PyObject* self, PyObject* args) {
oledShutdown();
Py_RETURN_NONE;
}
static PyObject* fill_oled(PyObject* self, PyObject* args) {
unsigned char pattern;
if (!PyArg_ParseTuple(args, "b", &pattern)) {
return NULL;
}
int result = oledFill(pattern);
return Py_BuildValue("i", result);
}
static PyObject* write_string(PyObject* self, PyObject* args) {
int x, y, bLarge;
char* szText;
if (!PyArg_ParseTuple(args, "iiisi", &x, &y, &szText, &bLarge)) {
return NULL;
}
int result = oledWriteString(x, y, szText, bLarge);
return Py_BuildValue("i", result);
}
static PyObject* set_pixel(PyObject* self, PyObject* args) {
int x, y;
unsigned char ucPixel;
if (!PyArg_ParseTuple(args, "iiB", &x, &y, &ucPixel)) {
return NULL;
}
int result = oledSetPixel(x, y, ucPixel);
return Py_BuildValue("i", result);
}
static PyObject* set_contrast(PyObject* self, PyObject* args) {
unsigned char ucContrast;
if (!PyArg_ParseTuple(args, "B", &ucContrast)) {
return NULL;
}
int result = oledSetContrast(ucContrast);
return Py_BuildValue("i", result);
}
static PyMethodDef dd_oled_methods[] = {
{"init", init_oled, METH_VARARGS, "Initialize the OLED display."},
{"shutdown", shutdown_oled, METH_NOARGS, "Shutdown the OLED display."},
{"fill", fill_oled, METH_VARARGS, "Fill the OLED display with a byte pattern."},
{"write_string", write_string, METH_VARARGS, "Write a text string to the display."},
{"set_pixel", set_pixel, METH_VARARGS, "Set a pixel to On or Off."},
{"set_contrast", set_contrast, METH_VARARGS, "Set the contrast level of the display."},
{NULL, NULL, 0, NULL} /* Sentinel */
};
static struct PyModuleDef dd_oled_module = {
PyModuleDef_HEAD_INIT,
"dd_oled",
NULL,
-1,
dd_oled_methods
};
PyMODINIT_FUNC PyInit_dd_oled(void) {
return PyModule_Create(&dd_oled_module);
}
## Stack Class
The `Stack` class represents a basic stack data structure in Python. It provides methods for pushing elements onto the stack, popping elements from the stack, and checking if the stack is empty.
### Methods
`__init__(self)`
- Constructor method to initialize an empty stack.
`push(self, item)`
- Pushes an item onto the top of the stack.
`pop(self)`
- Removes and returns the item at the top of the stack.
`is_empty(self)`
-Returns True if the stack is empty, False otherwise.
### Testing
From the terminal run
`python -m unittest test`
## RPN (Reverse Polish Notation) Evaluation
### Introduction
This Python function `rpn_eval` evaluates expressions in Reverse Polish Notation (RPN). RPN, also known as postfix notation, is a mathematical notation in which every operator follows all of its operands.
## Usage
The function `rpn_eval` takes a single argument, `expr`, which is a string representing the RPN expression to be evaluated. It returns a string representation of the result of the evaluation.
Example usage:
```python
result = rpn_eval("3 4 + 5 *")
print(result) # Output: "35"
```
The evaluate expression method takes a string (expr) and returns a string. This method checks if the expression passed as an arguement is an infix or postfix. If the expression is a postfix expression, it calls the rpn_eval method. Else, if it's an infix expression, it converts the expression to postfix one by using the helper methods in sy.py file. After the conversion has been made, the rpn_eval method is now called on the converted expression.
### Test cases
From the terminal run
`python -m unittest test`
---
### Part 2
To get the oled screen done we developed a python extension in a file named dd_oled.c
## OLED Python extension
This Python extension provides a convenient interface for controlling an OLED display module. It allows users to initialize the display, write text, set pixels, adjust contrast, and perform other display-related operations.
## Installation
To install the extension:
```bash
python3 setup.py install
```
## Keypad matrix
## Introduction
The `Keypad` class provides a simple interface for interacting with a keypad matrix using Raspberry Pi GPIO pins.
## Usage
### Installation
Ensure that you have the RPi.GPIO library installed. You can install it via pip:
```bash
pip install RPi.GPIO
### Detecting Key Press
You can use the `wait_for_key()` method to block until a key is pressed and return the row and column of the pressed key:
```
# Define column and row pins
col_pins = [2, 3, 4] # Example column pins
row_pins = [17, 27, 22] # Example row pins
# Initialize the keypad
keypad = Keypad(col_pins, row_pins)
key = keypad.wait_for_key()
print("Pressed Key:", key)
```
Alternatively, you can manually check for a key press using the get_key() method:
```python
key = keypad.get_key()
if key is not None:
print("Pressed Key:", key)
```
## Cleaning Up GPIO
After using the keypad, it's essential to clean up the GPIO pins:
## BRINGING EVERYTHING TOGETHER
### Calculator.py
This python file brings the hardware and the software together.
We import the OLED and Keypad Classes from their respective modules
Then we instantiate and then start calling the necessary methods on them.
Within this file is a while loop, that tries to get the keys pressed by calling the keypad.wait_for_key() method, which returns the row and column of the key pressed and displays the text to the OLED screen.
* checks if key pressed = "C" then it clears the screen by calling oled.clear()
* checks if the key pressed = "=" then calls the evaluate expression method from the rpn module, which checks if the expression passed to it is an infix or postfix expression.
if it's an infix expression, it calls the tokenize and shunt methods from the sy module before calculating the expresion by calling the rpn_eval method which eventually returns the calculated result or an error.
\ No newline at end of file
https://gitlab.uwe.ac.uk/b5-mohammed/dd_assignment.git
\ No newline at end of file
import RPi.GPIO as GPIO
import time
class Keypad:
def __init__(self, col_pins, row_pins):
self.col_pins = col_pins
self.row_pins = row_pins
# Setup GPIO
GPIO.setmode(GPIO.BCM)
for pin in self.col_pins:
GPIO.setup(pin, GPIO.OUT)
for pin in self.row_pins:
GPIO.setup(pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
def pressed(self, row: int, column: int) -> bool:
# Activate the specified column
GPIO.output(self.col_pins[column], GPIO.LOW)
# Check the state of the specified row
state = GPIO.input(self.row_pins[row])
return state == GPIO.LOW
def get_key(self):
# Iterate through each row and column to determine which key is pressed
for row in range(len(self.row_pins)):
for col in range(len(self.col_pins)):
if self.pressed(row, col):
return (row, col) # Return the row and column of the pressed key
return None # Return None if no key is pressed
def wait_for_key(self):
while True:
key = self.get_key()
if key is not None:
return key # Return the key when pressed
time.sleep(0.1) # Adjust the delay as needed
def cleanup(self):
GPIO.cleanup() # Clean up the GPIO setup
\ No newline at end of file
File added
This diff is collapsed.
File added
File added
CFLAGS=-c -Wall -O2
LIBS = -lm -lpthread
all: liboled.a
liboled.a: fonts.o oled.o
ar -rc liboled.a oled.o fonts.o ;
oled.o: oled.c
$(CC) $(CFLAGS) oled.c
fonts.o: fonts.c
$(CC) $(CFLAGS) fonts.c
clean:
rm -rf *.o liboled.a
// OLED SSD1306 using the I2C interface
// Written by Larry Bank (bitbank@pobox.com)
// Copyright (c) 2017 BitBank Software, Inc.
// Project started 1/15/2017
//
// 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.
//===========================================================================
// The I2C writes (through a file handle) can be single or multiple bytes.
// The write mode stays in effect throughout each call to write()
// To write commands to the OLED controller, start a byte sequence with 0x00,
// to write data, start a byte sequence with 0x40,
// The OLED controller is set to "page mode". This divides the display
// into 8 128x8 "pages" or strips. Each data write advances the output
// automatically to the next address. The bytes are arranged such that the LSB
// is the topmost pixel and the MSB is the bottom.
// The font data comes from another source and must be rotated 90 degrees
// (at init time) to match the orientation of the bits on the display memory.
// A copy of the display memory is maintained by this code so that single pixel
// writes can occur without having to read from the display controller.
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <linux/i2c-dev.h>
#include "oled.h"
extern unsigned char ucFont[], ucSmallFont[];
static int iScreenOffset; // current write offset of screen data
static unsigned char ucScreen[1024]; // local copy of the image buffer
static int file_i2c = 0;
static int oled_type, oled_flip;
static void oledWriteCommand(unsigned char);
//
// Opens a file system handle to the I2C device
// Initializes the OLED controller into "page mode"
// Prepares the font data for the orientation of the display
// Returns 0 for success, 1 for failure
//
int oledInit(int iChannel, int iAddr, int iType, int bFlip, int bInvert)
{
const unsigned char oled64_initbuf[]={0x00,0xae,0xa8,0x3f,0xd3,0x00,0x40,0xa1,0xc8,
0xda,0x12,0x81,0xff,0xa4,0xa6,0xd5,0x80,0x8d,0x14,
0xaf,0x20,0x02};
const unsigned char oled32_initbuf[] = {
0x00,0xae,0xd5,0x80,0xa8,0x1f,0xd3,0x00,0x40,0x8d,0x14,0xa1,0xc8,0xda,0x02,
0x81,0x7f,0xd9,0xf1,0xdb,0x40,0xa4,0xa6,0xaf};
char filename[32];
unsigned char uc[4];
oled_type = iType;
oled_flip = bFlip;
sprintf(filename, "/dev/i2c-%d", iChannel);
if ((file_i2c = open(filename, O_RDWR)) < 0)
{
fprintf(stderr, "Failed to open i2c bus %d\n", iChannel);
file_i2c = 0;
return 1;
}
if (ioctl(file_i2c, I2C_SLAVE, iAddr) < 0)
{
fprintf(stderr, "Failed to acquire bus access or talk to slave\n");
file_i2c = 0;
return 1;
}
if (iType == OLED_128x32)
{
write(file_i2c, oled32_initbuf, sizeof(oled32_initbuf));
}
else
{
write(file_i2c, oled64_initbuf, sizeof(oled64_initbuf));
}
if (bInvert)
{
uc[0] = 0; // command
uc[1] = 0xa7; // invert command
write(file_i2c, uc, 2);
}
if (bFlip) // rotate display 180
{
uc[0] = 0; // command
uc[1] = 0xa0;
write(file_i2c, uc, 2);
uc[1] = 0xc0;
write(file_i2c, uc, 2);
}
return 0;
} /* oledInit() */
// Sends a command to turn off the OLED display
// Closes the I2C file handle
void oledShutdown()
{
if (file_i2c != 0)
{
oledWriteCommand(0xaE); // turn off OLED
close(file_i2c);
file_i2c = 0;
}
}
// Send a single byte command to the OLED controller
static void oledWriteCommand(unsigned char c)
{
unsigned char buf[2];
int rc;
buf[0] = 0x00; // command introducer
buf[1] = c;
rc = write(file_i2c, buf, 2);
if (rc) {} // suppress warning
} /* oledWriteCommand() */
static void oledWriteCommand2(unsigned char c, unsigned char d)
{
unsigned char buf[3];
int rc;
buf[0] = 0x00;
buf[1] = c;
buf[2] = d;
rc = write(file_i2c, buf, 3);
if (rc) {} // suppress warning
} /* oledWriteCommand2() */
int oledSetContrast(unsigned char ucContrast)
{
if (file_i2c == 0)
return -1;
oledWriteCommand2(0x81, ucContrast);
return 0;
} /* oledSetContrast() */
//static void oledWriteData(unsigned char c)
//{
//unsigned char buf[2];
// buf[0] = 0x40; // data introducer
// buf[1] = c;
// write(file_i2c, buf, 2);
//} /* oledWriteData() */
// Send commands to position the "cursor" to the given
// row and column
static void oledSetPosition(int x, int y)
{
iScreenOffset = (y*128)+x;
if (oled_type == OLED_64x32) // visible display starts at column 32, row 4
{
x += 32; // display is centered in VRAM, so this is always true
if (oled_flip == 0) // non-flipped display starts from line 4
y += 4;
}
else if (oled_type == OLED_132x64) // SH1106 has 128 pixels centered in 132
{
x += 2;
}
oledWriteCommand(0xb0 | y); // go to page Y
oledWriteCommand(0x00 | (x & 0xf)); // // lower col addr
oledWriteCommand(0x10 | ((x >> 4) & 0xf)); // upper col addr
}
//static void oledWrite(unsigned char c)
//{
// write(file_i2c, &c, 1);
//} /* oledWrite() */
// Write a block of pixel data to the OLED
// Length can be anything from 1 to 1024 (whole display)
static void oledWriteDataBlock(unsigned char *ucBuf, int iLen)
{
unsigned char ucTemp[129];
int rc;
ucTemp[0] = 0x40; // data command
memcpy(&ucTemp[1], ucBuf, iLen);
rc = write(file_i2c, ucTemp, iLen+1);
if (rc) {} // suppress warning
// Keep a copy in local buffer
memcpy(&ucScreen[iScreenOffset], ucBuf, iLen);
iScreenOffset += iLen;
}
// Set (or clear) an individual pixel
// The local copy of the frame buffer is used to avoid
// reading data from the display controller
int oledSetPixel(int x, int y, unsigned char ucColor)
{
int i;
unsigned char uc, ucOld;
if (file_i2c == 0)
return -1;
i = ((y >> 3) * 128) + x;
if (i < 0 || i > 1023) // off the screen
return -1;
uc = ucOld = ucScreen[i];
uc &= ~(0x1 << (y & 7));
if (ucColor)
{
uc |= (0x1 << (y & 7));
}
if (uc != ucOld) // pixel changed
{
oledSetPosition(x, y>>3);
oledWriteDataBlock(&uc, 1);
}
return 0;
} /* oledSetPixel() */
//
// Draw a string of small (8x8), large (16x24), or very small (6x8) characters
// At the given col+row
// The X position is in character widths (8 or 16)
// The Y position is in memory pages (8 lines each)
//
int oledWriteString(int x, int y, char *szMsg, int iSize)
{
int i, iLen;
unsigned char *s;
if (file_i2c == 0) return -1; // not initialized
if (iSize < FONT_NORMAL || iSize > FONT_SMALL)
return -1;
iLen = strlen(szMsg);
if (iSize == FONT_BIG) // draw 16x32 font
{
if (iLen+x > 8) iLen = 8-x;
if (iLen < 0) return -1;
x *= 16;
for (i=0; i<iLen; i++)
{
s = &ucFont[9728 + (unsigned char)szMsg[i]*64];
oledSetPosition(x+(i*16), y);
oledWriteDataBlock(s, 16);
oledSetPosition(x+(i*16), y+1);
oledWriteDataBlock(s+16, 16);
oledSetPosition(x+(i*16), y+2);
oledWriteDataBlock(s+32, 16);
// oledSetPosition(x+(i*16), y+3);
// oledWriteDataBlock(s+48, 16);
}
}
else if (iSize == FONT_NORMAL) // draw 8x8 font
{
oledSetPosition(x*8, y);
if (iLen + x > 16) iLen = 16 - x; // can't display it
if (iLen < 0)return -1;
for (i=0; i<iLen; i++)
{
s = &ucFont[(unsigned char)szMsg[i] * 8];
oledWriteDataBlock(s, 8); // write character pattern
}
}
else // 6x8
{
oledSetPosition(x*6, y);
if (iLen + x > 21) iLen = 21 - x;
if (iLen < 0) return -1;
for (i=0; i<iLen; i++)
{
s = &ucSmallFont[(unsigned char)szMsg[i]*6];
oledWriteDataBlock(s, 6);
}
}
return 0;
} /* oledWriteString() */
// Fill the frame buffer with a byte pattern
// e.g. all off (0x00) or all on (0xff)
int oledFill(unsigned char ucData)
{
int y;
unsigned char temp[128];
int iLines, iCols;
if (file_i2c == 0) return -1; // not initialized
iLines = (oled_type == OLED_128x32 || oled_type == OLED_64x32) ? 4:8;
iCols = (oled_type == OLED_64x32) ? 4:8;
memset(temp, ucData, 128);
for (y=0; y<iLines; y++)
{
oledSetPosition(0,y); // set to (0,Y)
oledWriteDataBlock(temp, iCols*16); // fill with data byte
} // for y
return 0;
} /* oledFill() */
#ifndef OLED96_H
#define OLED96_H
//
// OLED96
// Library for accessing the 0.96" SSD1306 128x64 OLED display
// Written by Larry Bank (bitbank@pobox.com)
// Copyright (c) 2017 BitBank Software, Inc.
// Project started 1/15/2017
//
// 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.
//===========================================================================
// OLED type for init function
enum {
OLED_128x32 = 1,
OLED_128x64,
OLED_132x64,
OLED_64x32
};
typedef enum
{
FONT_NORMAL=0, // 8x8
FONT_BIG, // 16x24
FONT_SMALL // 6x8
} FONTSIZE;
// Initialize the OLED96 library for a specific I2C address
// Optionally enable inverted or flipped mode
// returns 0 for success, 1 for failure
//
int oledInit(int iChannel, int iAddress, int iType, int bFlip, int bInvert);
// Turns off the display and closes the I2C handle
void oledShutdown(void);
// Fills the display with the byte pattern
int oledFill(unsigned char ucPattern);
// Write a text string to the display at x (column 0-127) and y (row 0-7)
// bLarge = 0 - 8x8 font, bLarge = 1 - 16x24 font
int oledWriteString(int x, int y, char *szText, int bLarge);
// Sets a pixel to On (1) or Off (0)
// Coordinate system is pixels, not text rows (0-127, 0-63)
int oledSetPixel(int x, int y, unsigned char ucPixel);
// Sets the contrast (brightness) level of the display
// Valid values are 0-255 where 0=off and 255=max brightness
int oledSetContrast(unsigned char ucContrast);
#endif // OLED96_H
\ No newline at end of file
File added
rpn.py 0 → 100644
import re
import sy # Importing the provided infix to RPN conversion module
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def is_empty(self):
return len(self.items) == 0
def rpn_eval(expr: str) -> str:
stack = Stack()
operators = {'+': lambda x, y: x + y, '-': lambda x, y: x - y, '*': lambda x, y: x * y, '/': lambda x, y: x / y, '^': lambda x, y: x ** y}
for token in expr.split():
# Check if the token is an operator
if token in operators:
try:
operand2 = stack.pop() # The second operand is popped first (LIFO)
operand1 = stack.pop() # The first operand is popped after the second operand
result = operators[token](operand1, operand2) # Perform the operation
stack.push(result) # Push the result back onto the stack
except IndexError:
return "Error: Insufficient operands for operator {}".format(token)
except ZeroDivisionError:
return "Error: Division by zero"
else:
# If not an operator, push the operand to the stack
stack.push(int(token))
if len(stack.items) != 1:
return "Error: Invalid expression"
return str(stack.pop())
def is_infix(expression):
expr_arr = expression.split()
index = 0
operand_pos = 0
operator_pos = 1
operators = ["+", "-", "/", "*", "^", "**"]
if expr_arr[0] in operators:
return False
if expr_arr[-1] in operators:
return False
for char in expr_arr:
index += 1
if char == "(":
position_found = index- 1
operand_pos = position_found + 1
if not expr_arr[position_found + 2] == ")":
operator_pos = position_found + 2
if not expr_arr[operand_pos].isnumeric():
return False
else:
continue
elif char == ")":
position_found = index - 1
if len(expr_arr) - 1 == position_found:
continue
operator_pos = position_found + 1
operand_pos = position_found + 2
if not expr_arr[operator_pos] in operators:
return False
continue
if char.isnumeric():
if expr_arr[operand_pos] == char:
operand_pos += 2
continue
else:
return False
if not char.isnumeric() and char in operators:
if expr_arr[operator_pos] == char:
operator_pos += 2
continue
else:
return False
return True
def evaluate_expression(expr: str) -> str:
operators = ["+", "-", "*", "**", "^", "/"]
# Check if the expression is in RPN format
if not is_infix(expr) and not expr[0] in operators:
return rpn_eval(expr)
elif expr[0] in operators:
print("Please provide a postfix or infix expression")
return "Error: Invalid expression"
else:
# Convert the infix expression to RPN using the provided sy module
tokens = sy.tokenize(expr)
rpn_expr = " ".join(sy.shunt(tokens))
# Evaluate the RPN expression
return rpn_eval(rpn_expr)
setup.py 0 → 100644
from distutils.core import setup, Extension
def main():
setup(
name="dd_oled",
version="1.0.0",
description="Python interface for OLED96 library",
author="Badrudden Mohammed",
author_email="badrudeen2.mohammed@live.uwe.ac.uk",
ext_modules=[Extension("dd_oled", ["dd_oled.c"])],
)
if __name__ == "__main__":
main()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment