c - Umwandlung von Char Binary in C - Im-Coder.com

Step-by-Step Guide for Adding a Stack, Expanding Control Lines, and Building an Assembler

After the positive response to my first tutorial on expanding the RAM, I thought I'd continue the fun by expanding the capabilities of Ben's 8-bit CPU even further. That said, you'll need to have done the work in the previous post to be able to do this. You can get a sense for what we'll do in this Imgur gallery.
In this tutorial, we'll balance software and hardware improvements to make this a pretty capable machine:

Parts List

To only update the hardware, you'll need:
If you want to update the toolchain, you'll need:
  1. Arduino Mega 2560 (Amazon) to create the programmer.
  2. Ribbon Jumper Cables (Amazon) to connect the Arduino to the breadboard.
  3. TL866 II Plus EEPROM Programmer (Amazon) to program the ROM.
Bonus Clock Improvement: One additional thing I did is replace the 74LS04 inverter in Ben's clock circuit with a 74LS14 inverting Schmitt trigger (datasheet, Jameco). The pinouts are identical! Just drop it in, wire the existing lines, and then run the clock output through it twice (since it's inverting) to get a squeaky clean clock signal. Useful if you want to go even faster with the CPU.

Step 1: Program with an Arduino and Assembler (Image 1, Image 2)

There's a certain delight in the physical programming of a computer with switches. This is how Bill Gates and Paul Allen famously programmed the Altair 8800 and started Microsoft. But at some point, the hardware becomes limited by how effectively you can input the software. After upgrading the RAM, I quickly felt constrained by how long it took to program everything.
You can continue to program the computer physically if you want and even after upgrading that option is still available, so this step is optional. There's probably many ways to approach the programming, but this way felt simple and in the spirit of the build. We'll use an Arduino Mega 2560, like the one in Ben's 6502 build, to program the RAM. We'll start with a homemade assembler then switch to something more robust.
Preparing the Physical Interface
The first thing to do is prepare the CPU to be programmed by the Arduino. We already did the hard work on this in the RAM upgrade tutorial by using the bus to write to the RAM and disconnecting the control ROM while in program mode. Now we just need to route the appropriate lines to a convenient spot on the board to plug the Arduino into.
  1. This is optional, but I rewired all the DIP switches to have ground on one side, rather than alternating sides like Ben's build. This just makes it easier to route wires.
  2. Wire the 8 address lines from the DIP switch, connecting the side opposite to ground (the one going to the chips) to a convenient point on the board. I put them on the far left, next to the address LEDs and above the write button circuit.
  3. Wire the 8 data lines from the DIP switch, connecting the side opposite to ground (the one going to the chips) directly below the address lines. Make sure they're separated by the gutter so they're not connected.
  4. Wire a line from the write button to your input area. You want to connect the side of the button that's not connected to ground (the one going to the chip).
So now you have one convenient spot with 8 address lines, 8 data lines, and a write line. If you want to get fancy, you can wire them into some kind of connector, but I found that ribbon jumper cables work nicely and keep things tidy.
The way we'll program the RAM is to enter program mode and set all the DIP switches to the high position (e.g., 11111111). Since the switches are upside-down, this means they'll all be disconnected and not driving to ground. The address and write lines will simply be floating and the data lines will be weakly pulled up by 1k resistors. Either way, the Arduino can now drive the signals going into the chips using its outputs.
Creating the Arduino Programmer
Now that we can interface with an Arduino, we need to write some software. If you follow Ben's 6502 video, you'll have all the knowledge you need to get this working. If you want some hints and code, see below (source code):
  1. Create arrays for your data and address lines. For example: const char ADDRESS_LINES[] = {39, 41, 43, 45, 47, 49, 51, 53};. Create your write line with #define RAM_WRITE 3.
  2. Create functions to enable and disable your address and data lines. You want to enable them before writing. Make sure to disable them afterward so that you can still manually program using DIP switches without disconnecting the Arduino. The code looks like this (just change INPUT to OUTPUT accordingly): for(int n = 0; n < 8; n += 1) { pinMode(ADDRESS_LINES[n], OUTPUT); }
  3. Create a function to write to an address. It'll look like void writeData(byte writeAddress, byte writeData) and basically use two loops, one for address and one for data, followed by toggling the write.
  4. Create a char array that contains your program and data. You can use #define to create opcodes like #define LDA 0x01.
  5. In your main function, loop through the program array and send it through writeData.
With this setup, you can now load multi-line programs in a fraction of a second! This can really come in handy with debugging by stress testing your CPU with software. Make sure to test your setup with existing programs you know run reliably. Now that you have your basic setup working, you can add 8 additional lines to read the bus and expand the program to let you read memory locations or even monitor the running of your CPU.
Making an Assembler
The above will serve us well but it's missing a key feature: labels. Labels are invaluable in assembly because they're so versatile. Jumps, subroutines, variables all use labels. The problem is that labels require parsing. Parsing is a fun project on the road to a compiler but not something I wanted to delve into right now--if you're interested, you can learn about Flex and Bison. Instead, I found a custom assembler that lets you define your CPU's instruction set and it'll do everything else for you. Let's get it setup:
  1. If you're on Windows, you can use the pre-built binaries. Otherwise, you'll need to install Rust and compile via cargo build.
  2. Create a file called 8bit.cpu and define your CPU instructions (source code). For example, LDA would be lda {address} -> 0x01 @ address[7:0]. What's cool is you can also now create the instruction's immediate variant instead of having to call it LDI: lda #{value} -> 0x05 @ value[7:0].
  3. You can now write assembly by adding #include "8bit.cpu" to the top of your code. There's a lot of neat features so make sure to read the documentation!
  4. Once you've written some assembly, you can generate the machine code using ./customasm yourprogram.s -f hexc -p. This prints out a char array just like our Arduino program used!
  5. Copy the char array into your Arduino program and send it to your CPU.
At this stage, you can start creating some pretty complex programs with ease. I would definitely play around with writing some larger programs. I actually found a bug in my hardware that was hidden for a while because my programs were never very complex!

Step 2: Expand the Control Lines (Image)

Before we can expand the CPU any further, we have to address the fact we're running out of control lines. An easy way to do this is to add a 3rd 28C16 ROM and be on your way. If you want something a little more involved but satisfying, read on.
Right now the control lines are one hot encoded. This means that if you have 4 lines, you can encode 4 states. But we know that a 4-bit binary number can encode 16 states. We'll use this principle via 74LS138 decoders, just like Ben used for the step counter.
Choosing the Control Line Combinations
Everything comes with trade-offs. In the case of combining control lines, it means the two control lines we choose to combine can never be activated at the same time. We can ensure this by encoding all the inputs together in the first 74LS138 and all the outputs together in a second 74LS138. We'll keep the remaining control lines directly connected.
Rewiring the Control Lines
If your build is anything like mine, the control lines are a bit of a mess. You'll need to be careful when rewiring to ensure it all comes back together correctly. Let's get to it:
  1. Place the two 74LS138 decoders on the far right side of the breadboard with the ROMs. Connect them to power and ground.
  2. You'll likely run out of inverters, so place a 74LS04 on the breadboard above your decoders. Connect it to power and ground.
  3. Carefully take your inputs (MI, RI, II, AI, BI, J) and wire them to the outputs of the left 74LS138. Do not wire anything to O0 because that's activated by 000 which won't work for us!
  4. Carefully take your outputs (RO, CO, AO, EO) and wire them to the outputs of the right 74LS138. Remember, do not wire anything to O0!
  5. Now, the 74LS138 outputs are active low, but the ROM outputs were active high. This means you need to swap the wiring on all your existing 74LS04 inverters for the LEDs and control lines to work. Make sure you track which control lines are supposed to be active high vs. active low!
  6. Wire E3 to power and E2 to ground. Connect the E1 on both 138s together, then connect it to the same line as OE on your ROMs. This will ensure that the outputs are disabled when you're in program mode. You can actually take off the 1k pull-up resistors from the previous tutorial at this stage, because the 138s actively drive the lines going to the 74LS04 inverters rather than floating like the ROMs.
At this point, you really need to ensure that the massive rewiring job was successful. Connect 3 jumper wires to A0-A2 and test all the combinations manually. Make sure the correct LED lights up and check with a multimeteoscilloscope that you're getting the right signal at each chip. Catching mistakes at this point will save you a lot of headaches! Now that everything is working, let's finish up:
  1. Connect A0-A2 of the left 74LS138 to the left ROM's A0-A2.
  2. Connect A0-A2 of the right 74LS138 to the right ROM's A0-A2.
  3. Distribute the rest of the control signals across the two ROMs.
Changing the ROM Code
This part is easy. We just need to update all of our #define with the new addresses and program the ROMs again. For clarity that we're not using one-hot encoding anymore, I recommend using hex instead of binary. So instead of #define MI 0b0000000100000000, we can use #define MI 0x0100, #define RI 0x0200, and so on.
Testing
Expanding the control lines required physically rewiring a lot of critical stuff, so small mistakes can creep up and make mysterious errors down the road. Write a program that activates each control line at least once and make sure it works properly! With your assembler and Arduino programmer, this should be trivial.
Bonus: Adding B Register Output
With the additional control lines, don't forget you can now add a BO signal easily which lets you fully use the B register.

Step 3: Add a Stack (Image 1, Image 2)

Adding a stack significantly expands the capability of the CPU. It enables subroutines, recursion, and handling interrupts (with some additional logic). We'll create our stack with an 8-bit stack pointer hard-coded from $0100 to $01FF, just like the 6502.
Wiring up the Stack Pointer
A stack pointer is conceptually similar to a program counter. It stores an address, you can read it and write to it, and it increments. The only difference between a stack pointer and a program counter is that the stack pointer must also decrement. To create our stack pointer, we'll use two 74LS193 4-bit up/down binary counters:
  1. Place a 74LS00 NAND gate, 74LS245 transceiver, and two 74LS193 counters in a row next to your output register. Wire up power and ground.
  2. Wire the the Carry output of the right 193 to the Count Up input of the left 193. Do the same for the Borrow output and Count Down input.
  3. Connect the Clear input between the two 193s and with an active high reset line. The B register has one you can use on its 74LS173s.
  4. Connect the Load input between the two 193s and to a new active low control line called SI on your 74LS138 decoder.
  5. Connect the QA-QD outputs of the lower counter to A8-A5 and the upper counter to A4-A1. Pay special attention because the output are in a weird order (BACD) and you want to make sure the lower A is connected to A8 and the upper A is connected to A4.
  6. Connect the A-D inputs of the lower counter to B8-B5 and the upper counter to B4-B1. Again, the inputs are in a weird order and on both sides of the chip so pay special attention.
  7. Connect the B1-B8 outputs of the 74LS245 transceiver to the bus.
  8. On the 74LS245 transceiver, connect DIR to power (high) and connect OE to a new active low control line called SO on your 74LS138 decoder.
  9. Add 8 LEDs and resistors to the lower part of the 74LS245 transceiver (A1-A8) so you can see what's going on with the stack pointer.
Enabling Increment & Decrement
We've now connected everything but the Count Up and Count Down inputs. The way the 74LS193 works is that if nothing is counting, both inputs are high. If you want to increment, you keep Count Down high and pulse Count Up. To decrement, you do the opposite. We'll use a 74LS00 NAND gate for this:
  1. Take the clock from the 74LS08 AND gate and make it an input into two different NAND gates on the 74LS00.
  2. Take the output from one NAND gate and wire it to the Count Up input on the lower 74LS193 counter. Take the other output and wire it to the Count Down input.
  3. Wire up a new active high control line called SP from your ROM to the NAND gate going into Count Up.
  4. Wire up a new active high control line called SM from your ROM to the NAND gate going into Count Down.
At this point, everything should be working. Your counter should be able to reset, input a value, output a value, and increment/decrement. But the issue is it'll be writing to $0000 to $00FF in the RAM! Let's fix that.
Accessing Higher Memory Addresses
We need the stack to be in a different place in memory than our regular program. The problem is, we only have an 8-bit bus, so how do we tell the RAM we want a higher address? We'll use a special control line to do this:
  1. Wire up an active high line called SA from the 28C16 ROM to A8 on the Cypress CY7C199 RAM.
  2. Add an LED and resistor so you can see when the stack is active.
That's it! Now, whenever we need the stack we can use a combination of the control line and stack pointer to access $0100 to $01FF.
Updating the Instruction Set
All that's left now is to create some instructions that utilize the stack. We'll need to settle some conventions before we begin:
If you want to add a little personal flair to your design, you can change the convention fairly easily. Let's implement push and pop (source code):
  1. Define all your new control lines, such as #define SI 0x0700 and #define SO 0x0005.
  2. Create two new instructions: PSH (1011) and POP (1100).
  3. PSH starts the same as any other for the first two steps: MI|CO and RO|II|CE. The next step is to put the contents of the stack pointer into the address register via MI|SO|SA. Recall that SA is the special control line that tells the memory to access the $01XX bank rather than $00XX.
  4. We then take the contents of AO and write it into the RAM. We can also increment the stack pointer at this stage. All of this is done via: AO|RI|SP|SA, followed by TR.
  5. POP is pretty similar. Start off with MI|CO and RO|II|CE. We then need to take a cycle and decrement the stack pointer with SM. Like with PSH, we then set the address register with MI|SO|SA.
  6. We now just need to output the RAM into our A register with RO|AI|SA and then end the instruction with TR.
  7. Updating the assembler is easy since neither instruction has operands. For example, push is just psh -> 0x0B.
And that's it! Write some programs that take advantage of your new 256 byte stack to make sure everything works as expected.

Step 4: Add Subroutine Instructions (Image)

The last step to complete our stack is to add subroutine instructions. This allows us to write complex programs and paves the way for things like interrupt handling.
Subroutines are like a blend of push/pop instructions and a jump. Basically, when you want to call a subroutine, you save your spot in the program by pushing the program counter onto the stack, then jumping to the subroutine's location in memory. When you're done with the subroutine, you simply pop the program counter value from the stack and jump back into it.
We'll follow 6502 conventions and only save and restore the program counter for subroutines. Other CPUs may choose to save more state, but it's generally left up to the programmer to ensure they're not wiping out states in their subroutines (e.g., push the A register at the start of your subroutine if you're messing with it and restore it before you leave).
Adding an Extra Opcode Line
I've started running low on opcodes at this point. Luckily, we still have two free address lines we can use. To enable 5-bit opcodes, simply wire up the 4Q output of your upper 74LS173 register to A7 of your 28C16 ROM (this assumes your opcodes are at A3-A6).
Updating the ROM Writer
At this point, you simply need to update the Arduino writer to support 32 instructions vs. the current 16. So, for example, UCODE_TEMPLATE[16][8] becomes UCODE_TEMPLATE[32][8] and you fill in the 16 new array elements with nop. The problem is that the Arduino only has so much memory and with the way Ben's code is written to support conditional jumps, it starts to get tight.
I bet the code can be re-written to handle this, but I had a TL866II Plus EEPROM programmer handy from the 6502 build and I felt it would be easier to start using that instead. Converting to a regular C program is really simple (source code):
  1. Copy all the #define, global const arrays (don't forget to expand them from 16 to 32), and void initUCode(). Add #include and #include to the top.
  2. In your traditional int main (void) C function, after initializing with initUCode(), make two arrays: char ucode_upper[2048] and char ucode_lower[2048].
  3. Take your existing loop code that loops through all addresses: for (int address = 0; address < 2048; address++).
  4. Modify instruction to be 5-bit with int instruction = (address & 0b00011111000) >> 3;.
  5. When writing, just write to the arrays like so: ucode_lower[address] = ucode[flags][instruction][step]; and ucode_upper[address] = ucode[flags][instruction][step] >> 8;.
  6. Open a new file with FILE *f = fopen("rom_upper.hex", "wb");, write to it with fwrite(ucode_upper, sizeof(char), sizeof(ucode_upper), f); and close it with fclose(f);. Repeat this with the lower ROM too.
  7. Compile your code using gcc (you can use any C compiler), like so: gcc -Wall makerom.c -o makerom.
Running your program will spit out two binary files with the full contents of each ROM. Writing the file via the TL866II Plus requires minipro and the following command: minipro -p CAT28C16A -w rom_upper.hex.
Adding Subroutine Instructions
At this point, I cleaned up my instruction set layout a bit. I made psh and pop 1000 and 1001, respectively. I then created two new instructions: jsr and rts. These allow us to jump to a subroutine and returns from a subroutine. They're relatively simple:
  1. For jsr, the first three steps are the same as psh: MI|CO, RO|II|CE, MI|SO|SA.
  2. On the next step, instead of AO we use CO to save the program counter to the stack: CO|RI|SP|SA.
  3. We then essentially read the 2nd byte to do a jump and terminate: MI|CO, RO|J.
  4. For rts, the first four steps are the same as pop: MI|CO, RO|II|CE, SM, MI|SO|SA.
  5. On the next step, instead of AI we use J to load the program counter with the contents in stack: RO|J|SA.
  6. We're not done! If we just left this as-is, we'd jump to the 2nd byte of jsr which is not an opcode, but a memory address. All hell would break loose! We need to add a CE step to increment the program counter and then terminate.
Once you update the ROM, you should have fully functioning subroutines with 5-bit opcodes. One great way to test them is to create a recursive program to calculate something--just don't go too deep or you'll end up with a stack overflow!

Conclusion

And that's it! Another successful upgrade of your 8-bit CPU. You now have a very capable machine and toolchain. At this point I would have a bunch of fun with the software aspects. In terms of hardware, there's a number of ways to go from here:
  1. Interrupts. Interrupts are just special subroutines triggered by an external line. You can make one similar to how Ben did conditional jumps. The only added complexity is the need to load/save the flags register since an interrupt can happen at any time and you don't want to destroy the state. Given this would take more than 8 steps, you'd also need to add another line for the step counter (see below).
  2. ROM expansion. At this point, address lines on the ROM are getting tight which limits any expansion possibilities. With the new approach to ROM programming, it's trivial to switch out the 28C16 for the 28C256 that Ben uses in the 6502. These give you 4 additional address lines for flags/interrupts, opcodes, and steps.
  3. LCD output. At this point, adding a 16x2 character LCD like Ben uses in the 6502 is very possible.
  4. Segment/bank register. It's essentially a 2nd memory address register that lets you access 256-byte segments/banks of RAM using bank switching. This lets you take full advantage of the 32K of RAM in the Cypress chip.
  5. Fast increment instructions. Add these to registers by replacing 74LS173s with 74LS193s, allowing you to more quickly increment without going through the ALU. This is used to speed up loops and array operations.
submitted by MironV to beneater [link] [comments]

Trying to get my PC screen to be sent over serial and displayed on a nokia 5110, I think the PC side works but I can't get it to display on the screen correctly. If someone could look over my code that would be great.

I'm not exactly sure of the formatting NumPY uses to convert image to binary array, so the arduino code might just be recieving the data incorrectly. I don't know how to fix that if that is the issue though.
PC python code
from PIL import Image import pyautogui import os import numpy as np import serial ser = serial.Serial() ser.baudrate = 115200 ser.port = 'COM4' ser.open() loop = 0 img_row = 0 img_column = 0 def black_and_white(input_image_path, output_image_path): color_image = Image.open(input_image_path) bw = color_image.convert('1', dither=Image.NONE) bw.save(output_image_path) #while(loop < 1): while(True): image = pyautogui.screenshot() image.save(r'C:\Users\lordl\Desktop\scrnshot\pic.png') black_and_white('pic.png', 'bw_pic.png') image = Image.open('bw_pic.png') image = image.resize((84, 48)) image.save('resized.png') image = Image.open('resized.png') img_array = np.array(image) binarr = np.where(img_array==True, 1, 0) while(img_column < 84): while(img_row < 48): #print(binarr[img_row, img_column]) ser.write(binarr[img_row,img_column]) img_row = img_row + 1 img_column = img_column + 1 img_row = 0 ser.write(b'3') img_column = 0 loop += 1 os.remove('pic.png') os.remove('bw_pic.png') os.remove('resized.png') print(loop) 
Arduino code:
#include  #include  #include  // Software SPI (slower updates, more flexible pin options): // pin 7 - Serial clock out (SCLK) // pin 6 - Serial data out (DIN) // pin 5 - Data/Command select (D/C) // pin 4 - LCD chip select (CS) // pin 3 - LCD reset (RST) Adafruit_PCD8544 display = Adafruit_PCD8544(D4, D3, D2, D0, D1); void setup() { // put your setup code here, to run once: Serial.begin(115200); display.begin(); display.setContrast(50); display.display(); // show splashscreen delay(500); display.clearDisplay(); } int row = 0; int column = 0; bool newData = false; int i; int a; void loop() { // put your main code here, to run repeatedly: char receivedChars[8065]; // an array to store the received data static byte ndx = 0; char endMarker = '3'; char rc; while (Serial.available() > 0 && newData == false) { rc = Serial.read(); if (rc != endMarker) { receivedChars[ndx] = rc; ndx++; if (ndx >= 4032) { ndx = 4032 - 1; } } else { receivedChars[ndx] = '3'; // terminate the string ndx = 0; newData = true; } } column = 0; if (newData == true) { while (column < 84) { while (row < 48) { i = column*84 + row; a = receivedChars[i]; display.drawPixel(column, row, a); row = row + 1; } column = column + 1; row = 0; display.display(); } newData = false; } } 
submitted by OverclockedPizza to arduino [link] [comments]

C++ *char pointer

Hey guys. I have to do the following:
Create a class node of a binary tree with the following parameters: Name of the node (pointer to a character string), value (real number), pointer to a left child (Node *left) and a pointer to a right child (Node *right). Create constructor, destructor, input and output of node value.
The program menu needs to have the following options:
-Creating a binary tree by adding a new node;
-Removing a node by a given name;
-Searching for a node by value;
-Print all nodes of the tree.
Create a base abstract class, containing a clear virtual function for information output.

My parameters are:


#include
#include
#include
using namespace std;


struct node{
int value; char *name; node *left; node *right; 
};




The binary tree class is this
cclass btree{
public:
btree(); \~btree(); 

void insert(int key, char \*name); //Inserts a new node node \*search(int key); //searches by node value and returns node name void destroy\_tree(); //destroys the tree void tree\_print(); //prints all node values int FindSmallest(); //finds smallest value in right branch 



private:
void destroy\_tree(node \*leaf); void insert(int key, char \*name, node \*leaf); node \*search(int key, node \*leaf); node \*searchName(char \*name, node \*leaf); void tree\_print(node \*leaf); int FindSmallest(node\* Ptr); node \*root; 
};
//Деструктор
btree::~btree(){
destroy\_tree(); 
}



//tree deletion
void btree::destroy_tree(node *leaf){
if(leaf != NULL){ destroy\_tree(leaf->left); destroy\_tree(leaf->right); delete leaf; } 
}

void btree::destroy_tree(){
destroy\_tree(root); 
}




//adding a node - I believe my Issue is here - When adding a new node (value and name) the value is saved properly, but the name gets changed for more than one node - for example if I have the following nodes: 2 "Sam"
5 "George"
and then if I input 1 "Leonardo" and the names of the other nodes change too. It seems to be at random, because it happens only to some nodes.
void btree::insert(int key, char *name, node *leaf){
if(key < leaf->value){ if(leaf->left != NULL){ insert(key, leaf->name, leaf->left); }else{ leaf->left = new node; leaf->left->value = key; leaf->left->name=name; leaf->left->left = NULL; leaf->left->right = NULL; } }else if(key >= leaf->value){ if(leaf->right != NULL){ insert(key, name, leaf->right); }else{ leaf->right = new node; leaf->right->value = key; leaf->right->name=name; leaf->right->right = NULL; leaf->right->left = NULL; } } 

}
void btree::insert(int key, char *name){
if(root != NULL){ insert(key, name, root); }else{ root = new node; root->value = key; root->name = name; root->left = NULL; root->right = NULL; } 
}





//Searching by a value - I believe this functionality works correctly.
node *btree::search(int key, node *leaf)
{
if(leaf!=NULL)
{
if(key==leaf->value)
cout<name;
return leaf;
if(keyvalue)
return search(key, leaf->left);
else
return search(key, leaf->right);
}
else return NULL;
}

node *btree::search(int key){
return search(key, root); 
}





//Tree printing - When printing the issue with the mismatching names becomes obvious. If I use a set of nodes that are defined withing the code everything works fine, but when i input any via the "insert" function the names are not corresponding with the values. I believe it might be due to the *char not having different instances for the different nodes
void btree::tree_print(){
tree\_print(root); cout << "\\n"; 
}

void btree::tree_print(node *leaf){
if(leaf != NULL){ cout << leaf->value << ","; cout << leaf->name << ","<left); tree\_print(leaf->right); } 
}




//FindSmallest - it works correctly.
int btree::FindSmallest(){
return FindSmallest(root);
}

int btree::FindSmallest(node* Ptr){
if(root==NULL){
cout<<"The tree is empty\n";
return -1000;
}
else{
if(Ptr->left!=NULL)
{
return FindSmallest(Ptr->left);
}
else{
return Ptr->value;
}

}
}




nt main(){
int new_node_value; //it is used for input
btree \*tree = new btree(); char selection; //selection for the menu char nameInput\[20\]; //name input for the nodes tree->insert(8, name); tree->tree\_print(); tree->insert(6,"minko"); tree->insert(82,"dasdasd"); tree->insert(655,"ityi"); tree->insert(8523,"p555esho"); tree->insert(6235,"mi552nko"); tree->insert(8,"ivan"); 

do
{
cout << " 1. Add tree node\n";
cout << " 2. Delete tree node by name\n";
cout << " 3. Search tree node by value\n";
cout << " 4. Print all nodes\n";
cout << "\n";
cout << " 5. Exit\n";
cout << " ====================================\n";
cout << " Enter your selection: ";
cin >> selection;
cout << endl;

switch (selection)
{

case '1':

cout << "Enter new node value\n";
cin>>(new_node_value);
fflush(stdin);
cout << "Enter new node name\n";
gets(nameInput);
tree->insert(new_node_value, nameInput);
cout << "\n";
break;





case '2':
cout << "Enter node name you wish to delete\n";

fflush(stdin);
gets(nameInput);
// tree->gotree(root, nameInput);
// tree->searchName(nameInput);
cout << "\n";
break;





case '3':
cout << "Enter node value to search\n" ;
cin>>(new_node_value);
tree->search (new_node_value);
cout << "\n";
break;




case '4':
cout << "Print all nodes\n";
tree->tree_print();
cout << "\n";
break;



case '5':
cout << "Goodbye.\n";
delete tree;
break;

default: cout < cout << endl;
}


}while (selection != 0 );
return 0;
}



So my first issue is that when adding a new node using the insert(); function, after adding a new node, the name of the one I added previously becomes the same as the current one. How can I fix that?

Issue number two: How would I go about going through the nodes of the tree and finding one with a name that matches my input? I tried a few things but since my insert method isn't working correctly I couldn't check if this worked either.

I'm sorry if my original post wasn't clear enough but I tried to do this all night and didn't get any sleep.
submitted by narupaparu to cpp_questions [link] [comments]

Differences between LISP 1.5 and Common Lisp, Part 1:

[Edit: I didn't mean to put a colon in the title.]
In this post we'll be looking at some of the things that make LISP 1.5 and Common Lisp different. There isn't too much surviving LISP 1.5 code, but some of the code that is still around is interesting and worthy of study.
Here are some conventions used in this post of which you might take notice:
Sources are linked sometimes below, but here is a list of links that were helpful while writing this:
The differences between LISP 1.5 and Common Lisp can be classified into the following groups:
  1. Superficial differences—matters of syntax
  2. Conventional differences—matters of code style and form
  3. Fundamental differences—matters of semantics
  4. Library differences—matters of available functions
This post will go through the first three of these groups in that order. A future post will discuss library differences, except for some functions dealing with character-based input and output, since they are a little world unto their own.
[Originally the library differences were part of this post, but it exceeded the length limit on posts (40000 characters)].

Superficial differences.

LISP 1.5 was used initially on computers that had very limited character sets. The machine on which it ran at MIT, the IBM 7090, used a six-bit, binary-coded decimal encoding for characters, which could theoretically represent up to sixty-four characters. In practice, only fourty-six were widely used. The repertoire of this character set consisted of the twenty-six uppercase letters, the nine digits, the blank character '', and the ten special characters '-', '/', '=', '.', '$', ',', '(', ')', '*', and '+'. You might note the absence of the apostrophe/single quote—there was no shorthand for the quote operator in LISP 1.5 because no sensical character was available.
When the LISP 1.5 system read input from cards, it treated the end of a card not like a blank character (as is done in C, TeX, etc.), but as nothing. Therefore the first character of a symbol's name could be the last character of a card, the remaining characters appearing at the beginning of the next card. Lisp's syntax allowed for the omission of almost all whitespace besides that which was used as delimiters to separate tokens.
List syntax. Lists were contained within parentheses, as is the case in Common Lisp. From the beginning Lisp had the consing dot, which was written as a period in LISP 1.5; the interaction between the period when used as the consing dot and the period when used as the decimal point will be described shortly.
In LISP 1.5, the comma was equivalent to a blank character; both could be used to delimit items within a list. The LISP I Programmer's Manual, p. 24, tells us that
The commas in writing S-expressions may be omitted. This is an accident.
Number syntax. Numbers took one of three forms: fixed-point integers, floating-point numbers, and octal numbers. (Of course octal numbers were just an alternative notation for the fixed-point integers.)
Fixed-point integers were written simply as the decimal representation of the integers, with an optional sign. It isn't explicitly mentioned whether a plus sign is allowed in this case or if only a minus sign is, but floating-point syntax does allow an initial plus sign, so it makes sense that the fixed-point number syntax would as well.
Floating-point numbers had the syntax described by the following context-free grammar, where a term in square brackets indicates that the term is optional:
float: [sign] integer '.' [integer] exponent [sign] integer '.' integer [exponent] exponent: 'E' [sign] digit [digit] integer: digit integer digit digit: one of '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' sign: one of '+' '-' 
This grammar generates things like 100.3 and 1.E5 but not things like .01 or 14E2 or 100.. The manual seems to imply that if you wrote, say, (100. 200), the period would be treated as a consing dot [the result being (cons 100 200)].
Floating-point numbers are limited in absolute value to the interval (2-128, 2128), and eight digits are significant.
Octal numbers are defined by the following grammar:
octal: [sign] octal-digits 'Q' [integer] octal-digits: octal-digit [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] [octal-digit] octal-digit: one of '0' '1' '2' '3' '4' '5' '6' '7' 
The optional integer following 'Q' is a scale factor, which is a decimal integer representing an exponent with a base of 8. Positive octal numbers behave as one would expect: The value is shifted to the left 3×s bits, where s is the scale factor. Octal was useful on the IBM 7090, since it used thirty-six-bit words; twelve octal digits (which is the maximum allowed in an octal number in LISP 1.5) thus represent a single word in a convenient way that is more compact than binary (but still being easily convertable to and from binary). If the number has a negative sign, then the thirty-sixth bit is logically ored with 1.
The syntax of Common Lisp's numbers is a superset of that of LISP 1.5. The only major difference is in the notation of octal numbers; Common Lisp uses the sharpsign reader macro for that purpose. Because of the somewhat odd semantics of the minus sign in octal numbers in LISP 1.5, it is not necessarily trivial to convert a LISP 1.5 octal number into a Common Lisp expression resulting in the same value.
Symbol syntax. Symbol names can be up to thirty characters in length. While the actual name of a symbol was kept on its property list under the pname indicator and could be any sequence of thirty characters, the syntax accepted by the read program for symbols was limited in a few ways. First, it must not begin with a digit or with either of the characters '+' or '-', and the first two characters cannot be '$'. Otherwise, all the alphanumeric characters, along with the special characters '+', '-', '=', '*', '/', and '$'. The fact that a symbol can't begin with a sign character or a digit has to do with the number syntax; the fact that a symbol can't begin with '$$' has to do with the mechanism by which the LISP 1.5 reader allowed you to write characters that are usually not allowed in symbols, which is described next.
Two dollar signs initiated the reading of what we today might call an "escape sequence". An escape sequence had the form "$$xSx", where x was any character and S was a sequence of up to thirty characters not including x. For example, $$x()x would get the symbol whose name is '()' and would print as '()'. Thus it is similar in purpose to Common Lisp's | syntax. There is a significant difference: It could not be embedded within a symbol, unlike Common Lisp's |. In this respect it is closer to Maclisp's | reader macro (which created a single token) than it is to Common Lisp's multiple escape character. In LISP 1.5, "A$$X()X$" would be read as (1) the symbol A$$X, (2) the empty list, (3) the symbol X.
The following code sets up a $ reader macro so that symbols using the $$ notation will be read in properly, while leaving things like $eof$ alone.
(defun dollar-sign-reader (stream character) (declare (ignore character)) (let ((next (read-char stream t nil t))) (cond ((char= next #\$) (let ((terminator (read-char stream t nil t))) (values (intern (with-output-to-string (name) (loop for c := (read-char stream t nil t) until (char= c terminator) do (write-char c name))))))) (t (unread-char next stream) (with-standard-io-syntax (read (make-concatenated-stream (make-string-input-stream "$") stream) t nil t)))))) (set-macro-character #\$ #'dollar-sign-reader t) 

Conventional differences.

LISP 1.5 is an old programming language. Generally, compared to its contemporaries (such as FORTRANs I–IV), it holds up well to modern standards, but sometimes its age does show. And there were some aspects of LISP 1.5 that might be surprising to programmers familiar only with Common Lisp or a Scheme.
M-expressions. John McCarthy's original concept of Lisp was a language with a syntax like this (from the LISP 1.5 Programmer's Manual, p. 11):
equal[x;y]=[atom[x]→[atom[y]→eq[x;y]; T→F]; equal[car[x];car[Y]]→equal[cdr[x];cdr[y]]; T→F] 
There are several things to note. First is the entirely different phrase structure. It's is an infix language looking much closer to mathematics than the Lisp we know and love. Square brackets are used instead of parentheses, and semicolons are used instead of commas (or blanks). When square brackets do not enclose function arguments (or parameters when to the left of the equals sign), they set up a conditional expression; the arrows separate predicate expressions and consequent expressions.
If that was Lisp, then where do s-expressions come in? Answer: quoting. In the m-expression notation, uppercase strings of characters represent quoted symbols, and parenthesized lists represent quoted lists. Here is an example from page 13 of the manual:
λ[[x;y];cons[car[x];y]][(A B);(C D)] 
As an s-expressions, this would be
((lambda (x y) (cons (car x) y)) '(A B) '(C D)) 
The majority of the code in the manual is presented in m-expression form.
So why did s-expressions stick? There are a number of reasons. The earliest Lisp interpreter was a translation of the program for eval in McCarthy's paper introducing Lisp, which interpreted quoted data; therefore it read code in the form of s-expressions. S-expressions are much easier for a computer to parse than m-expressions, and also more consistent. (Also, the character set mentioned above includes neither square brackets nor a semicolon, let alone a lambda character.) But in publications m-expressions were seen frequently; perhaps the syntax was seen as a kind of "Lisp pseudocode".
Comments. LISP 1.5 had no built-in commenting mechanism. It's easy enough to define a comment operator in the language, but it seemed like nobody felt a need for them.
Interestingly, FORTRAN I had comments. Assembly languages of the time sort of had comments, in that they had a portion of each line/card that was ignored in which you could put any text. FORTRAN was ahead of its time.
(Historical note: The semicolon comment used in Common Lisp comes from Maclisp. Maclisp likely got it from PDP-10 assembly language, which let a semicolon and/or a line break terminate a statement; thus anything following a semicolon is ignored. The convention of octal numbers by default, decimal numbers being indicated by a trailing decimal point, of Maclisp too comes from the assembly language.)
Code formatting. The code in the manual that isn't written using m-expression syntax is generally lacking in meaningful indentation and spacing. Here is an example (p. 49):
(TH1 (LAMBDA (A1 A2 A C) (COND ((NULL A) (TH2 A1 A2 NIL NIL C)) (T (OR (MEMBER (CAR A) C) (COND ((ATOM (CAR A)) (TH1 (COND ((MEMBER (CAR A) A1) A1) (T (CONS (CAR A) A1))) A2 (CDR A) C)) (T (TH1 A1 (COND ((MEMBER (CAR A) A2) A2) (T (CONS (CAR A) A2))) (CDR A) C)))))))) 
Nowadays we might indent it like so:
(TH1 (LAMBDA (A1 A2 A C) (COND ((NULL A) (TH2 A1 A2 NIL NIL C)) (T (OR (MEMBER (CAR A) C) (COND ((ATOM (CAR A)) (TH1 (COND ((MEMBER (CAR A) A1) A1) (T (CONS (CAR A) A1))) A2 (CDR A) C)) (T (TH1 A1 (COND ((MEMBER (CAR A) A2) A2) (T (CONS (CAR A) A2))) (CDR A) C)))))))) 
Part of the lack of formatting stems probably from the primarily punched-card-based programming world of the time; you would see the indented structure only by printing a listing of your code, so there is no need to format the punched cards carefully. LISP 1.5 allowed a very free format, especially when compared to FORTRAN; the consequence is that early LISP 1.5 programs are very difficult to read because of the lack of spacing, while old FORTRAN programs are limited at least to one statement per line.
The close relationship of Lisp and pretty-printing originates in programs developed to produce nicely formatted listings of Lisp code.
Lisp code from the mid-sixties used some peculiar formatting conventions that seem odd today. Here is a quote from Steele and Gabriel's Evolution of Lisp:
This intermediate example is derived from a 1966 coding style:
DEFINE(( (MEMBER (LAMBDA (A X) (COND ((NULL X) F) ((EQ A (CAR X) ) T) (T (MEMBER A (CDR X))) ))) )) 
The design of this style appears to take the name of the function, the arguments, and the very beginning of the COND as an idiom, and hence they are on the same line together. The branches of the COND clause line up, which shows the structure of the cases considered.
This kind of indentation is somewhat reminiscent of the formatting of Algol programs in publications.
Programming style. Old LISP 1.5 programs can seem somewhat primitive. There is heavy use of the prog feature, which is related partially to the programming style that was common at the time and partially to the lack of control structures in LISP 1.5. You could express iteration only by using recursion or by using prog+go; there wasn't a built-in looping facility. There is a library function called for that is something like the early form of Maclisp's do (the later form would be inherited in Common Lisp), but no surviving LISP 1.5 code uses it. [I'm thinking of making another post about converting programs using prog to the more structured forms that Common Lisp supports, if doing so would make the logic of the program clearer. Naturally there is a lot of literature on so called "goto elimination" and doing it automatically, so it would not present any new knowledge, but it would have lots of Lisp examples.]
LISP 1.5 did not have a let construct. You would use either a prog and setq or a lambda:
(let ((x y)) ...) 
is equivalent to
((lambda (x) ...) y) 
Something that stands out immediately when reading LISP 1.5 code is the heavy, heavy use of combinations of car and cdr. This might help (though car and cdr should be left alone when they are used with dotted pairs):
(car x) = (first x) (cdr x) = (rest x) (caar x) = (first (first x)) (cadr x) = (second x) (cdar x) = (rest (first x)) (cddr x) = (rest (rest x)) (caaar x) = (first (first (first x))) (caadr x) = (first (second x)) (cadar x) = (second (first x)) (caddr x) = (third x) (cdaar x) = (rest (first (first x))) (cdadr x) = (rest (second x)) (cddar x) = (rest (rest (first x))) (cdddr x) = (rest (rest (rest x))) 
Here are some higher compositions, even though LISP 1.5 doesn't have them.
(caaaar x) = (first (first (first (first x)))) (caaadr x) = (first (first (second x))) (caadar x) = (first (second (first x))) (caaddr x) = (first (third x)) (cadaar x) = (second (first (first x))) (cadadr x) = (second (second x)) (caddar x) = (third (first x)) (cadddr x) = (fourth x) (cdaaar x) = (rest (first (first (first x)))) (cdaadr x) = (rest (first (second x))) (cdadar x) = (rest (second (first x))) (cdaddr x) = (rest (third x)) (cddaar x) = (rest (rest (first (first x)))) (cddadr x) = (rest (rest (second x))) (cdddar x) = (rest (rest (rest (first x)))) (cddddr x) = (rest (rest (rest (rest x)))) 
Things like defstruct and Flavors were many years away. For a long time, Lisp dialects had lists as the only kind of structured data, and programmers rarely defined functions with meaningful names to access components of data structures that are represented as lists. Part of understanding old Lisp code is figuring out how data structures are built up and what their components signify.
In LISP 1.5, it's fairly common to see nil used where today we'd use (). For example:
(LAMBDA NIL ...) 
instead of
(LAMBDA () ...) 
or (PROG NIL ...)
instead of
(PROG () ...) 
Actually this practice was used in other Lisp dialects as well, although it isn't really seen in newer code.
Identifiers. If you examine the list of all the symbols described in the LISP 1.5 Programmer's Manual, you will notice that none of them differ only in the characters after the sixth character. In other words, it is as if symbol names have only six significant characters, so that abcdef1 and abcdef2 would be considered equal. But it doesn't seem like that was actually the case, since there is no mention of such a limitation in the manual. Another thing of note is that many symbols are six characters or fewer in length.
(A sequence of six characters is nice to store on the hardware on which LISP 1.5 was running. The processor used thirty-six-bit words, and characters were six-bit; therefore six characters fit in a single word. It is conceivable that it might be more efficient to search for names that take only a single word to store than for names that take more than one word to store, but I don't know enough about the computer or implementation of LISP 1.5 to know if that's true.)
Even though the limit on names was thirty characters (the longest symbol names in standard Common Lisp are update-instance-for-different-class and update-instance-for-redefined-class, both thirty-five characters in length), only a few of the LISP 1.5 names are not abbreviated. Things like terpri ("terminate print") and even car and cdr ("contents of adress part of register" and "contents of decrement part of register"), which have stuck around until today, are pretty inscrutable if you don't know what they mean.
Thankfully the modern style is to limit abbreviations. Comparing the names that were introduced in Common Lisp versus those that have survived from LISP 1.5 (see the "Library" section below) shows a clear preference for good naming in Common Lisp, even at the risk of lengthy names. The multiple-value-bind operator could easily have been named mv-bind, but it wasn't.

Fundamental differences.

Truth values. Common Lisp has a single value considered to be false, which happens to be the same as the empty list. It can be represented either by the symbol nil or by (); either of these may be quoted with no difference in meaning. Anything else, when considered as a boolean, is true; however, there is a self-evaluating symbol, t, that traditionally is used as the truth value whenever there is no other more appropriate one to use.
In LISP 1.5, the situation was similar: Just like Common Lisp, nil or the empty list are false and everything else is true. But the symbol nil was used by programmers only as the empty list; another symbol, f, was used as the boolean false. It turns out that f is actually a constant whose value is nil. LISP 1.5 had a truth symbol t, like Common Lisp, but it wasn't self-evaluating. Instead, it was a constant whose permanent value was *t*, which was self-evaluating. The following code will set things up so that the LISP 1.5 constants work properly:
(defconstant *t* t) ; (eq *t* t) is true (defconstant f nil) 
Recall the practice in older Lisp code that was mentioned above of using nil in forms like (lambda nil ...) and (prog nil ...), where today we would probably use (). Perhaps this usage is related to the fact that nil represented an empty list more than it did a false value; or perhaps the fact that it seems so odd to us now is related to the fact that there is even less of a distinction between nil the empty list and nil the false value in Common Lisp (there is no separate f constant).
Function storage. In Common Lisp, when you define a function with defun, that definition gets stored somehow in the global environment. LISP 1.5 stores functions in a much simpler way: A function definition goes on the property list of the symbol naming it. The indicator under which the definition is stored is either expr or fexpr or subr or fsubr. The expr/fexpr indicators were used when the function was interpreted (written in Lisp); the subr/fsubr indicators were used when the function was compiled (or written in machine code). Functions can be referred to based on the property under which their definitions are stored; for example, if a function named f has a definition written in Lisp, we might say that "f is an expr."
When a function is interpreted, its lambda expression is what is stored. When a function is compiled or machine coded, a pointer to its address in memory is what is stored.
The choice between expr and fexpr and between subr and fsubr is based on evaluation. Functions that are exprs and subrs are evaluated normally; for example, an expr is effectively replaced by its lambda expression. But when an fexpr or an fsubr is to be processed, the arguments are not evaluated. Instead they are put in a list. The fexpr or fsubr definition is then passed that list and the current environment. The reason for the latter is so that the arguments can be selectively evaluated using eval (which took a second argument containing the environment in which evaluation is to occur). Here is an example of what the definition of an fexpr might look like, LISP 1.5 style. This function takes any number of arguments and prints them all, returning nil.
(LAMBDA (A E) (PROG () LOOP (PRINT (EVAL (CAR A) E)) (COND ((NULL (CDR A)) (RETURN NIL))) (SETQ A (CDR A)) (GO LOOP))) 
The "f" in "fexpr" and "fsubr" seems to stand for "form", since fexpr and fsubr functions got passed a whole form.
The top level: evalquote. In Common Lisp, the interpreter is usually available interactively in the form of a "Read-Evaluate-Print-Loop", for which a common abbreviation is "REPL". Its structure is exactly as you would expect from that name: Repeatedly read a form, evaluate it (using eval), and print the results. Note that this model is the same as top level file processing, except that the results of only the last form are printed, when it's done.
In LISP 1.5, the top level is not eval, but evalquote. Here is how you could implement evalquote in Common Lisp:
(defun evalquote (operator arguments) (eval (cons operator arguments))) 
LISP 1.5 programs commonly look like this (define takes a list of function definitions):
DEFINE (( (FUNCTION1 (LAMBDA () ...)) (FUNCTION2 (LAMBDA () ...)) ... )) 
which evalquote would process as though it had been written
(DEFINE ( (FUNCTION1 (LAMBDA () ...)) (FUNCTION2 (LAMBDA () ...)) ... )) 
Evaluation, scope, extent. Before further discussion, here the evaluator for LISP 1.5 as presented in Appendix B, translated from m-expressions to approximate Common Lisp syntax. This code won't run as it is, but it should give you an idea of how the LISP 1.5 interpreter worked.
(defun evalquote (function arguments) (if (atom function) (if (or (get function 'fexpr) (get function 'fsubr)) (eval (cons function arguments) nil)) (apply function arguments nil))) (defun apply (function arguments environment) (cond ((null function) nil) ((atom function) (let ((expr (get function 'expr)) (subr (get function 'subr))) (cond (expr (apply expr arguments environment)) (subr ; see below ) (t (apply (cdr (sassoc function environment (lambda () (error "A2")))) arguments environment))))) ((eq (car function 'label)) (apply (caddr function) arguments (cons (cons (cadr function) (caddr function)) arguments))) ((eq (car function) 'funarg) (apply (cadr function) arguments (caddr function))) ((eq (car function) 'lambda) (eval (caddr function) (nconc (pair (cadr function) arguments) environment))) (t (apply (eval function environment) arguments environment)))) (defun eval (form environment) (cond ((null form) nil) ((numberp form) form) ((atom form) (let ((apval (get atom 'apval))) (if apval (car apval) (cdr (sassoc form environment (lambda () (error "A8"))))))) ((eq (car form) 'quote) (cadr form)) ((eq (car form) 'function) (list 'funarg (cadr form) environment)) ((eq (car form) 'cond) (evcon (cdr form) environment)) ((atom (car form)) (let ((expr (get (car form) 'expr)) (fexpr (get (car form) 'fexpr)) (subr (get (car form) 'subr)) (fsubr (get (car form) 'fsubr))) (cond (expr (apply expr (evlis (cdr form) environment) environment)) (fexpr (apply fexpr (list (cdr form) environment) environment)) (subr ; see below ) (fsubr ; see below ) (t (eval (cons (cdr (sassoc (car form) environment (lambda () (error "A9")))) (cdr form)) environment))))) (t (apply (car form) (evlis (cdr form) environment) environment)))) (defun evcon (cond environment) (cond ((null cond) (error "A3")) ((eval (caar cond) environment) (eval (cadar cond) environment)) (t (evcon (cdr cond) environment)))) (defun evlis (list environment) (maplist (lambda (j) (eval (car j) environment)) list)) 
(The definition of evalquote earlier was a simplification to avoid the special case of special operators in it. LISP 1.5's apply can't handle special operators (which is also true of Common Lisp's apply). Hopefully the little white lie can be forgiven.)
There are several things to note about these definitions. First, it should be reiterated that they will not run in Common Lisp, for many reasons. Second, in evcon an error has been corrected; the original says in the consequent of the second branch (effectively)
(eval (cadar environment) environment) 
Now to address the "see below" comments. In the manual it describes the actions of the interpreter as calling a function called spread, which takes the arguments given in a Lisp function call and puts them into the machine registers expected with LISP 1.5's calling convention, and then executes an unconditional branch instruction after updating the value of a variable called $ALIST to the environment passed to eval or to apply. In the case of fsubr, instead of calling spread, since the function will always get two arguments, it places them directly in the registers.
You will note that apply is considered to be a part of the evaluator, while in Common Lisp apply and eval are quite different. Here it takes an environment as its final argument, just like eval. This fact highlights an incredibly important difference between LISP 1.5 and Common Lisp: When a function is executed in LISP 1.5, it is run in the environment of the function calling it. In contrast, Common Lisp creates a new lexical environment whenever a function is called. To exemplify the differences, the following code, if Common Lisp were evaluated like LISP 1.5, would be valid:
(defun weird (a b) (other-weird 5)) (defun other-weird (n) (+ a b n)) 
In Common Lisp, the function weird creates a lexical environment with two variables (the parameters a and b), which have lexical scope and indefinite extent. Since the body of other-weird is not lexically within the form that binds a and b, trying to make reference to those variables is incorrect. You can thwart Common Lisp's lexical scoping by declaring those variables to have indefinite scope:
(defun weird (a b) (declare (special a b)) (other-weird 5)) (defun other-weird (n) (declare (special a b)) (+ a b n)) 
The special declaration tells the implementation that the variables a and b are to have indefinite scope and dynamic extent.
Let's talk now about the funarg branch of apply. The function/funarg device was introduced some time in the sixties in an attempt to solve the scoping problem exemplified by the following problematic definition (using Common Lisp syntax):
(defun testr (x p f u) (cond ((funcall p x) (funcall f x)) ((atom x) (funcall u)) (t (testr (cdr x) p f (lambda () (testr (car x) p f u)))))) 
This function is taken from page 11 of John McCarthy's History of Lisp.
The only problematic part is the (car x) in the lambda in the final branch. The LISP 1.5 evaluator does little more than textual substitution when applying functions; therefore (car x) will refer to whatever x is currently bound whenever the function (lambda expression) is applied, not when it is written.
How do you fix this issue? The solution employed in LISP 1.5 was to capture the environment present when the function expression is written, using the function operator. When the evaluator encounters a form that looks like (function f), it converts it into (funarg f environment), where environment is the current environment during that call to eval. Then when apply gets a funarg form, it applies the function in the environment stored in the funarg form instead of the environment passed to apply.
Something interesting arises as a consequence of how the evaluator works. Common Lisp, as is well known, has two separate name spaces for functions and for variables. If a Common Lisp implementation encounters
(lambda (f x) (f x)) 
the result is not a function applying one of its arguments to its other argument, but rather a function applying a function named f to its second argument. You have to use an operator like funcall or apply to use the functional value of the f parameter. If there is no function named f, then you will get an error. In contrast, LISP 1.5 will eventually find the parameter f and apply its functional value, if there isn't a function named f—but it will check for a function definition first. If a Lisp dialect that has a single name space is called a "Lisp-1", and one that has two name spaces is called a "Lisp-2", then I guess you could call LISP 1.5 a "Lisp-1.5"!
How can we deal with indefinite scope when trying to get LISP 1.5 programs to run in Common Lisp? Well, with any luck it won't matter; ideally the program does not have any references to variables that would be out of scope in Common Lisp. However, if there are such references, there is a fairly simple fix: Add special declarations everywhere. For example, say that we have the following (contrived) program, in which define has been translated into defun forms to make it simpler to deal with:
(defun f (x) (prog (m) (setq m a) (setq a 7) (return (+ m b x)))) (defun g (l) (h (* b a))) (defun h (i) (/ l (f (setq b (setq a i))))) (defun p () (prog (a b i) (setq a 4) (setq b 6) (setq i 3) (return (g (f 10))))) 
The result of calling p should be 10/63. To make it work, add special declarations wherever necessary:
(defun f (x) (declare (special a b)) (prog (m) (setq m a) (setq a 7) (return (+ m b x)))) (defun g (l) (declare (special a b l)) (h (* b a))) (defun h (i) (declare (special a b l i)) (/ l (f (setq b (setq a i))))) (defun p () (prog (a b i) (declare (special a b i)) (setq a 4) (setq b 6) (setq i 3) (return (g (f 10))))) 
Be careful about the placement of the declarations. It is required that the one in p be inside the prog, since that is where the variables are bound; putting it at the beginning (i.e., before the prog) would do nothing because the prog would create new lexical bindings.
This method is not optimal, since it really doesn't help too much with understanding how the code works (although being able to see which variables are free and which are bound, by looking at the declarations, is very helpful). A better way would be to factor out the variables used among several functions (as long as you are sure that it is used in only those functions) and put them in a let. Doing that is more difficult than using global variables, but it leads to code that is easier to reason about. Of course, if a variable is used in a large number of functions, it might well be a better choice to create a global variable with defvar or defparameter.
Not all LISP 1.5 code is as bad as that example!
Join us next time as we look at the LISP 1.5 library. In the future, I think I'll make some posts talking about getting specific programs running. If you see any errors, please let me know.
submitted by kushcomabemybedtime to lisp [link] [comments]

LCD Arduino project Display Heart Rate

LCD Arduino project brief introduction
Some time ago, I found a heart rate sensor module MAX30100 in shopping online. This module can collect blood oxygen and heart rate data of users, which is also simple and convenient to use.
According to the data, I found that there are libraries of MAX30100 in the Arduino library files. That is to say, if I use the communication between LCD Arduino and MAX30100, I can directly call the Arduino library files without having to rewrite the driver files. This is a good thing, so I bought the module of MAX30100.
I decided to use Arduino to verify the heart rate and blood oxygen collection function of MAX30100. With STONE TFT LCD screen for monitoring blood pressure.
Note: this module by default only with 3.3 V level MCU communications, because it defaults to using IIC pin pull up the resistance of 4.7 K to 1.8 V, so there is no communication with the Arduino by default, if you want to commune with the Arduino and need two 4.7 K of the IIC pin pull-up resistor connected to the VIN pin, these contents will be introduced in the back of the chapter.

Functional assignments

Before starting this project, I thought about some simple features:
• Heart rate data and blood oxygen data were collected
• Heart rate and blood oxygen data are displayed through an LCD screen
These are the only two features, but if we want to implement it, we need to do more thinking:
• What master MCU is used?
• What kind of LCD display?
As we mentioned earlier, we use Arduino for the MCU, but this is an LCD Arduino project, so we need to choose the appropriate LCD display module. I plan to use the LCD display screen with a serial port. I have a STONE STVI070WT-01 displayer here, but if Arduino needs to communicate with it, MAX3232 is needed to do the level conversion.
Then the basic electronic materials are determined as follows:
  1. Arduino Mini Pro development board
  2. MAX30100 heart rate and blood oxygen sensor module
  3. STONE STVI070WT-01 LCD serial port display module
  4. MAX3232 module

Hardware Introduction

MAX30100

The MAX30100 is an integrated pulse oximetry and heart rate monitor sensor solution. It combines two LEDs, a photodetector, optimized optics, and low-noise analog signal processing to detect pulse oximetry and heart-rate signals. The MAX30100 operates from 1.8V and 3.3V power supplies and can be powered down through software with negligible standby current, permitting the power supply to remain connected at all times.

Applications

● Wearable Devices
● Fitness Assistant Devices
● Medical Monitoring Devices

Benefits and Features

1、Complete Pulse Oximeter and Heart-Rate SensorSolution Simplifies Design
• Integrated LEDs, Photo Sensor, and high-Performance Analog Front -End
• Tiny 5.6mm x 2.8mm x 1.2mm 14-Pin OpticallyEnhanced System-in-Package
2、Ultra-Low-Power Operation Increases Battery Life for wearable Devices
• Programmable Sample Rate and LED Current for Power Savings
• Ultra-Low Shutdown Current (0.7µA, typ)
3、Advanced Functionality Improves Measurement Performance
• High SNR Provides Robust Motion Artifact Resilience
• Integrated Ambient Light Cancellation
• High Sample Rate Capability
• Fast Data Output Capability

Detection Principle


https://preview.redd.it/254ou0pq20a51.jpg?width=817&format=pjpg&auto=webp&s=2d3287e1973b328412e14c6e56f74e6f5975153e
Just press your finger against the sensor to estimate pulse oxygen saturation (SpO2) and pulse (equivalent to heartbeat).
The pulse oximeter (oximeter) is a mini-spectrometer that USES the principles of different red cell absorption spectra to analyze the oxygen saturation of the blood. This real-time and rapid measurement method is also widely used in many clinical references.
I will not introduce the MAX30100 too much, because these materials are available on the Internet. Interested friends can look up the information of this heart rate test module on the Internet, and have a deeper understanding of its detection principle.

Introduction to the STVI070WT-01 displayer

In this project, I will use the STONE STVI070WT-01 to display the heart rate and blood oxygen data.
The driver chip has been integrated inside the display screen, and there is software for users to use. Users only need to add buttons, text boxes, and other logic through the designed UI pictures, and then generate configuration files and download them into the display screen to run.
The display of STVI070WT-01 communicates with MCU through the UART RS232 signal, which means that we need to add a MAX3232 chip to convert the RS232 signal into a TTL signal so that we can communicate with Arduino MCU.

https://preview.redd.it/kyyv3hou20a51.jpg?width=749&format=pjpg&auto=webp&s=512b7285eb763e518a85d0b172dabc08b15cab6a
If you are not sure how to use the MAX3232, please refer to the following pictures:

https://preview.redd.it/5laiqsxw20a51.jpg?width=653&format=pjpg&auto=webp&s=126fb57d5171d942046277896e1552995df0ce13
If you think the level conversion is too troublesome, you can choose other types of displayers of STONE Tech, some of which can directly output uart-TTL signal.
The official website has detailed information and introduction:
https://www.stoneitech.com/
If you need video tutorials and tutorials to use, you can also find it on the official website.

https://preview.redd.it/0rkfwxk530a51.jpg?width=867&format=pjpg&auto=webp&s=32803906927fff48bb8fbc1b0a7c073cfe54c5e5

Development steps

Three steps of STONE display screen development:
• Design the display logic and button logic with STONE TOOL software, and download the design file to the display module.
• MCU communicates with the STONE LCD display module through the serial port.
• With the data obtained in step 2, the MCU does other actions.

STONE TOOL software installation

Download the latest version of the STONE TOOL software (currently TOOL2019) from the website, and install it.
After the software is installed, the following interface will be opened:

https://preview.redd.it/evuct2w630a51.jpg?width=848&format=pjpg&auto=webp&s=201d40fdb81e2c4fd229992daf15501f2cb177a0
Click the "File" button in the upper left corner to create a new project, which we will discuss later.

LCD Arduino

Arduino is an open-source electronic prototype platform that is easy to use and easy to use. It includes the hardware part (various development boards that conform to the Arduino specification) and the software part (Arduino IDE and related development kits).
The hardware part (or development board) consists of a microcontroller (MCU), Flash memory (Flash), and a set of universal input/output interfaces (GPIO), which you can think of as a microcomputer motherboard.
The software part is mainly composed of Arduino IDE on PC, related board-level support package (BSP) and rich third-party function library. With the Arduino IDE, you can easily download the BSP associated with your development board and the libraries you need to write your programs.
Arduino is an open-source platform. So far, there have been many models and many derived controllers, including Arduino Uno, Arduino Nano, Arduino Yun and so on. In addition, the Arduino IDE now not only supports the Arduino series development boards but also adds support for popular development boards such as Intel Galileo and NodeMCU by introducing BSP.
Arduino senses the environment through a variety of sensors, controlling lights, motors and other devices to feedback and influence the environment. The microcontroller on the board can be programmed with an Arduino programming language, compiled into binaries, and burned into the microcontroller. Programming for Arduino is implemented with the Arduino programming language (based on Wiring) and the Arduino development environment (based on Processing). Arduino-based projects can contain Arduino only, as well as Arduino and other software running on PC, and they communicate with each other (such as Flash, Processing, MaxMSP).

HMI for Arduino serial display TFT LCD project development environment

The Arduino development environment is the Arduino IDE, which can be downloaded from the Internet.
Log into the official website of Arduino and download the software
https://www.arduino.cc/en/Main/Software?setlang=cn
After installing the Arduino IDE, the following interface will appear when you open the software:

https://preview.redd.it/2ajmkke830a51.jpg?width=567&format=pjpg&auto=webp&s=56dc9dd01c98b231c782ef94d24a9f620c4897b3
The Arduino IDE creates two functions by default: the setup function and the loop function.
There are many Arduino introductions on the Internet. If you don't understand something, you can go to the Internet to find it.

LCD Arduino Project implementation process

hardware connection

To ensure that the next step in writing code goes smoothly, we must first determine the reliability of the hardware connection.
Only four pieces of hardware were used in this project:
  1. Arduino Mini pro-development board
  2. STONE STVI070WT-01 TFT-LCD display screen
  3. MAX30100 heart rate and blood oxygen sensor
  4. MAX3232 (rs232-> TTL)
The Arduino Mini Pro development board and STVI070WT-01 TFT-LCD display screen are connected through UART, which requires level conversion through MAX3232, and then the Arduino Mini Pro development board and MAX30100 module are connected through IIC interface. After thinking clearly, we can draw the following wiring picture:

https://preview.redd.it/w2e5c9ha30a51.jpg?width=769&format=pjpg&auto=webp&s=95129db838d6c358e986c88a4d1348f4783cd0ab
https://preview.redd.it/eom4wiia30a51.jpg?width=1091&format=pjpg&auto=webp&s=ff56c3afaf063d7785a5b85ba283532be0dd896e
Make sure there are no errors in the hardware connection and proceed to the next step.

STONE TFT LCD user interface design

First of all, we need to design a UI display image, which can be designed by PhotoShop or other image design tools. After designing the UI display image, save the image in JPG format.
Open the software STONE TOOL 2019 and create a new project:

https://preview.redd.it/sqjii2mc30a51.jpg?width=1004&format=pjpg&auto=webp&s=12f0a87d6c2ca8decaff241d5a0b50a3a1aece89
https://preview.redd.it/4ta8cdlc30a51.jpg?width=871&format=pjpg&auto=webp&s=b31ac5e612a2c809e29f63974a04ba25bff83788
Remove the image that was loaded by default in the new project, and add the UI image that we designed.
Add the text display component, design the display digit and decimal point, get the storage location of the text display component in the displayer.
The effect is as follows:

https://preview.redd.it/2mfqapoe30a51.jpg?width=1335&format=pjpg&auto=webp&s=aacfa0fde88defacd127ea9d9d27ab006ab618dd
Text display component address:
• Connection sta : 0x0008
• Heart rate : 0x0001
• Blood oxygen : 0x0005
The main contents of the UI interface are as follows:
• Connection status
• Heart rate display
• Blood oxygen showed

Generate configuration file

Once the UI design is complete, the configuration file can be generated and downloaded to the STVI070WT-01 displaye.

First, perform step 1, then insert the USB flash drive into the computer, and the disk symbol will be displayed. Then click "Download to u-disk" to Download the configuration file to the USB flash drive, and then insert the USB flash drive into STVI070WT-01 to complete the upgrade.

MAX30100

MAX30100 communicates via IIC. Its working principle is that the ADC value of heart rate can be obtained through infrared led irradiation. The MAX30100 register can be divided into five categories: state register, FIFO, control register, temperature register, and ID register. The temperature register reads the temperature value of the chip to correct the deviation caused by the temperature. The ID register can read the chip's ID number.

https://preview.redd.it/221fq8vg30a51.jpg?width=848&format=pjpg&auto=webp&s=43e93284ac35cf1944a77d79ff9a2f662e540c7e

MAX30100 is connected with the Arduino Mini Pro development board through the IIC communication interface. Because there are ready-made MAX30100 library files in the Arduino IDE, we can read the heart rate and blood oxygen data without studying the registers of MAX30100.
For those who are interested in exploring the MAX30100 register, see the MAX30100 Datasheet.

Modify the MAX30100 IIC pull-up resistor

It should be noted that the 4.7k pull-up resistance of the IIC pin of MAX30100 module is connected to 1.8v, which is not a problem in theory. However, the communication logic level of the Arduino IIC pin is 5V, so it cannot communicate with Arduino without changing the hardware of the MAX30100 module.Direct communication is possible if the MCU is STM32 or another 3.3v logic level MCU.
Therefore, the following changes need to be made:

https://preview.redd.it/jti57usl30a51.jpg?width=521&format=pjpg&auto=webp&s=c56b1b1a8294d60a8f9e931e411305f68c5c5559
Remove the three 4.7k resistors marked in the picture with an electric soldering iron. Then weld two resistors of 4.7k at the pins of SDA and SCL to VIN, so that we can communicate with Arduino.

Arduino serial display LCD

Open the Arduino IDE and find the following buttons:

https://preview.redd.it/990d3bdp30a51.jpg?width=853&format=pjpg&auto=webp&s=24136c385601b69d5afc67842358b102373277ef
Search for "MAX30100" to find two libraries for MAX30100, then click download and install.

https://preview.redd.it/4n167pbv30a51.jpg?width=933&format=pjpg&auto=webp&s=cef50833667bae3f30ac94f5a48b43795b779845
After the installation, you can find the Demo of MAX30100 in the LIB library folder of LCD Arduino:

https://preview.redd.it/rn05xgvw30a51.jpg?width=911&format=pjpg&auto=webp&s=3709bc7c5be36ebdd14c01cb0b7c1933953425b0
Double-click the file to open it.

https://preview.redd.it/q6fqylky30a51.jpg?width=819&format=pjpg&auto=webp&s=8073917be374a72bef2977b4b11ccb2b56fa944e
This Demo can be directly tested. If the hardware connection is ok, you can download the code compilation into the Arduino development board and see the data of MAX30100 in the serial debugging tool.
The complete code is as follows: /*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016 OXullo Intersecans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
Serial.println("Beat!");
}
void setup()
{
Serial.begin(115200);
Serial.print("Initializing pulse oximeter..");
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
} else {
Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
// pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
Serial.print("Heart rate:");
Serial.print(pox.getHeartRate());
Serial.print("bpm / SpO2:");
Serial.print(pox.getSpO2());
Serial.println("%");
tsLastReport = millis();
}
}
📷
This code is very simple, I believe you can understand it at a glance. I have to say that the modular programming of Arduino is very convenient, and I don't even need to understand how the driver code of Uart and IIC is implemented.
Of course, the above code is an official Demo, and I still need to make some changes to display the data to STONE's displayer.

Display data to the STONE display through Arduino LCD

First, we need to get the address of the component that displays the heart rate and blood oxygen data in STONE's displayer:
In my project, the address is as follows:
Heart rate display component address: 0x0001
Address of blood oxygen display module: 0x0005
Sensor connection status address: 0x0008
If you need to change the display content in the corresponding space, you can change the display content by sending data to the corresponding address of the display screen through the serial port of Arduino.
The modified code is as follows:
/*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016 OXullo Intersecans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
#define Heart_dis_addr 0x01
#define Sop2_dis_addr 0x05
#define connect_sta_addr 0x08
unsigned char heart_rate_send[8]= {0xA5, 0x5A, 0x05, 0x82,\
0x00, Heart_dis_addr, 0x00, 0x00};
unsigned char Sop2_send[8]= {0xA5, 0x5A, 0x05, 0x82, 0x00, \
Sop2_dis_addr, 0x00, 0x00};
unsigned char connect_sta_send[8]={0xA5, 0x5A, 0x05, 0x82, 0x00, \
connect_sta_addr,0x00, 0x00};
// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
// Serial.println("Beat!");
}
void setup()
{
Serial.begin(115200);
// Serial.print("Initializing pulse oximeter..");
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
// Serial.println("FAILED");
// connect_sta_send[7]=0x00;
// Serial.write(connect_sta_send,8);
for(;;);
} else {
connect_sta_send[7]=0x01;
Serial.write(connect_sta_send,8);
// Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
// Serial.print("Heart rate:");
// Serial.print(pox.getHeartRate());
// Serial.print("bpm / SpO2:");
// Serial.print(pox.getSpO2());
// Serial.println("%");
heart_rate_send[7]=(uint32_t)pox.getHeartRate();
Serial.write(heart_rate_send,8);
Sop2_send[7]=pox.getSpO2();
Serial.write(Sop2_send,8);
tsLastReport = millis();
}
}
Compile the code, download it to the Arduino serial display LCD development board, and you're ready to start testing.
We can see that when the fingers leave the MAX30100, the heart rate and blood oxygen display 0. Place your finger on the MAX30100 collector to see your heart rate and blood oxygen levels in real-time.

LCD Arduino project effect can be seen in the following picture:


https://preview.redd.it/k9u0jtg040a51.jpg?width=510&format=pjpg&auto=webp&s=1e9994109a072807a802eb1179b874f727aeff5a
https://preview.redd.it/0ow2lfg040a51.jpg?width=576&format=pjpg&auto=webp&s=b0f5f6ac073894c8b0c033549fce79fac1c90bc3
submitted by Tamesliu to arduino [link] [comments]

Unhandled Exception Error in code

Hey all, I've been learning to program for a few months now and I've been working on a program to manage student data. Here's the code:
#include  #include  #include  #include  #include  using namespace std; class Student { private: char name[20]; string course; int section; int grade; public: void calcgrade(); void getData(); void showData(); }; void Student::calcgrade() { if (grade >= 90) grade = 'A'; else if (grade >= 80) grade = 'B'; else if (grade >= 70) grade = 'C'; else if (grade >= 60) grade = 'D'; else grade = 'F'; } void Student::getData() { cout << "Enter the name of the student: "; cin.ignore(); getline(cin, name); cout << "Enter the course: "; cin >> course; cout << "Enter the section: "; cin >> section; cout << "Enter the grade received: "; cin >> grade; calcgrade(); } void Student::showData() { cout << ".......Student Information......" << endl; cout << "Student Name: " << name << endl; cout << "Course: " << course << endl; cout << "Section: " << section << endl; cout << "Grade: " << grade << endl; cout << endl; } void addData() { Student st; ofstream fout; fout.open("Student.data", ios::binary | ios::out | ios::app); st.getData(); fout.write((char*)& st, sizeof(st)); fout.close(); cout << "Data Successfully Saved to File." << endl; } void displayData() { Student st; ifstream file; file.open("Student.data", ios::in | ios::binary); if (file.is_open()) { while (file.read((char*)& st, sizeof(st))) { st.showData(); } cout << "Finished Reading Data From File." << endl; } else { cout << "Unable to open file" << endl; } file.close(); } void searchData() { Student st; ifstream file; file.open("Student.data", ios::in | ios::binary); string search; cout << "Please enter the first name of a student to search for: "; cin >> search; bool isFound = 0; while (file.read((char*)& st, sizeof(st))) { string temp = " "; getline(file, temp); for (int i = 0; i < search.size(); i++) { if (temp[i] == search[i]) isFound = 1; else { isFound = 0; break; } } if (isFound) { cout << "The name " << search << " was found in the database." << endl; break; } } if (file.read((char*)& st, sizeof(st)) && (!isFound)) { cout << "Name not found." << endl; } file.close(); } void modifyData() { Student st; string stname; bool isFound = 0; int pos; fstream file; file.open("Student.data", ios::in | ios::out | ios::binary); cout << "Enter the name of a student whose data you want to modify: "; cin >> stname; while (file.read((char*)& st, sizeof(st))) { string temp = " "; getline(file, temp); for (int i = 0; i < stname.size(); i++) { if (temp[i] == stname[i]) isFound = 1; else { isFound = 0; break; } } if (isFound) { pos = file.tellg(); cout << "Current Data" << endl; st.showData(); cout << "Modified Data" << endl; st.getData(); file.seekg(pos - sizeof(st)); file.write((char*)& st, sizeof(st)); } } if (file.read((char*)& st, sizeof(st)) && (!isFound)) { cout << "Name not found." << endl; } file.close(); } void deleteData() { Student st; string stname; bool isFound = 0; ifstream file; ofstream fout; file.open("Student.data", ios::in | ios::binary); fout.open("Temporary.data", ios::out | ios::app | ios::binary); cout << "Enter the name of a student whose data you want to delete: "; cin >> stname; while (file.read((char*)& st, sizeof(st))) { string temp = " "; getline(file, temp); for (int i = 0; i < stname.size(); i++) { if (temp[i] == stname[i]) isFound = 1; else { isFound = 0; break; } } if (isFound) { cout << "Bleh" << endl; fout.write((char*)& st, sizeof(st)); } } if (file.read((char*)& st, sizeof(st)) && (!isFound)) { cout << "Name not found." << endl; } fout.close(); file.close(); remove("Student.data"); rename("Temporary.data", "Student.data"); } void printData() { ifstream file; file.open("Student.data", ios::in | ios::binary); if (file.is_open()) { cout << file.rdbuf(); } file.close(); } int main() { int num; do { cout << "...............STUDENT MANAGEMENT SYSTEM..............\n"; cout << "======================================== ==============\n"; cout << "0. Close Program. " << endl; cout << "1. Add Data. " << endl; cout << "2. List Data. " << endl; cout << "3. Modify Data. " << endl; cout << "4. Search For Data. " << endl; cout << "5. Print Data. " << endl; cout << "6. Delete Data. " << endl; cout << "Choose an option: "; cin >> num; if (num == 1) { addData(); } else if (num == 2) { displayData(); } else if (num == 3) { modifyData(); } else if (num == 4) { searchData(); } else if (num == 5) { printData(); } else if (num == 6) { deleteData(); } } while (num > 0); return 0; } 
Ideally, when the program runs, the user chooses an option, with different function calls depending on the number entered. The Add Data option works fine, but when choosing others, such as List Data or Search Data, I run into an error: Unhandled exception thrown: read access violation. _Pnext was 0x10A6A04.
Code in xmemory:
 inline void _Container_base12::_Orphan_all() noexcept { #if _ITERATOR_DEBUG_LEVEL == 2 if (_Myproxy != nullptr) { // proxy allocated, drain it _Lockit _Lock(_LOCK_DEBUG); for (_Iterator_base12** _Pnext = &_Myproxy->_Myfirstiter; *_Pnext != nullptr; *_Pnext = (*_Pnext)->_Mynextiter) { (*_Pnext)->_Myproxy = nullptr; } _Myproxy->_Myfirstiter = nullptr; } 
The error occurs after != nullptr. Because there are no obvious errors in the code, I'd like a little help in picking out what I've done wrong.
submitted by nottooavidprogrammer to cpp_questions [link] [comments]

Differences between LISP 1.5 and Common Lisp, Part 2a

Here is the first part of the second part (I ran out of characters again...) of a series of posts documenting the many differences between LISP 1.5 and Common Lisp. The preceding post can be found here.
In this part we're going to look at LISP 1.5's library of functions.
Of the 146 symbols described in The LISP 1.5 Programmer's Manual, sixty-two have the same names as standard symbols in Common Lisp. These symbols are enumerated here.
The symbols t and nil have been discussed already. The remaining symbols are operators. We can divide them into groups based on how semantics (and syntax) differ between LISP 1.5 and Common Lisp:
  1. Operators that have the same name but have quite different meanings
  2. Operators that have been extended in Common Lisp (e.g. to accept a variable number of arguments), but that otherwise have similar enough meanings
  3. Operators that have remained effectively the same
The third group is the smallest. Some functions differ only in that they have a larger domain in Common Lisp than in LISP 1.5; for example, the length function works on sequences instead of lists only. Such functions are pointed out below. All the items in this list should, given the same input, behave identically in Common Lisp and LISP 1.5. They all also have the same arity.
These are somewhat exceptional items on this list. In LISP 1.5, car and cdr could be used on any object; for atoms, the result was undefined, but there was a result. In Common Lisp, applying car and cdr to anything that is not a cons is an error. Common Lisp does specify that taking the car or cdr of nil results in nil, which was not a feature of LISP 1.5 (it comes from Interlisp).
Common Lisp's equal technically compares more things than the LISP 1.5 function, but of course Common Lisp has many more kinds of things to compare. For lists, symbols, and numbers, Common Lisp's equal is effectively the same as LISP 1.5's equal.
In Common Lisp, expt can return a complex number. LISP 1.5 does not support complex numbers (as a first class type).
As mentioned above, Common Lisp extends length to work on sequences. LISP 1.5's length works only on lists.
It's kind of a technicality that this one makes the list. In terms of functionality, you probably won't have to modify uses of return---in the situations in which it was used in LISP 1.5, it worked the same as it would in Common Lisp. But Common Lisp's definition of return is really hiding a huge difference between the two languages discussed under prog below.
As with length, this function operates on sequences and not only lists.
In Common Lisp, this function is deprecated.
LISP 1.5 defined setq in terms of set, whereas Common Lisp makes setq the primitive operator.
Of the remaining thirty-three, seven are operators that behave differently from the operators of the same name in Common Lisp:
  • apply, eval
The connection between apply and eval has been discussed already. Besides setq and prog or special or common, function parameters were the only way to bind variables in LISP 1.5 (the idea of a value cell was introduced by Maclisp); the manual describes apply as "The part of the interpreter that binds variables" (p. 17).
  • compile
In Common Lisp the compile function takes one or two arguments and returns three values. In LISP 1.5 compile takes only a single argument, a list of function names to compile, and returns that argument. The LISP 1.5 compiler would automatically print a listing of the generated assembly code, in the format understood by the Lisp Assembly Program or LAP. Another difference is that compile in LISP 1.5 would immediately install the compiled definitions in memory (and store a pointer to the routine under the subr or fsubr indicators of the compiled functions).
  • count, uncount
These have nothing to do withss Common Lisp's count. Instead of counting the number of items in a collection satisfying a certain property, count is an interface to the "cons counter". Here's what the manual says about it (p. 34):
The cons counter is a useful device for breaking out of program loops. It automatically causes a trap when a certain number of conses have been performed.
The counter is turned on by executing count[n], where n is an integer. If n conses are performed before the counter is turned off, a trap will occur and an error diagnostic will be given. The counter is turned off by uncount[NIL]. The counter is turned on and reset each time count[n] is executed. The counter can be turned on so as to continue counting from the state it was in when last turned off by executing count[NIL].
This counting mechanism has no real counterpart in Common Lisp.
  • error
In Common Lisp, error is part of the condition system, and accepts a variable number of arguments. In LISP 1.5, it has a single, optional argument, and of course LISP 1.5 had no condition system. It had errorset, which we'll discuss later. In LISP 1.5, executing error would cause an error diagnostic and print its argument if given. While this is fairly similar to Common Lisp's error, I'm putting it in this section since the error handling capabilities of LISP 1.5 are very limited compared to those of Common Lisp (consider that this was one of the only ways to signal an error). Uses of error in LISP 1.5 won't necessarily run in Common Lisp, since LISP 1.5's error accepted any object as an argument, while Common Lisp's error needs designators for a simple-error condition. An easy conversion is to change (error x) into (error "~A" x).
  • map
This function is quite different from Common Lisp's map. The incompatibility is mentioned in Common Lisp: The Language:
In MacLisp, Lisp Machine Lisp, Interlisp, and indeed even Lisp 1.5, the function map has always meant a non-value-returning version. However, standard computer science literature, including in particular the recent wave of papers on "functional programming," have come to use map to mean what in the past Lisp implementations have called mapcar. To simplify things henceforth, Common Lisp follows current usage, and what was formerly called map is named mapl in Common Lisp.
But even mapl isn't the same as map in LISP 1.5, since mapl returns the list it was given and LISP 1.5's map returns nil. Actually there is another, even larger incompatibility that isn't mentioned: The order of the arguments is different. The first argument of LISP 1.5's map was the list to be mapped and the second argument was the function to map over it. (The order was changed in Maclisp, likely because of the extension of the mapping functions to multiple lists.) You can't just change all uses of map to mapl because of this difference. You could define a function like map-1.5,such as
(defun map-1.5 (list function) (mapl function list) nil) 
and replace map with map-1.5 (or just shadow the name map).
  • function
This operator has been discussed earlier in this post.
Common Lisp doesn't need anything like LISP 1.5's function. However, mostly by coincidence, it will tolerate it in many cases; in particular, it works with lambda expressions and with references to global function definitions.
  • search
This function isn't really anything like Common Lisp's search. Here is how it is defined in the manual (p. 63, converted from m-expressions into Common Lisp syntax):
(defun search (x p f u) (cond ((null x) (funcall u x)) ((p x) (funcall f x)) (t (search (cdr x) p f u)))) 
Somewhat confusingly, the manual says that it searches "for an element that has the property p"; one might expect the second branch to test (get x p).
The function is kind of reminiscent of the testr function, used to exemplify LISP 1.5's indefinite scoping in the previous part.
  • special, unspecial
LISP 1.5's special variables are pretty similar to Common Lisp's special variables—but only because all of LISP 1.5's variables are pretty similar to Common Lisp's special variables. The difference between regular LISP 1.5 variables and special variables is that symbols declared special (using this special special special operator) have a value on their property list under the indicator special, which is used by the compiler when no binding exists in the current environment. The interpreter knew nothing of special variables; thus they could be used only in compiled functions. Well, they could be used in any function, but the interpreter wouldn't find the special value. (It appears that this is where the tradition of Lisp dialects having different semantics when compiled versus when interpreted began; eventually Common Lisp would put an end to the confusion.)
You can generally change special into defvar and get away fine. However there isn't a counterpart to unspecial. See also common.
Now come the operators that are essentially the same in LISP 1.5 and in Common Lisp, but have some minor differences.
  • append
The LISP 1.5 function takes only two arguments, while Common Lisp allows any number.
  • cond
In Common Lisp, when no test in a cond form is true, the result of the whole form is nil. In LISP 1.5, an error was signaled, unless the cond was contained within a prog, in which case it would quietly do nothing. Note that the cond must be at the "top level" inside the prog; cond forms at any deeper level will error if no condition holds.
  • gensym
The LISP 1.5 gensym function takes no arguments, while the Common Lisp function does.
  • get
Common Lisp's get takes three arguments, the last of which is a value to return if the symbol does not have the indicator on its property list; in LISP 1.5 get has no such third argument.
  • go
In LISP 1.5 go was allowed in only two contexts: (1) at the top level of a prog; (2) within a cond form at the top level of a prog. Later dialects would loosen this restriction, leading to much more complicated control structures. While progs in LISP 1.5 were somewhat limited, it is at least fairly easy to tell what's going on (e.g. loop conditions). Note that return does not appear to be limited in this way.
  • intern
In Common Lisp, intern can take a second argument specifying in what package the symbol is to be interned, but LISP 1.5 does not have packages. Additionally, the required argument to intern is a string in Common Lisp; LISP 1.5 doesn't really have strings, and so intern instead wants a pointer to a list of full words (of packed BCD characters; the print names of symbols were stored in this way).
  • list
In Common Lisp, list can take any number of arguments, including zero, but in LISP 1.5 it seems that it must be given at least one argument.
  • load
In LISP 1.5, load can't be given a filespec as an argument, for many reason. Actually, it can't be given anything as an argument; its purpose is simply to hand control over to the loader. The loader "expects octal correction cards, 704 row binary cards, and a transfer card." If you have the source code that would be compiled into the material to be loaded, then you can just put it in another file and use Common Lisp's load to load it in. But if you don't have the source code, then you're out of luck.
  • mapcon, maplist
The differences between Common Lisp and LISP 1.5 regarding these functions are similar to those for map given above. Both of these functions returned nil in LISP 1.5, and they took the list to be mapped as their first argument and the function to map as their second argument. A major incompatibility to note is that maplist in LISP 1.5 did what mapcar in Common Lisp does; Common Lisp's maplist is different.
  • member
In LISP 1.5, member takes none of the fancy keyword arguments that Common Lisp's member does, and returns only a truth value, not the tail of the list.
  • nconc
In LISP 1.5, this function took only two arguments; in Common Lisp, it takes any number.
  • prin1, print, terpri
In Common Lisp, these functions take an optional argument specifying an output stream to which they will send their output, but in LISP 1.5 prin1 and print take just one argument, and terpri takes no arguments.
  • prog
In LISP 1.5, the list of program variables was just that: a list of variables. No initial values could be provided as they can in Common Lisp; all the program variables started out bound to nil. Note that the program variables are just like any other variables in LISP 1.5 and have indefinite scope.
In the late '70s and early '80s, the maintainers of Maclisp and Lisp Machine Lisp wanted to add "naming" abilities to prog. You could say something like
(prog outer () ... (prog () (return ... outer))) 
and the return would jump not just out of the inner prog, but also out of the outer one. However, they ran into a problem with integrating a named prog with parts of the language that were based on prog. For example, they could add a special case to dotimes to handle an atomic first argument, since regular dotimes forms had a list as their first argument. But Maclisp's do had two forms: the older (introduced in 1969) form
(do atom initial step-form end-test body...) 
and the newer form, which was identical to Common Lisp's do. The older form was equivalent to
(do ((atom intitial step-form)) (end-test) body...) 
Since the older form was still supported, they couldn't add a special case for an atomic first argument because that was the normal case of the older kind of do. They ended up not adding named prog, owing to these kinds of difficulties.
However, during the discussion of how to make named prog work, Kent Pitman sent a message that contained the following text:
I now present my feelings on this issue of how DO/PROG could be done in order this haggling, part of which I think comes out of the fact that these return tags are tied up in PROG-ness and so on ... Suppose you had the following primitives in Lisp: (PROG-BODY ...) which evaluated all non-atomic stuff. Atoms were GO-tags. Returns () if you fall off the end. RETURN does not work from this form. (PROG-RETURN-POINT form name) name is not evaluated. Form is evaluated and if a RETURN-FROM specifying name (or just a RETURN) were executed, control would pass to here. Returns the value of form if form returns normally or the value returned from it if a RETURN or RETURN-FROM is executed. [Note: this is not a [*]CATCH because it is lexical in nature and optimized out by the compiler. Also, a distinction between NAMED-PROG-RETURN-POINT and UNNAMED-PROG-RETURN-POINT might be desirable – extrapolate for yourself how this would change things – I'll just present the basic idea here.] (ITERATE bindings test form1 form2 ...) like DO is now but doesn't allow return or goto. All forms are evaluated. GO does not work to get to any form in the iteration body. So then we could just say that the definitions for PROG and DO might be (ignore for now old-DO's – they could, of course, be worked in if people really wanted them but they have nothing to do with this argument) ... (PROG [  ]  . ) => (PROG-RETURN-POINT (LET  (PROG-BODY . )) [  ]) (DO [  ]   . ) => (PROG-RETURN-POINT (ITERATE   (PROG-BODY . )) [  ]) Other interesting combinations could be formed by those interested in them. If these lower-level primitives were made available to the user, he needn't feel tied to one of PROG/DO – he can assemble an operator with the functionality he really wants. 
Two years later, Pitman would join the team developing the Common Lisp language. For a little while, incorporating named prog was discussed, which eventually led to the splitting of prog in quite a similar way to Pitman's proposal. Now prog is a macro, simply combining the three primitive operators let, block, and tagbody. The concept of the tagbody primitive in its current form appears to have been introduced in this message, which is a writeup by David Moon of an idea due to Alan Bawden. In the message he says
The name could be GO-BODY, meaning a body with GOs and tags in it, or PROG-BODY, meaning just the inside part of a PROG, or WITH-GO, meaning something inside of which GO may be used. I don't care; suggestions anyone?
Guy Steele, in his proposed evaluator for Common Lisp, called the primitive tagbody, which stuck. It is a little bit more logical than go-body, since go is just an operator and allowed anywhere in Common Lisp; the only special thing about tagbody is that atoms in its body are treated as tags.
  • prog2
In LISP 1.5, prog2 was really just a function that took two arguments and returned the result of the evaluation of the second one. The purpose of it was to avoid having to write (prog () ...) everywhere when all you want to do is call two functions. In later dialects, progn would be introduced and the "implicit progn" feature would remove the need for prog2 used in this way. But prog2 stuck around and was generalized to a special operator that evaluated any number of forms, while holding on to the result of the second one. Programmers developed the (prog2 nil ...) idiom to save the result of the first of several forms; later prog1 was introduced, making the idiom obsolete. Nowadays, prog1 and prog2 are used typically for rather special purposes.
Regardless, in LISP 1.5 prog2 was machine-coded subroutine that was equivalent to the following function definition in Common Lisp:
(defun prog2 (one two) two) 
  • read
The read function in LISP 1.5 did not take any arguments; Common Lisp's read takes four. In LISP 1.5, read read either from "SYSPIT" or from the punched carded reader. It seems that SYSPIT stood for "SYStem Paper (maybe Punched) Input Tape", and that it designated a punched tape reader; alternatively, it might designate a magnetic tape reader, but the manual makes reference to punched cards. But more on input and output later.
  • remprop
The only difference between LISP 1.5's remprop and Common Lisp's remprop is that the value of LISP 1.5's remprop is always nil.
  • setq
In Common Lisp, setq takes an arbitrary even number of arguments, representing pairs of symbols and values to assign to the variables named by the symbols. In LISP 1.5, setq takes only two arguments.
  • sublis
LISP 1.5's sublis and subst do not take the keyword arguments that Common Lisp's sublis and subst take.
  • trace, untrace
In Common Lisp, trace and untrace are operators that take any number of arguments and trace the functions named by them. In LISP 1.5, both trace and untrace take a single argument, which is a list of the functions to trace.

Functions not in Common Lisp

We turn now to the symbols described in the LISP 1.5 Programmer's Manual that don't appear in Common Lisp. Let's get the easiest case out of the way first: Here are all the operators in LISP 1.5 that have a corresponding operator in Common Lisp, with notes about differences in functionality where appropriate.
  • add1, sub1
These functions are the same as Common Lisp's 1+ and 1- in every way, down to the type genericism.
  • conc
This is just Common Lisp's append, or LISP 1.5's append extended to more than two arguments.
  • copy
Common Lisp's copy-list function does the same thing.
  • difference
This corresponds to -, although difference takes only two arguments.
  • divide
This function takes two arguments and is basically a consing version of Common Lisp's floor:
(divide x y) = (values-list (floor x y)) 
  • digit
This function takes a single argument, and is like Common Lisp's digit-char-p except that the radix isn't variable, and it returns a true or false value only (and not the weight of the digit).
  • efface
This function deletes the first appearance of an item from a list. A call like (efface item list) is equivalent to the Common Lisp code (delete item list :count 1).
  • greaterp, lessp
These correspond to Common Lisp's > and <, although greaterp and lessp take only two arguments.
As a historical note, the names greaterp and lessp survived in Maclisp and Lisp Machine Lisp. Both of those languages had also > and <, which were used for the two-argument case; Common Lisp favored genericism and went with > and < only. However, a vestige of the old predicates still remains, in the lexicographic ordering functions: char-lessp, char-greaterp, string-lessp, string-greaterp.
  • minus
This function takes a single argument and returns its negation; it is equivalent to the one-argument case of Common Lisp's -.
  • leftshift
This function is the same as ash in Common Lisp; it takes two arguments, m and n, and returns m×2n. Thus if the second argument is negative, the shift is to the right instead of to the left.
  • liter
This function is identical in essence to Common Lisp's alpha-char-p, though more precisely it's closer to upper-case-p; LISP 1.5 was used on computers that made no provision for lowercase characters.
  • pair
This is equivalent to the normal, two-argument case of Common Lisp's pairlis.
  • plus
This function takes any number of arguments and returns their sum; its Common Lisp counterpart is +.
  • quotient
This function is equivalent to Common Lisp's /, except that quotient takes only two arguments.
  • recip
This function is equivalent to the one-argument case of Common Lisp's /.
  • remainder
This function is equivalent to Common Lisp's rem.
  • times
This function takes any number of arguments and returns their product; its Common Lisp counterpart is *.
Part 2b will be posted in a few hours probably.
submitted by kushcomabemybedtime to lisp [link] [comments]

AssemblyScript Introduction (Part 1)

AssemblyScript Introduction (Part 1)
This article is written by the CoinEx Chain lab. CoinEx Chain is the world’s first public chain exclusively designed for DEX, and will also include a Smart Chain supporting smart contracts and a Privacy Chain protecting users’ privacy.
AssemblyScript is not a brand new programming language. Its syntax is a strict subset of the popular TypeScript language syntax. It is tailored and customized specifically for WebAssembly (hereinafter referred to as Wasm). The following diagram shows the grammatical relationship of JavaScript, TypeScript and AssemblyScript.

https://preview.redd.it/kpyvptf6r1551.png?width=1352&format=png&auto=webp&s=95759713118f3c21d83f86f25c6cda8846ba6a68
This article aims to discuss how AssemblyScript programs are compiled into Wasm modules. To understand the basic syntax and usage of AssemblyScript language, you can refer to the AssemblyScript tutorial. In our previous Wasm articles, we have discussed the Wasm binary format and instruction set in detail. We already know that the Wasm binary module organizes content by section, and there are currently 12 different types of sections. Let’s briefly review the content of these sections:
  • The custom section (ID is 0) stores auxiliary information such as function names. Such information does not affect the execution semantics of Wasm, and there won’t be any problem even if it is completely discarded.
  • The type section (ID is 1) stores function types (also called function signature) and block types.
  • The import section (ID is 2) stores the import information. There are four types of items that can be imported: functions, table, memory, and global variables.
  • The function section (ID is 3) stores the function signature information defined internally. This is an index table, which stores the index of the signature of the internally defined function in the type section.
  • Table section (ID is 4) stores internally defined table information. Restricted by the Wasm specification, the module can import or define only one table.
  • The memory section (ID is 5) stores internally defined memory information. Restricted by the Wasm specification, the module can import or define only one block of memory.
  • The global section (ID is 6) stores internally defined global variable information.
  • The export section (ID is 7) stores export information. Like the import section, there are four types of items that can be exported: functions, table, memory, and global variables.
  • The Start section (ID is 8) stores the start function index.
  • The element section (ID is 9) stores the initialization data of the table.
  • The code section (ID is 10) stores the local variable information and bytecode of the internally defined functions.
  • The data section (ID is 11) stores initialization data of the memory.
Let's take a look at how AssemblyScript programs are compiled into Wasm modules, or to be more specific, how the key information needed to run the program is stored in various sections. We will use the wasm2wat and wasm-objdump command line tools provided by WABT to observe the binary modules generated by the AssemblyScript compiler.

Type Section

All function signatures in the program will be collected by the compiler and put into the type section of the binary module. Here is an example:
declare function f1(x: i32): i32; declare function f2(x: f32, y: f32): f32; declare function f3(x: f32, y: f32): f32; export function f4(a: i32, b: i32): i32 { return f1(b) + f1(b); } export function f5(a: f32, b: f32, c: f32): f32 { return f2(a, b) + f3(b, c); } 
In the above example three external functions are declared and two internal functions defined. Note that we need to mark the internal functions as exported (or turn off compiler optimization); otherwise they may be optimized out by the compiler. Compile the above program using AssemblyScript compiler, and then use the wasm-objdump command to convert the generated binary module to text format. The result is shown as below:
(module (type (;0;) (func (param f32 f32) (result f32))) (type (;1;) (func (param i32) (result i32))) (type (;2;) (func (param i32 i32) (result i32))) (type (;3;) (func (param f32 f32 f32) (result f32))) (import "index" "f1" (func (;0;) (type 1))) (import "index" "f2" (func (;1;) (type 0))) (import "index" "f3" (func (;2;) (type 0))) (func (;3;) (type 2) (; unrelated code ;) ) (func (;4;) (type 3) (; unrelated code ;) ) ;; unrelated code ) 
Since the signatures of f2() and f3() are the same, there are a total of four function signatures. As you can see, the compiler puts the signatures of f2() and f3() first, followed by the signatures of f1(), f4(), and f5().

Import & Export Section

As mentioned earlier, the module can import or export four kind of items: functions, table, memory, and global variables. According to the above example, if compiler optimization is not taken into consideration, the functions in AssemblyScript will be compiled into Wasm functions. Global variables also take on a similar correspondence, which we will see immediately. The following example shows how to declare external functions and global variables:
declare function add(a: i32, b: i32): i32; @external("sub2") declare function sub(a: i32, b: i32): i32; @external("math", "mul2") declare function mul(a: i32, b: i32): i32; @external("math", "pi") declare const pi: f32; export function main(): void { add(1, 2); sub(1, 2); mul(1, pi as i32); } 
The AssemblyScript compiler will take the file name of the compiled program as the external module name and the function or global variable name as the member name by default. Yet you can also use the @external annotation to explicitly specify the member name alone, or specify both the external module name and the member name. Table and memory are special, and we will discuss them in detail later. The AssemblyScript compiler provides --importTable and --importMemory options. If these two options are specified during compilation, table and memory import items (env.table and env.memory) will be generated in the import section of the module. Save the above example as index.ts and then compile it with these two options. Below is the compilation result (which has been converted to text format):
(module (type (;0;) (func (param i32 i32) (result i32))) (type (;1;) (func)) (import "index" "add" (func (;0;) (type 0))) (import "index" "sub2" (func (;1;) (type 0))) (import "math" "mul2" (func (;2;) (type 0))) (import "math" "pi" (global (;0;) f32)) (import "env" "memory" (memory (;0;) 0)) (import "env" "table" (table (;0;) 1 funcref)) (func (;3;) (type 1) (; unrelated code ;) ) ;; unrelated code ) 
The functions and global variables marked as exported in the AssemblyScript language will be put by the compiler in the export section of the module; the memory is exported by default, but can be turned off by the --noExportMemory option; the table is not exported by default, but can be turned on by the --exportTable option. Let's look at another example:
export const pi: f32 = 3.14; export function add(a: i32, b: i32): i32 { return a + b; } export function sub(a: i32, b: i32): i32 { return a - b; } export function mul(a: i32, b: i32): i32 { return a * b; } 
Compile the above example with the --exportTable option, and here is the compiled module (which has been converted to text format):
(module (type (;0;) (func (param i32 i32) (result i32))) (func (;0;) (type 0) (; unrelated code ;) ) (func (;1;) (type 0) (; unrelated code ;) ) (func (;2;) (type 0) (; unrelated code ;) ) (table (;0;) 1 funcref) (memory (;0;) 0) (global (;0;) f32 (f32.const 0x1.91eb86p+1 (;=3.14;))) (export "memory" (memory 0)) (export "table" (table 0)) (export "pi" (global 0)) (export "add" (func 0)) (export "sub" (func 1)) (export "mul" (func 2)) (elem (;0;) (i32.const 1) func) ) 

Function & Code Section

As mentioned above, the function information defined in the module is divided into two sections: the signature information of the function is in the type section, and the local variable information and bytecode of the function are in the code section. If optimization is turned off completely, then there should be a direct correspondence between the functions defined in the AssemblyScript language and the functions in the Wasm module. That is to say, each function defined in the language will produce an entry in the function section and code section of the module. Let's look at an example:
function add(a: i32, b: i32): i32 { return a + b; } function sub(a: i32, b: i32): i32 { return a - b; } function mul(a: i32, b: i32): i32 { return a * b; } export function main(): void { add(1, 2); sub(1, 2); mul(1, 2); } 
When compiler optimization is turned on, such correspondence may be broken when it comes to non-exported internal functions. For better observation, we can specify the -O0 option to turn off optimization during compilation. The following is the compiled module (which has been converted to text format):
(module (type (;0;) (func (param i32 i32) (result i32))) (type (;1;) (func)) (func (;0;) (type 0) (; unrelated code ;) ) (func (;1;) (type 0) (; unrelated code ;) ) (func (;2;) (type 0) (; unrelated code ;) ) (func (;3;) (type 1) (; unrelated code ;) ) (table (;0;) 1 funcref) (memory (;0;) 0) (export "memory" (memory 0)) (export "main" (func 3)) (elem (;0;) (i32.const 1) func) ) 
It is more intuitive to observe the function section and code section with the wasm-objdumpcommand. The following is the output result (irrelevant content is omitted):
... Section Details: Type[2]: - type[0] (i32, i32) -> i32 - type[1] () -> nil Function[4]: - func[0] sig=0 - func[1] sig=0 - func[2] sig=0 - func[3] sig=1 
Table[1]: ... Memory[1]: ... Export[2]: ... Elem[1]: ... Code[4]: - func[0] size=7 - func[1] size=7 - func[2] size=7 - func[3] size=23
Custom: ...

Table & Element Section

The table in Wasm are mainly for implementing function pointers in C/C++ and other languages. Both AssemblyScript language and JavaScript/TypeScript language support first-class functions, which is also achieved through the Wasm table. Here is an example:
type op = (a: i32, b: i32) => i32; function add(a: i32, b: i32): i32 { return a + b; } function sub(a: i32, b: i32): i32 { return a - b; } function mul(a: i32, b: i32): i32 { return a * b; } export function calc(a: i32, b: i32, op: (x:i32, y:i32) => i32): i32 { return op(a, b); } export function main(a: i32, b: i32): void { calc(a, b, add); calc(a, b, sub); calc(a, b, mul); } 
The following is the compiled module (which has been converted to text format). Please pay attention to the table section and element section. We will talk more about Wasm table in subsequent articles.
(module (type (;0;) (func (param i32 i32) (result i32))) (type (;1;) (func (param i32 i32))) (type (;2;) (func (param i32 i32 i32) (result i32))) (func (;0;) (type 2) (param i32 i32 i32) (result i32) (call_indirect (type 0) (local.get 0) (local.get 1) (block (result i32) ;; label = @1 (global.set 0 (i32.const 2)) (local.get 2) ) ) ) (func (;1;) (type 0) (; unrelated code ;) ) (func (;2;) (type 0) (; unrelated code ;) ) (func (;3;) (type 0) (; unrelated code ;) ) (func (;4;) (type 1) (param i32 i32) (drop (call 0 (local.get 0) (local.get 1) (i32.const 1))) (drop (call 0 (local.get 0) (local.get 1) (i32.const 2))) (drop (call 0 (local.get 0) (local.get 1) (i32.const 3))) ) (table (;0;) 4 funcref) (memory (;0;) 0) (global (;0;) (mut i32) (i32.const 0)) (export "memory" (memory 0)) (export "calc" (func 0)) (export "main" (func 4)) (elem (;0;) (i32.const 1) func 1 2 3) ) 

Memory & Data Section

We will discuss AssemblyScript memory management in detail subsequent articles. Let's first look at a simple example:
declare function printChar(c: i32): void; export function main(): void { const str = "Hello, World!\n"; for (let i = 0; i < str.length; i++) { printChar(str.charCodeAt(i)); } } 
UTF-16 encoding is adopted in AssemblyScript strings, and string literals are placed in the data section. The following is the compiled module (with compiler optimization on). Please pay attention to the memory section and data section:
(module (type (;0;) (func)) (type (;1;) (func (param i32))) (import "index" "printChar" (func (;0;) (type 1))) (func (;1;) (type 0) (; unrelated code ;) ) (memory (;0;) 1) (export "memory" (memory 0)) (export "main" (func 1)) (data (;0;) (i32.const 1024) "\1c\00\00\00\01\00\00\00\01\00\00\00\1c\00\00\00H\00e\00l\00l\00o\00,\00 \00W\00o\00r\00l\00d\00!\00\0a") ) 
The AssemblyScript compiler also provides two options, respectively --initialMemory and --maximumMemory, allowing us to explicitly control the initial and maximum number of pages of memory. We are not going into details here.

Global Section

As can be seen from the above, the AssemblyScript language uses Wasm global variables to implement global variables in the language. When the compiler optimization is turned off completely, each global variable defined in the AssemblyScript language will occupy an item in the global section of the generated module. Let's look at an example:
var g1: i32 = 100; export var g2: i32 = 200; export var g3: i64 = 300; export const pi: f32 = 3.14; export function main(): i32 { return g1; } 
The following is the compiled module (with compiler optimization off). As you can see, all the four global variables appear in the global section:
(module (type (;0;) (func (result i32))) (func (;0;) (type 0) (result i32) (global.get 0)) (table (;0;) 1 funcref) (memory (;0;) 0) (global (;0;) (mut i32) (i32.const 100)) (global (;1;) (mut i32) (i32.const 200)) (global (;2;) (mut i64) (i64.const 300)) (global (;3;) f32 (f32.const 0x1.91eb86p+1 (;=3.14;))) (export "memory" (memory 0)) (export "g2" (global 1)) (export "g3" (global 2)) (export "pi" (global 3)) (export "main" (func 0)) (elem (;0;) (i32.const 1) func) ) 

Start Section

The start section is to specify a start function index. The specified function will be automatically invoked after the module is instantiated, so as to perform some additional initialization. Here is an example:
declare function max(a: i32, b: i32): i32; declare function printI32(n: i32): void; var x = max(123, 456); export function main(): void { printI32(x); } 
In this example two external functions are declared and a global variable x and a function main() are defined. The AssemblyScript compiler needs to put the initialization logic of the global variable x into a function and the index of the function in the initial section. Please see the compiled module below (the index of the start function is 4):
(module (type (;0;) (func)) (type (;1;) (func (param i32))) (type (;2;) (func (param i32 i32) (result i32))) (import "index" "max" (func (;0;) (type 2))) (import "index" "printI32" (func (;1;) (type 1))) (func (;2;) (type 0) (global.set 0 (call 0 (i32.const 123) (i32.const 456))) ) (func (;3;) (type 0) (call 1 (global.get 0))) (func (;4;) (type 0) (call 2)) (table (;0;) 1 funcref) (memory (;0;) 0) (global (;0;) (mut i32) (i32.const 0)) (export "memory" (memory 0)) (export "main" (func 3)) (start 4) (elem (;0;) (i32.const 1) func) ) 

Custom Section

As mentioned above, the custom section mainly stores additional information, such as function names and other debugging information. The Wasm specification only defines one standard "name" custom section, which is specifically designed to store name information. By default, the AssemblyScript compiler does not generate a "name" custom section, but it can be enabled through the --debug option. Let's add the --debug option to recompile the above example, and observe the generated binary module through the wasm-objdump command (some irrelevant content is omitted):
... Section Details: Type[3]: - type[0] () -> nil - type[1] (i32) -> nil - type[2] (i32, i32) -> i32 Import[2]: - func[0] sig=2  <- index.max - func[1] sig=1  <- index.printI32 Function[3]: - func[2] sig=0  - func[3] sig=0  - func[4] sig=0 <~start> Table[1]: ... Memory[1]: ... Global[1]: - global[0] i32 mutable=1 - init i32=0 Export[2]: ... Start: - start function: 4 Elem[1]: ... Code[3]: - func[2] size=12  - func[3] size=6  - func[4] size=4 <~start> Custom: - name: "name" - func[0]  - func[1]  - func[2]  - func[3]  - func[4] <~start> Custom: - name: "sourceMappingURL" 

Summary

In this article, we have discussed how AssemblyScript programs are compiled into Wasm modules, focusing on what information is stored in the various sections of the Wasm module. Next time we will discuss how the AssemblyScript language uses the Wasm instruction set to implement various grammatical elements.
submitted by coinexchain to u/coinexchain [link] [comments]

LCD Arduino + STONE HMI + Display Heart Rate

LCD Arduino project brief introduction

Some time ago, I found a heart rate sensor module MAX30100 in shopping online. This module can collect blood oxygen and heart rate data of users, which is also simple and convenient to use.
According to the data, I found that there are libraries of MAX30100 in the Arduino library files. That is to say, if I use the communication between LCD Arduino and MAX30100, I can directly call the Arduino library files without having to rewrite the driver files. This is a good thing, so I bought the module of MAX30100.
I decided to use Arduino to verify the heart rate and blood oxygen collection function of MAX30100. With STONE TFT LCD screen for monitoring blood pressure.

https://preview.redd.it/fbm2i8e32o251.jpg?width=328&format=pjpg&auto=webp&s=20329c7187f3fdf628106e923453fdf588fe69ab
Note: this module by default only with 3.3 V level MCU communications, because it defaults to using IIC pin pull up the resistance of 4.7 K to 1.8 V, so there is no communication with the Arduino by default, if you want to commune with the Arduino and need two 4.7 K of the IIC pin pull-up resistor connected to the VIN pin, these contents will be introduced in the back of the chapter.

Functional assignments

Before starting this project, I thought about some simple features:
• Heart rate data and blood oxygen data were collected
• Heart rate and blood oxygen data are displayed through an LCD screen
These are the only two features, but if we want to implement it, we need to do more thinking:
• What master MCU is used?
• What kind of LCD display?
As we mentioned earlier, we use Arduino for the MCU, but this is an LCD Arduino project, so we need to choose the appropriate LCD display module. I plan to use the LCD display screen with a serial port. I have a STONE STVI070WT-01 displayer here, but if Arduino needs to communicate with it, MAX3232 is needed to do the level conversion.
Then the basic electronic materials are determined as follows:
  1. Arduino Mini Pro development board
  2. MAX30100 heart rate and blood oxygen sensor module
  3. STONE STVI070WT-01 LCD serial port display module
  4. MAX3232 module

Hardware Introduction

MAX30100

The MAX30100 is an integrated pulse oximetry and heart rate monitor sensor solution. It combines two LEDs, a photodetector, optimized optics, and low-noise analog signal processing to detect pulse oximetry and heart-rate signals. The MAX30100 operates from 1.8V and 3.3V power supplies and can be powered down through software with negligible standby current, permitting the power supply to remain connected at all times.

Applications

● Wearable Devices
● Fitness Assistant Devices
● Medical Monitoring Devices

Benefits and Features

1、Complete Pulse Oximeter and Heart-Rate SensorSolution Simplifies Design
• Integrated LEDs, Photo Sensor, and high-Performance Analog Front -End
• Tiny 5.6mm x 2.8mm x 1.2mm 14-Pin OpticallyEnhanced System-in-Package
2、Ultra-Low-Power Operation Increases Battery Life for wearable Devices
• Programmable Sample Rate and LED Current for Power Savings
• Ultra-Low Shutdown Current (0.7µA, typ)
3、Advanced Functionality Improves Measurement Performance
• High SNR Provides Robust Motion Artifact Resilience
• Integrated Ambient Light Cancellation
• High Sample Rate Capability
• Fast Data Output Capability

Detection Principle


https://preview.redd.it/kgu72wk52o251.jpg?width=817&format=pjpg&auto=webp&s=0b44a5b4b476c50c1cbd311f048313777d06cabb
Just press your finger against the sensor to estimate pulse oxygen saturation (SpO2) and pulse (equivalent to heartbeat).
The pulse oximeter (oximeter) is a mini-spectrometer that USES the principles of different red cell absorption spectra to analyze the oxygen saturation of the blood. This real-time and rapid measurement method is also widely used in many clinical references.
I will not introduce the MAX30100 too much, because these materials are available on the Internet. Interested friends can look up the information of this heart rate test module on the Internet, and have a deeper understanding of its detection principle.

Introduction to the STVI070WT-01 displayer

In this project, I will use the STONE STVI070WT-01 to display the heart rate and blood oxygen data.
The driver chip has been integrated inside the display screen, and there is software for users to use. Users only need to add buttons, text boxes and other logic through the designed UI pictures, and then generate configuration files and download them into the display screen to run.
The display of STVI070WT-01 communicates with MCU through the UART RS232 signal, which means that we need to add a MAX3232 chip to convert the RS232 signal into a TTL signal so that we can communicate with Arduino MCU.

https://preview.redd.it/oacuof082o251.jpg?width=749&format=pjpg&auto=webp&s=d1427adf34689c8a433a2af71c494f7698e4baf8
If you are not sure how to use the MAX3232, please refer to the following pictures:

https://preview.redd.it/u39qtog92o251.jpg?width=653&format=pjpg&auto=webp&s=04cf458bcebcd27ba09f36903e20e7ebe1aaa6f9
If you think the level conversion is too troublesome, you can choose other types of displayers of STONE Tech, some of which can directly output uart-TTL signal.
The official website has detailed information and introduction:
https://www.stoneitech.com/
If you need video tutorials and tutorials to use, you can also find it on the official website.

Development steps

Three steps of STONE display screen development:
• Design the display logic and button logic with STONE TOOL software, and download the design file to the display module.
• MCU communicates with the STONE LCD display module through the serial port.
• With the data obtained in step 2, the MCU does other actions.

STONE TOOL software installation

Download the latest version of the STONE TOOL software (currently TOOL2019) from the website, and install it.
After the software is installed, the following interface will be opened:

https://preview.redd.it/ryc7qjkd2o251.jpg?width=848&format=pjpg&auto=webp&s=72f674b6a2b653562a31735f103aecf2df16199d
Click the "File" button in the upper left corner to create a new project, which we will discuss later.

LCD Arduino

Arduino is an open-source electronic prototype platform that is easy to use and easy to use. It includes the hardware part (various development boards that conform to the Arduino specification) and the software part (Arduino IDE and related development kits).
The hardware part (or development board) consists of a microcontroller (MCU), Flash memory (Flash), and a set of universal input/output interfaces (GPIO), which you can think of as a microcomputer motherboard.
The software part is mainly composed of Arduino IDE on PC, related board-level support package (BSP) and rich third-party function library. With the Arduino IDE, you can easily download the BSP associated with your development board and the libraries you need to write your programs.
Arduino is an open-source platform. So far, there have been many models and many derived controllers, including Arduino Uno, Arduino Nano, Arduino Yun and so on. In addition, the Arduino IDE now not only supports the Arduino series development boards but also adds support for popular development boards such as Intel Galileo and NodeMCU by introducing BSP.
Arduino senses the environment through a variety of sensors, controlling lights, motors and other devices to feedback and influence the environment. The microcontroller on the board can be programmed with an Arduino programming language, compiled into binaries, and burned into the microcontroller. Programming for Arduino is implemented with the Arduino programming language (based on Wiring) and the Arduino development environment (based on Processing). Arduino-based projects can contain Arduino only, as well as Arduino and other software running on PC, and they communicate with each other (such as Flash, Processing, MaxMSP).

HMI for Arduino serial display TFT LCD project development environment

The Arduino development environment is the Arduino IDE, which can be downloaded from the Internet.
Log into the official website of Arduino and download the software
https://www.arduino.cc/en/Main/Software?setlang=cn
After installing the Arduino IDE, the following interface will appear when you open the software:

https://preview.redd.it/2fcfnrkg2o251.jpg?width=567&format=pjpg&auto=webp&s=9b6664d15fb99c31ee91c49be56d9eb9e17e04de
The Arduino IDE creates two functions by default: the setup function and the loop function.
There are many Arduino introductions on the Internet. If you don't understand something, you can go to the Internet to find it.

LCD Arduino Project implementation process

hardware connection

To ensure that the next step in writing code goes smoothly, we must first determine the reliability of the hardware connection.
Only four pieces of hardware were used in this project:
  1. Arduino Mini pro development board
  2. STONE STVI070WT-01 tft-lcd display screen
  3. MAX30100 heart rate and blood oxygen sensor
  4. MAX3232 (rs232-> TTL)
The Arduino Mini Pro development board and STVI070WT tft-lcd display screen are connected through UART, which requires level conversion through MAX3232, and then the Arduino Mini Pro development board and MAX30100 module are connected through IIC interface.After thinking clearly, we can draw the following wiring picture:

https://preview.redd.it/xkpv7bxi2o251.jpg?width=769&format=pjpg&auto=webp&s=b3658c7c455ba97c6f3a961e34ed020059201b8b

https://preview.redd.it/zobnoatl2o251.jpg?width=1091&format=pjpg&auto=webp&s=2263d1d5a6d208b6e9c1110334971a1d34ed742c
Make sure there are no errors in the hardware connection and proceed to the next step.

STONE TFT LCD user interface design

First of all, we need to design a UI display image, which can be designed by PhotoShop or other image design tools. After designing the UI display image, save the image in JPG format.
Open the software STONE TOOL 2019 and create a new project:

https://preview.redd.it/ou27uc4o2o251.jpg?width=1004&format=pjpg&auto=webp&s=e559c55a3d4fb014fc35dd94bca4d7a52938c87f

https://preview.redd.it/j7mkexnp2o251.jpg?width=871&format=pjpg&auto=webp&s=eb80865fd5efe45a5b015790f0fd0c02f07ca069
Remove the image that was loaded by default in the new project, and add the UI image that we designed.
Add the text display component, design the display digit and decimal point, get the storage location of the text display component in the displayer.
The effect is as follows:

https://preview.redd.it/y7333lor2o251.jpg?width=1335&format=pjpg&auto=webp&s=501576a9d57e92b1435bc25406612a0f758038a5
Text display component address:
• Connection sta : 0x0008
• Heart rate : 0x0001
• Blood oxygen : 0x0005
The main contents of the UI interface are as follows:
• Connection status
• Heart rate display
• Blood oxygen showed

Generate configuration file

Once the UI design is complete, the configuration file can be generated and downloaded to the STVI070WT-01 displaye.

https://preview.redd.it/c94grplt2o251.jpg?width=606&format=pjpg&auto=webp&s=ab0a7306791341599fbb874c63638f1066e5f1d9
First, perform step 1, then insert the USB flash drive into the computer, and the disk symbol will be displayed. Then click "Download to u-disk" to Download the configuration file to the USB flash drive, and then insert the USB flash drive into STVI070WT-01 to complete the upgrade.

MAX30100

MAX30100 communicates via IIC. Its working principle is that the ADC value of heart rate can be obtained through infrared led irradiation. The MAX30100 register can be divided into five categories: state register, FIFO, control register, temperature register, and ID register. The temperature register reads the temperature value of the chip to correct the deviation caused by the temperature. The ID register can read the chip's ID number.

https://preview.redd.it/dfomjb1z2o251.jpg?width=848&format=pjpg&auto=webp&s=911b174be98448c64002c1a24fa6528ce56ae3b7
MAX30100 is connected with the Arduino Mini Pro development board through the IIC communication interface. Because there are ready-made MAX30100 library files in the Arduino IDE, we can read the heart rate and blood oxygen data without studying the registers of MAX30100.
For those who are interested in exploring the MAX30100 register, see the MAX30100 Datasheet.

Modify the MAX30100 IIC pull-up resistor

It should be noted that the 4.7k pull-up resistance of the IIC pin of MAX30100 module is connected to 1.8v, which is not a problem in theory. However, the communication logic level of the Arduino IIC pin is 5V, so it cannot communicate with Arduino without changing the hardware of the MAX30100 module.Direct communication is possible if the MCU is STM32 or another 3.3v logic level MCU.
Therefore, the following changes need to be made:

https://preview.redd.it/l5cimq013o251.jpg?width=521&format=pjpg&auto=webp&s=9fc29401ed402b9bf623c4f8e474336c8050fae8
Remove the three 4.7k resistors marked in the picture with an electric soldering iron. Then weld two resistors of 4.7k at the pins of SDA and SCL to VIN, so that we can communicate with Arduino.

Arduino serial display LCD

Open the Arduino IDE and find the following buttons:

https://preview.redd.it/w9mska373o251.jpg?width=853&format=pjpg&auto=webp&s=fe0ee068c64ce109028dab4f5898335ded02c82e
Search for "MAX30100" to find two libraries for MAX30100, then click download and install.

https://preview.redd.it/pqlihp9a3o251.jpg?width=933&format=pjpg&auto=webp&s=493965c54d1cc755a0dd2ac98ad6100cf7c93948
After the installation, you can find the Demo of MAX30100 in the LIB library folder of LCD Arduino:

https://preview.redd.it/srk2g83c3o251.jpg?width=911&format=pjpg&auto=webp&s=da696328a0a198c0ee41a17a7811024d36a153ea
Double-click the file to open it.

https://preview.redd.it/lc8z3gtd3o251.jpg?width=819&format=pjpg&auto=webp&s=bbac5eb529e4279792c899d738ebdb0fa9263c54
This Demo can be directly tested. If the hardware connection is ok, you can download the code compilation into the Arduibo development board and see the data of MAX30100 in the serial debugging tool.
The complete code is as follows:
/*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016 OXullo Intersecans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
Serial.println("Beat!");
}
void setup()
{
Serial.begin(115200);
Serial.print("Initializing pulse oximeter..");
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
Serial.println("FAILED");
for(;;);
} else {
Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
// pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
Serial.print("Heart rate:");
Serial.print(pox.getHeartRate());
Serial.print("bpm / SpO2:");
Serial.print(pox.getSpO2());
Serial.println("%");
tsLastReport = millis();
}
}


https://preview.redd.it/nyuyl4zl3o251.jpg?width=552&format=pjpg&auto=webp&s=58e05bc67a250de6f7b24060290d8a0703624e30
This code is very simple, I believe you can understand it at a glance. I have to say that the modular programming of Arduino is very convenient, and I don't even need to understand how the driver code of Uart and IIC is implemented.
Of course, the above code is an official Demo, and I still need to make some changes to display the data to STONE's displayer.

Display data to the STONE display through Arduino LCD

First, we need to get the address of the component that displays the heart rate and blood oxygen data in STONE's displayer:
In my project, the address is as follows:
Heart rate display component address: 0x0001
Address of blood oxygen display module: 0x0005
Sensor connection status address: 0x0008
If you need to change the display content in the corresponding space, you can change the display content by sending data to the corresponding address of the display screen through the serial port of Arduino.
The modified code is as follows:
/*
Arduino-MAX30100 oximetry / heart rate integrated sensor library
Copyright (C) 2016 OXullo Intersecans
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see .
*/
#include
#include "MAX30100_PulseOximeter.h"
#define REPORTING_PERIOD_MS 1000
#define Heart_dis_addr 0x01
#define Sop2_dis_addr 0x05
#define connect_sta_addr 0x08
unsigned char heart_rate_send[8]= {0xA5, 0x5A, 0x05, 0x82,\
0x00, Heart_dis_addr, 0x00, 0x00};
unsigned char Sop2_send[8]= {0xA5, 0x5A, 0x05, 0x82, 0x00, \
Sop2_dis_addr, 0x00, 0x00};
unsigned char connect_sta_send[8]={0xA5, 0x5A, 0x05, 0x82, 0x00, \
connect_sta_addr,0x00, 0x00};
// PulseOximeter is the higher level interface to the sensor
// it offers:
// * beat detection reporting
// * heart rate calculation
// * SpO2 (oxidation level) calculation
PulseOximeter pox;
uint32_t tsLastReport = 0;
// Callback (registered below) fired when a pulse is detected
void onBeatDetected()
{
// Serial.println("Beat!");
}
void setup()
{
Serial.begin(115200);
// Serial.print("Initializing pulse oximeter..");
// Initialize the PulseOximeter instance
// Failures are generally due to an improper I2C wiring, missing power supply
// or wrong target chip
if (!pox.begin()) {
// Serial.println("FAILED");
// connect_sta_send[7]=0x00;
// Serial.write(connect_sta_send,8);
for(;;);
} else {
connect_sta_send[7]=0x01;
Serial.write(connect_sta_send,8);
// Serial.println("SUCCESS");
}
// The default current for the IR LED is 50mA and it could be changed
// by uncommenting the following line. Check MAX30100_Registers.h for all the
// available options.
pox.setIRLedCurrent(MAX30100_LED_CURR_7_6MA);
// Register a callback for the beat detection
pox.setOnBeatDetectedCallback(onBeatDetected);
}
void loop()
{
// Make sure to call update as fast as possible
pox.update();
// Asynchronously dump heart rate and oxidation levels to the serial
// For both, a value of 0 means "invalid"
if (millis() - tsLastReport > REPORTING_PERIOD_MS) {
// Serial.print("Heart rate:");
// Serial.print(pox.getHeartRate());
// Serial.print("bpm / SpO2:");
// Serial.print(pox.getSpO2());
// Serial.println("%");
heart_rate_send[7]=(uint32_t)pox.getHeartRate();
Serial.write(heart_rate_send,8);
Sop2_send[7]=pox.getSpO2();
Serial.write(Sop2_send,8);
tsLastReport = millis();
}
}

Compile the code, download it to the Arduino serial display LCD development board, and you're ready to start testing.
We can see that when the fingers leave the MAX30100, the heart rate and blood oxygen display 0. Place your finger on the MAX30100 collector to see your heart rate and blood oxygen levels in real-time.

LCD Arduino project effect can be seen in the following picture:


https://preview.redd.it/lf120a5s3o251.jpg?width=510&format=pjpg&auto=webp&s=d705a9e10bac1758afc554036a31748c5f73d255
submitted by woodkiki to ArduinoProjects [link] [comments]

Binary options trading for dummies step by step. C++ : Print char array in reverse using recursion C program Convert Integer to Binary Binary Options - When to Enter Trades - YouTube Decimal To Binary using Stack  Code Tutorial C Programming - Array Searching Binary search tree - Implementation in C/C++ - YouTube How to print out a number in binary format using C/C++ ... C++ Program To Convert String / Word into Binary

Es klingt wie Sie versuchen, zu konvertieren, ein single char binary, in diesem Fall ist relativ einfach, und es heißt, Sie brauchen nicht einen Zeiger (das würde keinen Sinn machen), Sie brauchen nur die Verschiebung durch die bits und prüfen, ob es 1 ist (UND mit 1). Blick auf Salvatore zweite snippet. Können Sie uns zeigen, ein Beispiel oder zwei von spezifischen ein-und Ausgängen ... Print formatted data to stdout. Writes the C string pointed by format to the standard output . If ... as argument, but performs the proper conversion to a char value (or a wchar_t) before formatting it for output. Note: Yellow rows indicate specifiers and sub-specifiers introduced by C99. See <cinttypes> for the specifiers for extended types.... (additional arguments) Depending on the format ... I can print with printf as a hex or octal number. Is there a format tag to print as binary, or arbitrary base? I am running gcc. printf("%d %x %o\n", 10, 10, 10); //prints "10 A 12\n" print("%... Serial.print("Hello world.") gives "Hello world." An optional second parameter specifies the base (format) to use; permitted values are BIN(binary, or base 2) , OCT(octal, or base 8) , DEC(decimal, or base 10) , HEX(hexadecimal, or base 16) . additional arguments − Depending on the format string, the function may expect a sequence of additional arguments, each containing one value to be inserted instead of each %-tag specified in the format parameter (if any). There should be the same number of these arguments as the number of %-tags that expect a value. Return Value. If successful, the total number of characters written is returned. str − This is the pointer to an array of char elements where the resulting C string is stored. format − This is the String that contains the text to be written to buffer. It can optionally contain embedded format tags that are replaced by the values specified in subsequent additional arguments and formatted as requested. Format tags prototype: %[flags][width][.precision][length]specifier ... Gdb print unsigned char array Collection. Viewing NSData contents in Xcode - Stack Overflow #109608. C tour Unix #109609 . IA32 Linux Memory Layout Stack Heap Data Text not drawn to scale ... #109610. C tour Unix #109611. Gdb print variable binary options #109612. Cannot inspect the content of STL containers in debugger · Issue ... #109613. X Window System Internals #109614. Structured Data ... If you want to print an integer in octal or hexadecimal you'd use o for octal, or x for hexadecimal. If you want capital letters (A instead of a when printing out decimal 10) then you can use X. Conversion specifiers for floating point numbers. Displaying floating point numbers has a ton of different options, best shown in a table: Although ANSI C does not have this mechanism, it is possible to use itoa() as a shortcut: char buffer [33]; itoa (i,buffer,2); printf ("binary: %s\n",buffer); Here's the origin: itoa in cplusplus reference. It is non-standard C, but K&R mentioned the implementation in the C book, so it should be quite common. It should be in stdlib.h. Su código es muy vaga y no comprensible, pero puede proporcionarle una alternativa. En primer lugar, si usted quiere temp para ir a través d...

[index] [29546] [2126] [14301] [27515] [13785] [17285] [16750] [11092] [12114] [8804]

Binary options trading for dummies step by step.

See complete series on data structures here: http://www.youtube.com/playlist?list=PL2_aWCzGMAwI3W_JlcBbtYTwiQSsOTa6P In this lesson, we have implemented bina... Subscribe for more! The trick to entering trades is predicting, not following. You must watch for warning signals, and then capitalize the opportunity when a... How to print in binary - Duration: 18:35. CodeVault 481 views. 18:35. C PROGRAMMING - DECIMAL TO BINARY CONVERSION - Duration: 15:06. Sundeep Saradhi Kanthety 40,770 views. 15:06. Linux File ... Binary options brokers provide tools such as comprehensive guides, market news, streaming news feeds, videos and training programs. Account managers can help educate traders on the subject and ... Print binary of a decimal number using recursion - Duration: 14:09. Data Structure by Saurabh Shukla Sir 12,178 views. 14:09. Iterative Postorder traversal of binary tree using one stack ... In this video, I will show you how to convert an integer number to binary format string and display it using C/C++ NOTE: This approach assumes positive numbe... Count occurrences of a number in a sorted array with duplicates using Binary Search - Duration: 12:25. mycodeschool 182,449 views. 12:25. ... C PROGRAMMING - INSERTION OF AN ... C Program for character to binary conversion using bitwise operator in one line in Linux - Duration: 6 ... C++ Program to Print ASCII value of Character - Duration: 1:51. Computer World 14,330 ... In this video i will show you how to print a char array (or char pointer) in reverse using recursion. Email: [email protected] If you have a intro...

http://binary-optiontrade.sourrelansa.gq